9
0
mirror of https://github.com/HibiscusMC/HMCCosmetics.git synced 2025-12-19 15:09:19 +00:00

Compare commits

...

191 Commits

Author SHA1 Message Date
LoJoSho
17abd0c8cc feat: Improvements to emote block checking 2023-03-11 20:48:09 -06:00
LoJoSho
a907cd51b9 feat: Add CMI vanish support 2023-03-11 20:07:01 -06:00
LoJoSho
9f6c7db8fd fix: kicking while interacting in emote/wardrobe #76 2023-03-11 19:20:35 -06:00
LoJoSho
2ba83d8cc5 fix: default color being white 2023-03-10 16:06:51 -06:00
LoJoSho
40bf0e173e version bump (2.2.5-DEV) 2023-03-10 16:06:46 -06:00
LoJoSho
a757292b4b version bump (2.2.4) 2023-03-09 19:14:33 -06:00
LoJoSho
b41d466546 fix: action menu not using debug method 2023-03-09 19:09:42 -06:00
LoJoSho
135fdc94d4 fix: sound debug was wrong level 2023-03-09 19:08:21 -06:00
LoJoSho
d0092a2ffe clean: refactor spelling mistake in isBackpackSpawned 2023-03-02 19:19:45 -06:00
LoJoSho
acf31009d5 feat: backpack improvements 2023-03-02 19:19:08 -06:00
LoJoSho
981c6155e7 feat: add all to unapply command 2023-03-01 10:45:06 -06:00
LoJoSho
2ecc86fc7b fix: same issue as before but with cosmetic wardrobe flag 2023-03-01 10:27:27 -06:00
LoJoSho
2682428354 fix: worldguard flag hiding cosmetics when on allow 2023-03-01 10:21:40 -06:00
LoJoSho
df8ad26684 fix: Flying with elytra and teleporting with backpack causing NPE 2023-03-01 10:14:05 -06:00
LoJoSho
1f714c0153 -1 in wardrobe static radius now returns true 2023-03-01 10:09:18 -06:00
LoJoSho
0bfadad222 Reload IA on change option (Legacy IA hook option) 2023-03-01 10:02:27 -06:00
LoJoSho
a1c719fc50 version bump (2.2.4-DEV) 2023-03-01 10:02:05 -06:00
Craftinators
fe9812cd69 clean: suppress warnings 2023-03-01 08:56:49 -05:00
Craftinators
b9699b27c7 fix: spelling errors 2023-03-01 00:52:13 -05:00
Craftinators
2c5ddb542e clean: remove unused import 2023-03-01 00:44:27 -05:00
Craftinators
461642d64b clean: make Type abstract 2023-03-01 00:44:00 -05:00
Craftinators
37a8a2379d clean: add @NotNull & remove import 2023-02-28 22:25:13 -05:00
LoJoSho
e698392e40 Merge pull request #74 from Craftinators/remapped
`Action` Abstraction
2023-02-28 18:54:02 -06:00
Craftinators
e1357b265f clean: use final 2023-02-28 14:50:16 -05:00
Craftinators
a5475b0268 clean: prefer not to use var 2023-02-28 14:50:03 -05:00
Craftinators
60dba9efa6 fix: use parseFloat instead of valueOf 2023-02-28 14:41:46 -05:00
Craftinators
e2d3391070 clean: reduce nesting 2023-02-28 14:40:58 -05:00
Craftinators
aed34ec28d clean: reduce nesting 2023-02-28 14:35:08 -05:00
Craftinators
ae6d88ab56 clean: make Action abstract 2023-02-28 14:34:03 -05:00
LoJoSho
35be7283e9 Merge pull request #72 from Craftinators/remapped
`CosmeticType` Abstraction
2023-02-28 09:32:30 -06:00
Craftinators
224fcb83d9 clean: config to local 2023-02-28 01:03:11 -05:00
Craftinators
98934536be clean: make Cosmetic abstract 2023-02-28 01:02:52 -05:00
LoJoSho
5ac3712e56 Merge pull request #71 from Craftinators/remapped
Database structure changes
2023-02-27 21:57:40 -06:00
Craftinators
2d2d4e6d44 clean: remove TODO 2023-02-27 22:55:33 -05:00
Craftinators
4b1921b754 clean: try-with-resource to SuppressWarnings 2023-02-27 22:55:12 -05:00
Craftinators
8ca1d44375 clean: add error message 2023-02-27 15:36:50 -05:00
Craftinators
23c82cc6ed fix: additional null checks 2023-02-27 15:34:42 -05:00
Craftinators
2bf5280827 fix: reorder null checks 2023-02-27 15:29:50 -05:00
Craftinators
475a1e0ef1 fix: add Class.forName(...) back 2023-02-27 13:06:23 -05:00
Craftinators
ef4d53eb85 fix: throw error if file isn't created 2023-02-27 12:57:12 -05:00
Craftinators
97da4f7809 feat: add SQLData class 2023-02-27 12:53:51 -05:00
Craftinators
1622dac67f clean: cleanup openConnection() 2023-02-27 12:26:43 -05:00
Craftinators
fce1ec5042 refactor: use try-with-resources 2023-02-27 12:23:30 -05:00
Craftinators
060bcc95e1 clean: reorganize MySQLData 2023-02-27 12:20:26 -05:00
Craftinators
5aca80609a feat: make Data abstract 2023-02-27 12:11:09 -05:00
LoJoSho
7c1da21026 Refactoring and Misc changes in UserWardrobeManager 2023-02-25 10:48:39 -06:00
LoJoSho
52329a6de5 Move wardrobe lists to singleton list 2023-02-25 10:34:23 -06:00
LoJoSho
8cdef228e3 Add HMCColor to the internal hook system 2023-02-25 10:27:31 -06:00
LoJoSho
432d6d837a check if user has cosmetic permissions on wardrobe leave 2023-02-25 09:43:19 -06:00
LoJoSho
f42e8b2298 Refactor custom Armorstands and add HMcParticleCloud Entity 2023-02-25 09:39:27 -06:00
LoJoSho
107f5b9215 Merge remote-tracking branch 'origin/remapped' into remapped 2023-02-24 20:31:50 -06:00
LoJoSho
d303fcc45b Merge pull request #70 from Craftinators/remapped
clean: use preferred method
2023-02-24 20:31:31 -06:00
Craftinators
147be9ab7c clean: use preferred method 2023-02-24 21:22:25 -05:00
LoJoSho
7f91f9dbad set default database to SQLite 2023-02-24 20:09:07 -06:00
LoJoSho
63e538511b Merge pull request #69 from Craftinators/remapped
Major consistency changes
2023-02-24 19:48:40 -06:00
Craftinators
d0c8abc38c clean: add annotations 2023-02-24 17:51:48 -05:00
Craftinators
97a28b9e0c clean: remove unused imports 2023-02-24 17:47:21 -05:00
Craftinators
b5ae6e65a1 clean: annotation & variable modifier changes 2023-02-24 17:46:39 -05:00
Craftinators
0c7e740d7a clean: annotation & variable modifier changes 2023-02-24 16:46:23 -05:00
Craftinators
1b7462becc clean: several annotation & naming changes 2023-02-24 13:33:45 -05:00
Craftinators
d508ecd4c0 clean: cosmetic annotation changes 2023-02-24 12:21:53 -05:00
Craftinators
601d6f8a53 fix: break once "-s" flag found 2023-02-24 12:11:22 -05:00
Craftinators
44be4eceb8 clean: comment delete 2023-02-24 12:02:28 -05:00
Craftinators
8bebd57169 fix: event annotation changes 2023-02-24 12:00:14 -05:00
LoJoSho
8f426cef31 version bump (2.2.3) 2023-02-24 10:19:52 -06:00
LoJoSho
abce477f0d add cosmetic playEmote command 2023-02-24 10:19:39 -06:00
LoJoSho
985e797f83 remove annoying space 2023-02-24 09:03:20 -06:00
LoJoSho
8bc84cbdd2 Fix balloon teleport fix not checking if player has balloon 2023-02-24 09:02:16 -06:00
LoJoSho
894e4eef26 update default with correct dye menu name 2023-02-21 17:08:27 -06:00
LoJoSho
5995dabf6f Fix clicking in emote kicking players 2023-02-21 17:05:02 -06:00
LoJoSho
ed647b7e5d Fix for invalid player on emote command 2023-02-21 10:20:42 -06:00
LoJoSho
e378732d44 Fixed backpack model engine in wardrobe 2023-02-20 19:06:25 -06:00
LoJoSho
74eb5dd85a version bump (2.2.2) 2023-02-20 18:48:27 -06:00
LoJoSho
c9ba396c33 remove debug messages 2023-02-20 18:47:52 -06:00
LoJoSho
3967ac4fa5 rename viewer in wardrobe manager 2023-02-20 18:47:25 -06:00
LoJoSho
b1a35df7b5 condense if statements 2023-02-20 18:45:52 -06:00
LoJoSho
0e1c9b3f7e Backpack no longer equipped on fly or swim 2023-02-20 18:41:11 -06:00
LoJoSho
0238ac8fc4 Merge pull request #60 from HibiscusMC/modelengine_backpack
Model Engine Backpacks
2023-02-20 14:17:13 -06:00
LoJoSho
4d6baf0b0c offset backpack for ME backpack 2023-02-20 14:16:40 -06:00
LoJoSho
157fab6309 Merge branch 'remapped' into modelengine_backpack 2023-02-20 14:11:46 -06:00
lucian929
0a488a6791 Add Explorer Backpack Cosmetic 2023-02-17 10:38:56 -05:00
LoJoSho
1c9989e64a readd paper repo 2023-02-16 21:23:45 -06:00
LoJoSho
fb8dcf53e3 Merge branch 'remapped' into modelengine_backpack 2023-02-16 14:50:03 -06:00
LoJoSho
17179cbe35 version bump (2.2.1) 2023-02-16 14:44:54 -06:00
LoJoSho
f589696d19 update paper userdev 2023-02-16 14:43:28 -06:00
LoJoSho
68e87cba6f Merge pull request #61 from HibiscusMC/papi_fix
Fix for PAPI in menus
2023-02-15 17:00:21 -06:00
LoJoSho
63a0bdd0d5 Fix for PAPI in menus 2023-02-15 16:58:47 -06:00
LoJoSho
a01f35c53d Model Engine Backpacks 2023-02-15 16:46:03 -06:00
LoJoSho
a607f2dcbd Merge pull request #59 from HibiscusMC/tweaks
make dye menu slots configurable
2023-02-15 11:00:23 -06:00
Boy
7a9a002e25 make dye menu slots configurable 2023-02-15 12:56:32 +01:00
LoJoSho
fd50cd058a Merge pull request #58 from HibiscusMC/fix_looty
add missing hook initializer for Looty
2023-02-13 13:55:05 -06:00
Boy
970ca8227b add missing hook initializer 2023-02-13 19:04:10 +01:00
LoJoSho
e7fd3ac288 Merge pull request #57 from HibiscusMC/emotes
HMCC Emotes with PlayerAnimator
2023-02-12 13:12:51 -06:00
lucian929
51214964c4 Update default files 2023-02-12 12:58:57 -05:00
LoJoSho
4d4be789ae Merge remote-tracking branch 'origin/emotes' into emotes 2023-02-12 10:56:05 -06:00
LoJoSho
f2b276a2ef Premium + Super Vanish hook 2023-02-12 10:55:54 -06:00
LoJoSho
cf54f2b487 Premium + Super Vanish hook 2023-02-12 10:53:04 -06:00
LoJoSho
bae13c2e3c Create emote folder 2023-02-12 10:40:06 -06:00
LoJoSho
004f9ebef5 Fix rogue wardrobe runnable 2023-02-11 19:48:39 -06:00
LoJoSho
ad956259d0 move event cancel check 2023-02-11 16:13:34 -06:00
LoJoSho
65cebc3154 stop players picking items in wardrobe 2023-02-11 16:05:17 -06:00
LoJoSho
fb79293902 version bump (2.2.0) 2023-02-11 10:19:03 -06:00
LoJoSho
b49cebdec8 command improvements + /cosmetic emote playerName 2023-02-10 16:34:40 -06:00
LoJoSho
00cc3eef2c improve command handling and add permissions 2023-02-10 16:28:42 -06:00
LoJoSho
42bae598a6 offhand switch cancel 2023-02-10 16:10:06 -06:00
LoJoSho
b182e46b28 update api to 1.17 2023-02-10 16:03:15 -06:00
LoJoSho
6b6b0e385e fixed armor showing in emotes 2023-02-10 16:01:11 -06:00
LoJoSho
db60046701 More checks and does not save invisibility from emote 2023-02-10 11:30:41 -06:00
LoJoSho
300e2cffba Emote settings and messages 2023-02-10 10:49:57 -06:00
LoJoSho
d5983d8834 Made player stand still + fixed other players viewing nothing 2023-02-10 09:28:44 -06:00
LoJoSho
9e07f728e1 it works 2023-02-09 13:32:28 -06:00
LoJoSho
dcd38d86c5 latest changes 2023-02-08 17:14:03 -06:00
LoJoSho
d39110af6c emo work 2023-02-08 15:28:04 -06:00
LoJoSho
0f6fa3db8a reimplement dependencies that got missing in merge 2023-02-07 15:55:15 -06:00
LoJoSho
5aef04dee0 Complete overhaul of hooks 2023-02-07 15:54:21 -06:00
LoJoSho
a096f6c684 Merge remote-tracking branch 'origin/remapped' into remapped 2023-02-07 15:34:50 -06:00
LoJoSho
89825659a6 more refactoring 2023-02-07 15:04:17 -06:00
LoJoSho
6ba078dcc4 removed toggle method (unused) 2023-02-07 15:02:27 -06:00
LoJoSho
2e32b8d9d5 move wardrobe to a manager 2023-02-07 14:55:54 -06:00
LoJoSho
941f57af35 Merge pull request #53 from MineInAbyss/mia
LootyHook
2023-02-06 15:30:11 -06:00
LoJoSho
bdb52c0a32 Merge remote-tracking branch 'origin/remapped' into remapped 2023-02-06 14:54:17 -06:00
LoJoSho
a7170e09cf Add force-permission-join option 2023-02-06 14:53:52 -06:00
LoJoSho
8456d6a7ae Fixed balloons applied in wardrobe not having leashes 2023-02-06 14:28:34 -06:00
LoJoSho
08b28bc254 Exiting wardrobe balloon fixes 2023-02-06 14:04:17 -06:00
LoJoSho
c27a9ab2ad Internal wardrobe rework 2023-02-06 13:48:29 -06:00
LoJoSho
2bf618d8d3 ItemFlag rework 2023-02-06 13:46:51 -06:00
LoJoSho
6eb7c9243d Better locked lore handling 2023-02-06 13:11:06 -06:00
LoJoSho
c2b4fade42 Merge pull request #56 from HibiscusMC/defaultmenu
getDefaultMenu method
2023-02-06 10:44:32 -06:00
Boy
382eed9982 requested changes 2023-02-06 17:42:15 +01:00
Boy
498370cc8e replace old methods 2023-02-06 17:23:21 +01:00
Boy
fef5769e31 getDefaultMenu method 2023-02-06 14:17:18 +01:00
Boy
4aa1f9451d tweak oraxen hook for nullchecks 2023-02-06 00:03:01 +01:00
Boy
c7730429de improve looty hook check 2023-02-06 00:03:01 +01:00
Boy
73ccddf628 add softdepend 2023-02-06 00:03:01 +01:00
Boy
26b5472924 add looty support 2023-02-06 00:03:01 +01:00
LoJoSho
5ecfb08412 Refactor entities into managers 2023-02-05 12:28:37 -06:00
LoJoSho
8b223228ce Or statement should be And 2023-02-05 10:40:17 -06:00
LoJoSho
eb03acd959 version bump (2.1.3-SNAPSHOT) 2023-02-04 18:15:28 -06:00
LoJoSho
8e5b3d098c placeholder current causing npe 2023-02-04 18:02:29 -06:00
LoJoSho
a869120b62 misspells 2023-02-04 17:51:03 -06:00
LoJoSho
614892500c Version bump (2.1.2) 2023-02-03 13:16:38 -06:00
LoJoSho
872282f77a Fix publishing 2023-02-03 13:16:26 -06:00
LoJoSho
c0483bfefe Action Menu can override target menu permission with "-o" 2023-02-03 12:35:12 -06:00
LoJoSho
aecd40ba5a Hidden reason now saved in database 2023-02-03 12:19:34 -06:00
LoJoSho
c3db45cfc4 update checker more in align with HMCWraps 2023-02-02 22:26:30 -06:00
LoJoSho
99bc0a0756 Add color to apply command 2023-02-02 21:30:07 -06:00
LoJoSho
e9afd6deb8 Add ability to silent messages in command with -s 2023-02-02 21:25:29 -06:00
lucian929
0770ac456d Delete publish.yml 2023-02-02 17:44:16 -05:00
lucian929
327d602491 Fix repository link 2023-02-02 22:33:19 +00:00
LoJoSho
65f162c89c Update publish.yml 2023-02-02 15:51:24 -06:00
LoJoSho
e96d1f505e Update publish.yml 2023-02-02 15:48:08 -06:00
LoJoSho
2af1deb4c1 Update publish.yml 2023-02-02 15:42:59 -06:00
LoJoSho
d740989a01 add ia hook comment 2023-02-02 15:42:28 -06:00
LoJoSho
fdc0004b75 Repo workflow 2023-02-02 15:23:05 -06:00
LoJoSho
a1ac0a83e1 Merge remote-tracking branch 'origin/remapped' into remapped 2023-02-02 14:55:52 -06:00
LoJoSho
f51ac5969f Improve balloon handling through teleports 2023-02-02 14:52:52 -06:00
LoJoSho
3255f744a7 Add new color handling (Thanks Boy!) 2023-02-02 14:45:48 -06:00
lucian929
dfa5e85dcb Add description for dye-menu key in config 2023-02-02 08:14:58 -05:00
LoJoSho
e30451e972 check if user is created on potion effect event 2023-02-01 18:01:30 -06:00
LoJoSho
500b8ca0ce Condensed IA hook if statement 2023-02-01 16:45:38 -06:00
LoJoSho
c52718da58 Merge remote-tracking branch 'origin/remapped' into remapped 2023-02-01 16:28:38 -06:00
LoJoSho
1290750028 version bump (2.1.1) 2023-02-01 16:28:19 -06:00
LoJoSho
57d5e02275 Add more hidden reasons & show, hide, and toggle actions 2023-02-01 15:51:06 -06:00
LoJoSho
645fd25b82 Fixed ModelEngine being used when not present 2023-02-01 15:27:30 -06:00
LoJoSho
4b1c15f46f Fix ItemAdder reloaded HMCC dozens of times 2023-02-01 15:15:22 -06:00
lucian929
b96ae68f24 Merge pull request #47 from HibiscusMC/fix_dyeing
add dyeing support for potions and maps
2023-01-29 12:21:51 -05:00
Boy
3e5f698dbd revert slots 2023-01-29 18:20:56 +01:00
Boy
88632dce3f add dyeing support for potions and maps 2023-01-29 18:10:22 +01:00
LoJoSho
30f25b4a92 Rename license to license.md 2023-01-28 18:49:00 -06:00
LoJoSho
a385b341f7 Create license 2023-01-28 18:48:02 -06:00
lucian929
66c5fd86c5 Update default configurations for 2.1.0 2023-01-27 17:47:40 -05:00
LoJoSho
ff4f2b6ede moved NMS detection to info 2023-01-27 12:05:52 -06:00
LoJoSho
80eb333b39 fixed offhand item not immidently apply 2023-01-27 10:02:46 -06:00
LoJoSho
8b2b771a9b Fixes offhand cosmetics not appearing if applied via menus 2023-01-26 18:15:20 -06:00
LoJoSho
7873b3fe04 removed certain debug messages 2023-01-26 18:01:46 -06:00
LoJoSho
9854e77bf5 Ballons item now dye correctly 2023-01-26 16:24:21 -06:00
LoJoSho
cad78636d0 Version bump (2.1.0) 2023-01-25 17:10:27 -06:00
LoJoSho
14d256feed Add 1.17 NMS Support 2023-01-25 17:08:09 -06:00
LoJoSho
53163feb60 Add ability for lock names and lore #45 2023-01-24 19:23:03 -06:00
LoJoSho
caf168d29d Invisibility now hides cosmetics 2023-01-24 18:31:21 -06:00
LoJoSho
2a7686e6b7 particle fix 2023-01-24 18:17:00 -06:00
LoJoSho
5309c37902 Add particle action 2023-01-22 19:04:42 -06:00
LoJoSho
ea1b87c128 dyable balloons if no parts selected 2023-01-21 18:12:57 -06:00
LoJoSho
9d92ed0dda Add dyable parts to balloons 2023-01-21 18:06:25 -06:00
LoJoSho
e24d5697e7 Fixed issue with windows packet not preserving held item 2023-01-21 10:41:40 -06:00
LoJoSho
8c59b27302 Add color for bossbar in config 2023-01-20 20:03:52 -06:00
LoJoSho
df3544726d Add 1.18.2 Support 2023-01-20 17:31:25 -06:00
LoJoSho
27af0a6085 Add Equip and Unequip actions 2023-01-20 17:10:17 -06:00
LoJoSho
1db96c38d9 Add hidden reason to internal code 2023-01-20 17:03:44 -06:00
LoJoSho
d9b92d5336 Add sound action #43 2023-01-20 16:24:11 -06:00
LoJoSho
0905071dd2 Balloon rework for items as balloons 2023-01-20 16:08:28 -06:00
120 changed files with 4139 additions and 1066 deletions

1
.gitignore vendored
View File

@@ -23,7 +23,6 @@ atlassian-ide-plugin.xml
*.ctxt
# Package Files #
*.jar
*.war
*.nar
*.ear

View File

@@ -2,14 +2,13 @@ import net.minecrell.pluginyml.bukkit.BukkitPluginDescription
plugins {
id("java")
id("maven-publish")
id("com.github.johnrengelman.shadow") version "7.1.2"
id("xyz.jpenilla.run-paper") version "2.0.0"
id("net.minecrell.plugin-yml.bukkit") version "0.5.2"
}
group = "com.hibiscusmc"
version = "2.0.3"
version = "2.2.5-DEV"
allprojects {
apply(plugin = "java")
@@ -54,37 +53,50 @@ allprojects {
// UpdateChecker
maven("https://hub.jeff-media.com/nexus/repository/jeff-media-public/")
// ParticleHelper
maven("https://repo.bytecode.space/repository/maven-public/")
// PlayerAnimator
maven("https://mvn.lumine.io/repository/maven/")
}
dependencies {
compileOnly(fileTree("${project.rootDir}/lib") { include("*.jar") })
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT")
compileOnly("org.spigotmc:spigot-api:1.17.1-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.ticxo.modelengine:api:R3.0.1")
compileOnly("com.github.oraxen:oraxen:-SNAPSHOT")
compileOnly("com.github.LoneDev6:API-ItemsAdder:3.2.5")
compileOnly("com.mineinabyss:idofront:0.12.111")
compileOnly("com.mineinabyss:geary-papermc-core:0.19.113")
compileOnly("com.mineinabyss:looty:0.8.67")
compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.1.0-SNAPSHOT")
compileOnly("it.unimi.dsi:fastutil:8.5.11")
compileOnly("com.github.LeonMangler:SuperVanish:6.2.6-4")
}
}
dependencies {
implementation(project(path = ":common"))
implementation(project(path = ":v1_17_R1", configuration = "reobf"))
implementation(project(path = ":v1_18_R2", configuration = "reobf"))
implementation(project(path = ":v1_19_R1", configuration = "reobf"))
implementation(project(path = ":v1_19_R2", configuration = "reobf"))
//compileOnly("com.github.Fisher2911:FisherLib:master-SNAPSHOT")
implementation("net.kyori:adventure-api:4.11.0")
implementation ("net.kyori:adventure-text-minimessage: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("org.spongepowered:configurate-yaml:4.1.2")
implementation("org.bstats:bstats-bukkit:3.0.0")
implementation("com.jeff_media:SpigotUpdateChecker:3.0.0")
implementation("com.owen1212055:particlehelper:1.0.0-SNAPSHOT")
implementation("com.ticxo.playeranimator:PlayerAnimator:R1.2.5")
}
tasks {
@@ -108,6 +120,8 @@ tasks {
}
shadowJar {
dependsOn(":v1_17_R1:reobfJar")
dependsOn(":v1_18_R2:reobfJar")
dependsOn(":v1_19_R1:reobfJar")
dependsOn(":v1_19_R2:reobfJar")
mergeServiceFiles()
@@ -120,6 +134,8 @@ tasks {
relocate("com.zaxxer.hikaricp", "com.hisbiscusmc.hmccosmetics.hikaricp")
relocate("com.j256.ormlite", "com.hisbiscusmc.hmccosmetics.ormlite")
relocate("com.jeff_media.updatechecker", "com.hisbiscusmc.hmccosmetics.updatechecker")
relocate("com.owen1212055.particlehelper", "com.hisbiscusmc.hmccosmetics.particlehelper")
relocate("com.ticxo.playeranimator", "com.hisbiscusmc.hmccosmetics.playeranimator")
archiveFileName.set("HMCCosmeticsRemapped-${project.version}.jar")
dependencies {
@@ -144,10 +160,10 @@ tasks {
bukkit {
load = BukkitPluginDescription.PluginLoadOrder.POSTWORLD
main = "com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin"
apiVersion = "1.19"
apiVersion = "1.17"
authors = listOf("LoJoSho")
depend = listOf("ProtocolLib", "PlaceholderAPI")
softDepend = listOf("ModelEngine", "Oraxen", "ItemsAdder", "HMCColor", "WorldGuard", "MythicMobs")
depend = listOf("ProtocolLib")
softDepend = listOf("ModelEngine", "Oraxen", "ItemsAdder", "Looty", "HMCColor", "WorldGuard", "MythicMobs", "PlaceholderAPI", "SuperVanish", "PremiumVanish")
version = "${project.version}"
commands {
@@ -174,6 +190,21 @@ bukkit {
register("hmccosmetics.cmd.menu") {
default = BukkitPluginDescription.Permission.Default.TRUE
}
register("hmccosmetics.emote.shiftrun") {
default = BukkitPluginDescription.Permission.Default.TRUE
}
register("hmccosmetics.cmd.emote") {
default = BukkitPluginDescription.Permission.Default.TRUE
}
register("hmccosmetics.cmd.playemote") {
default = BukkitPluginDescription.Permission.Default.OP
}
register("hmccosmetics.cmd.playemote.other") {
default = BukkitPluginDescription.Permission.Default.OP
}
register("hmccosmetics.cmd.emote.other") {
default = BukkitPluginDescription.Permission.Default.OP
}
register("hmccosmetics.cmd.setlocation") {
default = BukkitPluginDescription.Permission.Default.OP
}
@@ -219,17 +250,4 @@ bukkit {
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(17
))
}
publishing {
publications {
create<MavenPublication>("maven") {
groupId = "${project.group}"
artifactId = "${project.name}"
version = "${project.version}"
from(components["java"])
}
}
}

View File

@@ -1,32 +1,104 @@
plugins {
id("java")
id("maven-publish")
}
dependencies {
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT")
compileOnly("org.spigotmc:spigot-api:1.17.1-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.ticxo.modelengine:api:R3.0.1")
compileOnly("com.github.oraxen:oraxen:-SNAPSHOT")
compileOnly("com.github.LoneDev6:API-ItemsAdder:3.2.5")
compileOnly("com.mineinabyss:geary-papermc-core:0.19.113")
compileOnly("com.mineinabyss:looty:0.8.67")
compileOnly("com.hibiscus:hmccolor:0.3-SNAPSHOT")
compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.1.0-SNAPSHOT")
compileOnly("it.unimi.dsi:fastutil:8.5.11")
compileOnly("io.lumine:Mythic-Dist:5.2.1")
compileOnly("com.github.LeonMangler:SuperVanish:6.2.6-4")
//compileOnly("com.github.Fisher2911:FisherLib:master-SNAPSHOT")
implementation("net.kyori:adventure-api:4.12.0")
implementation ("net.kyori:adventure-text-minimessage:4.12.0")
implementation("net.kyori:adventure-text-minimessage:4.12.0")
implementation("net.kyori:adventure-platform-bukkit:4.2.0")
implementation("dev.triumphteam:triumph-gui:3.1.3")
implementation("org.spongepowered:configurate-yaml:4.1.2")
implementation("org.bstats:bstats-bukkit:3.0.0")
implementation("com.jeff_media:SpigotUpdateChecker:3.0.0")
implementation("com.owen1212055:particlehelper:1.0.0-SNAPSHOT")
implementation("com.ticxo.playeranimator:PlayerAnimator:R1.2.5")
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(17
))
}
publishing {
val publishData = PublishData(project)
publications {
create<MavenPublication>("maven") {
groupId = "${rootProject.group}"
artifactId = "${rootProject.name}"
version = "${rootProject.version}"
from(components["java"])
}
}
repositories {
maven {
authentication {
credentials(PasswordCredentials::class) {
username = System.getenv("REPO_USERNAME")
password = System.getenv("REPO_PASSWORD")
}
}
name = "HibiscusMCRepository"
url = uri(publishData.getRepository())
}
}
}
class PublishData(private val project: Project) {
var type: Type = getReleaseType()
var hashLength: Int = 7
private fun getReleaseType(): Type {
val branch = getCheckedOutBranch()
return when {
branch.contentEquals("master") || branch.contentEquals("local") -> Type.RELEASE
branch.startsWith("dev") -> Type.DEV
else -> Type.SNAPSHOT
}
}
private fun getCheckedOutGitCommitHash(): String =
System.getenv("GITHUB_SHA")?.substring(0, hashLength) ?: "local"
private fun getCheckedOutBranch(): String =
System.getenv("GITHUB_REF")?.replace("refs/heads/", "") ?: "local"
fun getVersion(): String = getVersion(false)
fun getVersion(appendCommit: Boolean): String =
type.append(getVersionString(), appendCommit, getCheckedOutGitCommitHash())
private fun getVersionString(): String =
(rootProject.version as String).replace("-SNAPSHOT", "").replace("-DEV", "")
fun getRepository(): String = type.repo
enum class Type(private val append: String, val repo: String, private val addCommit: Boolean) {
RELEASE("", "https://repo.hibiscusmc.com/releases/", false),
DEV("-DEV", "https://repo.hibiscusmc.com/development/", true),
SNAPSHOT("-SNAPSHOT", "https://repo.hibiscusmc.com/snapshots/", true);
fun append(name: String, appendCommit: Boolean, commitHash: String): String =
name.plus(append).plus(if (appendCommit && addCommit) "-".plus(commitHash) else "")
}
}

View File

@@ -12,8 +12,7 @@ import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.database.Database;
import com.hibiscusmc.hmccosmetics.gui.Menus;
import com.hibiscusmc.hmccosmetics.hooks.PAPIHook;
import com.hibiscusmc.hmccosmetics.hooks.items.ItemHooks;
import com.hibiscusmc.hmccosmetics.hooks.Hooks;
import com.hibiscusmc.hmccosmetics.hooks.worldguard.WGHook;
import com.hibiscusmc.hmccosmetics.hooks.worldguard.WGListener;
import com.hibiscusmc.hmccosmetics.listener.PlayerConnectionListener;
@@ -23,6 +22,10 @@ import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.TranslationUtil;
import com.jeff_media.updatechecker.UpdateCheckSource;
import com.jeff_media.updatechecker.UpdateChecker;
import com.ticxo.playeranimator.PlayerAnimatorImpl;
import com.ticxo.playeranimator.api.PlayerAnimator;
import com.ticxo.playeranimator.api.animation.pack.AnimationPack;
import org.apache.commons.io.FilenameUtils;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -38,6 +41,7 @@ import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.nio.file.Path;
import java.util.Map;
public final class HMCCosmeticsPlugin extends JavaPlugin {
@@ -45,6 +49,9 @@ public final class HMCCosmeticsPlugin extends JavaPlugin {
private static boolean disable = false;
private static YamlConfigurationLoader configLoader;
private static final int pluginId = 13873;
private static boolean hasModelEngine = false;
private static boolean onLatestVersion = true;
private static String latestVersion = "";
@Override
public void onEnable() {
@@ -61,11 +68,24 @@ public final class HMCCosmeticsPlugin extends JavaPlugin {
}
// Update Checker
new UpdateChecker(this, UpdateCheckSource.POLYMART, "1879")
.setDownloadLink("https://polymart.org/resource/1879")
UpdateChecker checker = new UpdateChecker(this, UpdateCheckSource.POLYMART, "1879")
.onSuccess((commandSenders, latestVersion) -> {
this.latestVersion = (String) latestVersion;
if (!this.latestVersion.equalsIgnoreCase(getDescription().getVersion())) {
getLogger().info("+++++++++++++++++++++++++++++++++++");
getLogger().info("There is a new update for HMCCosmetics!");
getLogger().info("Please download it as soon as possible for possible fixes and new features.");
getLogger().info("Current Version " + getDescription().getVersion() + " | Latest Version " + latestVersion);
getLogger().info("Spigot: https://www.spigotmc.org/resources/100107/");
getLogger().info("Polymart: https://polymart.org/resource/1879");
getLogger().info("+++++++++++++++++++++++++++++++++++");
}
})
.setNotifyRequesters(false)
.setNotifyOpsOnJoin(false)
.checkEveryXHours(24)
.checkNow();
onLatestVersion = checker.isUsingLatestVersion();
// File setup
if (!getDataFolder().exists()) {
saveDefaultConfig();
@@ -74,6 +94,12 @@ public final class HMCCosmeticsPlugin extends JavaPlugin {
saveResource("cosmetics/defaultcosmetics.yml", false);
saveResource("menus/defaultmenu.yml", false);
}
// Emote folder setup
File emoteFile = new File(getDataFolder().getPath() + "/emotes");
if (!emoteFile.exists()) emoteFile.mkdir();
// Player Animator
PlayerAnimatorImpl.initialize(this);
setup();
@@ -88,10 +114,12 @@ public final class HMCCosmeticsPlugin extends JavaPlugin {
// Database
new Database();
// PAPI
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
new PAPIHook().register();
// ModelEngine
if (Bukkit.getPluginManager().getPlugin("ModelEngine") != null) {
hasModelEngine = true;
}
// WorldGuard
if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) {
getServer().getPluginManager().registerEvents(new WGListener(), this);
}
@@ -173,8 +201,8 @@ public final class HMCCosmeticsPlugin extends JavaPlugin {
throw new RuntimeException(e);
}
// ItemHooks
ItemHooks.setup();
// Misc Hooks setup (like items)
Hooks.setup();
// Cosmetics setup
Cosmetics.setup();
@@ -205,6 +233,22 @@ public final class HMCCosmeticsPlugin extends JavaPlugin {
}
}
File emoteFolder = new File(getInstance().getDataFolder().getPath() + "/emotes/");
if (emoteFolder.exists()) {
PlayerAnimator.api.getAnimationManager().clearRegistry();
File[] emotesFiles = emoteFolder.listFiles();
for (File emoteFile : emotesFiles) {
if (!emoteFile.getName().contains("bbmodel")) continue;
String animationName = emoteFile.getName().replaceAll(".bbmodel", "");
PlayerAnimator.api.getAnimationManager().importAnimations(FilenameUtils.removeExtension(emoteFile.getName()), emoteFile);
MessagesUtil.sendDebugMessages("Added '" + animationName + "' to Player Animator ");
}
for (Map.Entry<String, AnimationPack> packEntry : PlayerAnimator.api.getAnimationManager().getRegistry().entrySet()) {
//Set<String> animationNames = packEntry.getValue().getAnimations().keySet().stream().map(animation -> packEntry.getKey().replace(":", ".") + "." + animation).collect(Collectors.toSet());
}
}
getInstance().getLogger().info("Successfully Enabled HMCCosmetics");
getInstance().getLogger().info(Cosmetics.values().size() + " Cosmetics Successfully Setup");
getInstance().getLogger().info(Menus.getMenuNames().size() + " Menus Successfully Setup");
@@ -229,4 +273,14 @@ public final class HMCCosmeticsPlugin extends JavaPlugin {
throw new RuntimeException(e);
}
}
public static boolean hasModelEngine() {
return hasModelEngine;
}
public static boolean isOnLatestVersion() {
return onLatestVersion;
}
public static String getLatestVersion() {
return latestVersion;
}
}

View File

@@ -2,6 +2,7 @@ package com.hibiscusmc.hmccosmetics.api;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class HMCCosmeticSetupEvent extends Event {
@@ -12,6 +13,7 @@ public class HMCCosmeticSetupEvent extends Event {
private static final HandlerList handlers = new HandlerList();
@Override
@NotNull
public HandlerList getHandlers() {
return handlers;
}

View File

@@ -5,10 +5,11 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerCosmeticEquipEvent extends Event implements Cancellable {
private CosmeticUser user;
private final CosmeticUser user;
private Cosmetic cosmetic;
private boolean isCancelled;
@@ -31,6 +32,7 @@ public class PlayerCosmeticEquipEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@Override
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@@ -47,7 +49,7 @@ public class PlayerCosmeticEquipEvent extends Event implements Cancellable {
return cosmetic;
}
public void setCosmetic() {
public void setCosmetic(Cosmetic cosmetic) {
this.cosmetic = cosmetic;
}
}

View File

@@ -4,14 +4,17 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerCosmeticHideEvent extends Event implements Cancellable {
private CosmeticUser user;
private final CosmeticUser user;
private final CosmeticUser.HiddenReason reason;
private boolean isCancelled;
public PlayerCosmeticHideEvent(CosmeticUser user) {
public PlayerCosmeticHideEvent(CosmeticUser user, CosmeticUser.HiddenReason reason) {
this.user = user;
this.reason = reason;
this.isCancelled = false;
}
@@ -28,6 +31,7 @@ public class PlayerCosmeticHideEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@Override
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@@ -39,4 +43,7 @@ public class PlayerCosmeticHideEvent extends Event implements Cancellable {
public CosmeticUser getUser() {
return user;
}
public CosmeticUser.HiddenReason getReason() {
return reason;
}
}

View File

@@ -5,11 +5,12 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerCosmeticRemoveEvent extends Event implements Cancellable {
private CosmeticUser user;
private Cosmetic cosmetic;
private final CosmeticUser user;
private final Cosmetic cosmetic;
private boolean isCancelled;
public PlayerCosmeticRemoveEvent(CosmeticUser user, Cosmetic cosmetic) {
@@ -31,6 +32,7 @@ public class PlayerCosmeticRemoveEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@Override
@NotNull
public HandlerList getHandlers() {
return handlers;
}

View File

@@ -4,10 +4,11 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerCosmeticShowEvent extends Event implements Cancellable {
private CosmeticUser user;
private final CosmeticUser user;
private boolean isCancelled;
public PlayerCosmeticShowEvent(CosmeticUser user) {
@@ -28,6 +29,7 @@ public class PlayerCosmeticShowEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@Override
@NotNull
public HandlerList getHandlers() {
return handlers;
}

View File

@@ -5,11 +5,12 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerMenuOpenEvent extends Event implements Cancellable {
private CosmeticUser user;
private Menu menu;
private final CosmeticUser user;
private final Menu menu;
private boolean isCancelled;
public PlayerMenuOpenEvent(CosmeticUser user, Menu menu) {
@@ -31,6 +32,7 @@ public class PlayerMenuOpenEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@Override
@NotNull
public HandlerList getHandlers() {
return handlers;
}

View File

@@ -4,10 +4,11 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerWardrobeEnterEvent extends Event implements Cancellable {
private CosmeticUser user;
private final CosmeticUser user;
private boolean isCancelled;
public PlayerWardrobeEnterEvent(CosmeticUser user) {
@@ -28,6 +29,7 @@ public class PlayerWardrobeEnterEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@Override
@NotNull
public HandlerList getHandlers() {
return handlers;
}

View File

@@ -4,10 +4,11 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerWardrobeLeaveEvent extends Event implements Cancellable {
private CosmeticUser user;
private final CosmeticUser user;
private boolean isCancelled;
public PlayerWardrobeLeaveEvent(CosmeticUser user) {
@@ -28,6 +29,7 @@ public class PlayerWardrobeLeaveEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@Override
@NotNull
public HandlerList getHandlers() {
return handlers;
}

View File

@@ -6,6 +6,7 @@ import com.hibiscusmc.hmccosmetics.config.WardrobeSettings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticEmoteType;
import com.hibiscusmc.hmccosmetics.database.Database;
import com.hibiscusmc.hmccosmetics.gui.Menu;
import com.hibiscusmc.hmccosmetics.gui.Menus;
@@ -14,6 +15,7 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.ServerUtils;
import com.ticxo.playeranimator.api.PlayerAnimator;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.apache.commons.lang3.EnumUtils;
@@ -26,13 +28,18 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
public class CosmeticCommand implements CommandExecutor {
// cosmetics apply cosmetics playerName
// 0 1 2
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args) {
boolean silent = false;
if (args.length == 0) {
if (!(sender instanceof Player)) {
// Console
@@ -44,7 +51,7 @@ public class CosmeticCommand implements CommandExecutor {
}
CosmeticUser user = CosmeticUsers.getUser(((Player) sender).getUniqueId());
Menu menu = Menus.getMenu(Settings.getDefaultMenu());
Menu menu = Menus.getDefaultMenu();
if (user == null) {
MessagesUtil.sendMessage(sender, "invalid-player");
@@ -62,49 +69,64 @@ public class CosmeticCommand implements CommandExecutor {
Player player = sender instanceof Player ? (Player) sender : null;
String firstArgs = args[0].toLowerCase();
if (sender.hasPermission("HMCCosmetics.cmd.silent") || sender.isOp()) {
for (String singleArg : args) {
if (singleArg.equalsIgnoreCase("-s")) {
silent = true;
break;
}
}
}
switch (firstArgs) {
case ("reload") -> {
if (!sender.hasPermission("HMCCosmetics.cmd.reload") || !sender.isOp()) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!sender.hasPermission("HMCCosmetics.cmd.reload") && !sender.isOp()) {
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
HMCCosmeticsPlugin.setup();
MessagesUtil.sendMessage(sender, "reloaded");
if (!silent) MessagesUtil.sendMessage(sender, "reloaded");
return true;
}
case ("apply") -> {
if (!sender.hasPermission("hmccosmetics.cmd.apply")) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
Cosmetic cosmetic;
Color color = null;
if (sender instanceof Player) player = ((Player) sender).getPlayer();
if (sender.hasPermission("hmccosmetics.cmd.apply.other")) {
if (args.length >= 3) player = Bukkit.getPlayer(args[2]);
}
if (sender.hasPermission("hmccosmetics.cmd.apply.color")) {
if (args.length >= 4) color = ServerUtils.hex2Rgb(args[3]);
}
if (args.length == 1) {
MessagesUtil.sendMessage(player, "not-enough-args");
if (!silent) MessagesUtil.sendMessage(player, "not-enough-args");
return true;
}
cosmetic = Cosmetics.getCosmetic(args[1]);
if (cosmetic == null) {
MessagesUtil.sendMessage(sender, "invalid-cosmetic");
if (!silent) MessagesUtil.sendMessage(sender, "invalid-cosmetic");
return true;
}
if (player == null) {
MessagesUtil.sendMessage(sender, "invalid-player");
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
CosmeticUser user = CosmeticUsers.getUser(player);
if (!user.canEquipCosmetic(cosmetic)) {
MessagesUtil.sendMessage(player, "no-cosmetic-permission");
if (!silent) MessagesUtil.sendMessage(player, "no-cosmetic-permission");
return true;
}
@@ -113,56 +135,62 @@ public class CosmeticCommand implements CommandExecutor {
TagResolver.resolver(Placeholder.parsed("player", player.getName())),
TagResolver.resolver(Placeholder.parsed("cosmeticslot", cosmetic.getSlot().name())));
MessagesUtil.sendMessage(player, "equip-cosmetic", placeholders);
if (!silent) MessagesUtil.sendMessage(player, "equip-cosmetic", placeholders);
user.addPlayerCosmetic(cosmetic);
user.addPlayerCosmetic(cosmetic, color);
user.updateCosmetic(cosmetic.getSlot());
return true;
}
case ("unapply") -> {
if (!sender.hasPermission("hmccosmetics.cmd.unapply")) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (args.length == 1) {
MessagesUtil.sendMessage(player, "not-enough-args");
if (!silent) MessagesUtil.sendMessage(player, "not-enough-args");
return true;
}
CosmeticSlot cosmeticSlot = null;
if (sender instanceof Player) player = ((Player) sender).getPlayer();
if (sender.hasPermission("hmccosmetics.cmd.unapply.other")) {
if (args.length >= 3) player = Bukkit.getPlayer(args[2]);
}
if (!EnumUtils.isValidEnum(CosmeticSlot.class, args[1].toUpperCase())) {
MessagesUtil.sendMessage(sender, "invalid-slot");
return true;
}
cosmeticSlot = CosmeticSlot.valueOf(args[1].toUpperCase());
if (player == null) {
MessagesUtil.sendMessage(sender, "invalid-player");
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
CosmeticUser user = CosmeticUsers.getUser(player);
if (user.getCosmetic(cosmeticSlot) == null) {
MessagesUtil.sendMessage(sender, "no-cosmetic-slot");
return true;
Set<CosmeticSlot> cosmeticSlots;
if (args[1].equalsIgnoreCase("all")) {
cosmeticSlots = user.getSlotsWithCosmetics();
} else {
if (!EnumUtils.isValidEnum(CosmeticSlot.class, args[1].toUpperCase())) {
if (!silent) MessagesUtil.sendMessage(sender, "invalid-slot");
return true;
}
cosmeticSlots = Set.of(CosmeticSlot.valueOf(args[1].toUpperCase()));
}
TagResolver placeholders =
TagResolver.resolver(Placeholder.parsed("cosmetic", user.getCosmetic(cosmeticSlot).getId()),
TagResolver.resolver(Placeholder.parsed("player", player.getName())),
TagResolver.resolver(Placeholder.parsed("cosmeticslot", cosmeticSlot.name())));
for (CosmeticSlot cosmeticSlot : cosmeticSlots) {
if (user.getCosmetic(cosmeticSlot) == null) {
if (!silent) MessagesUtil.sendMessage(sender, "no-cosmetic-slot");
continue;
}
MessagesUtil.sendMessage(player, "unequip-cosmetic", placeholders);
TagResolver placeholders =
TagResolver.resolver(Placeholder.parsed("cosmetic", user.getCosmetic(cosmeticSlot).getId()),
TagResolver.resolver(Placeholder.parsed("player", player.getName())),
TagResolver.resolver(Placeholder.parsed("cosmeticslot", cosmeticSlot.name())));
user.removeCosmeticSlot(cosmeticSlot);
user.updateCosmetic(cosmeticSlot);
if (!silent) MessagesUtil.sendMessage(player, "unequip-cosmetic", placeholders);
user.removeCosmeticSlot(cosmeticSlot);
user.updateCosmetic(cosmeticSlot);
}
return true;
}
case ("wardrobe") -> {
@@ -172,12 +200,12 @@ public class CosmeticCommand implements CommandExecutor {
}
if (!sender.hasPermission("hmccosmetics.cmd.wardrobe")) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (player == null) {
MessagesUtil.sendMessage(sender, "invalid-player");
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
@@ -190,7 +218,7 @@ public class CosmeticCommand implements CommandExecutor {
case ("menu") -> {
if (args.length == 1) return true;
if (!sender.hasPermission("hmccosmetics.cmd.menu")) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
Menu menu = Menus.getMenu(args[1]);
@@ -202,12 +230,12 @@ public class CosmeticCommand implements CommandExecutor {
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) {
MessagesUtil.sendMessage(sender, "invalid-player");
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
if (menu == null) {
MessagesUtil.sendMessage(sender, "invalid-menu");
if (!silent) MessagesUtil.sendMessage(sender, "invalid-menu");
return true;
}
@@ -219,7 +247,7 @@ public class CosmeticCommand implements CommandExecutor {
OfflinePlayer selectedPlayer = Bukkit.getOfflinePlayer(args[1]);
if (selectedPlayer == null) return true;
if (!sender.hasPermission("hmccosmetics.cmd.dataclear") && !sender.isOp()) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
Database.clearData(selectedPlayer.getUniqueId());
@@ -231,30 +259,30 @@ public class CosmeticCommand implements CommandExecutor {
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return true;
if (!sender.hasPermission("hmccosmetics.cmd.dye") && !sender.isOp()) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (args.length == 1) {
MessagesUtil.sendMessage(player, "not-enough-args");
if (!silent) MessagesUtil.sendMessage(player, "not-enough-args");
return true;
}
if (!EnumUtils.isValidEnum(CosmeticSlot.class, args[1])) {
MessagesUtil.sendMessage(player, "invalid-slot");
if (!silent) MessagesUtil.sendMessage(player, "invalid-slot");
return true;
}
CosmeticSlot slot = CosmeticSlot.valueOf(args[1]);
Cosmetic cosmetic = user.getCosmetic(slot);
if (args.length >= 3) {
if (!args[2].contains("#") || args[2].isEmpty()) {
MessagesUtil.sendMessage(player, "invalid-color");
if (args[2].isEmpty()) {
if (!silent) MessagesUtil.sendMessage(player, "invalid-color");
return true;
}
Color color = ServerUtils.hex2Rgb(args[2]);
if (color == null) {
MessagesUtil.sendMessage(player, "invalid-color");
if (!silent) MessagesUtil.sendMessage(player, "invalid-color");
return true;
}
user.addPlayerCosmetic(cosmetic, color); // #FFFFFF
@@ -264,32 +292,32 @@ public class CosmeticCommand implements CommandExecutor {
}
case ("setlocation") -> {
if (!sender.hasPermission("hmccosmetics.cmd.setlocation")) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (player == null) return true;
if (args.length < 2) {
MessagesUtil.sendMessage(player, "not-enough-args");
if (!silent) MessagesUtil.sendMessage(player, "not-enough-args");
return true;
}
if (args[1].equalsIgnoreCase("wardrobelocation")) {
WardrobeSettings.setWardrobeLocation(player.getLocation());
MessagesUtil.sendMessage(player, "set-wardrobe-location");
if (!silent) MessagesUtil.sendMessage(player, "set-wardrobe-location");
return true;
}
if (args[1].equalsIgnoreCase("viewerlocation")) {
WardrobeSettings.setViewerLocation(player.getLocation());
MessagesUtil.sendMessage(player, "set-wardrobe-viewing");
if (!silent) MessagesUtil.sendMessage(player, "set-wardrobe-viewing");
return true;
}
if (args[1].equalsIgnoreCase("leavelocation")) {
WardrobeSettings.setLeaveLocation(player.getLocation());
MessagesUtil.sendMessage(player, "set-wardrobe-leaving");
if (!silent) MessagesUtil.sendMessage(player, "set-wardrobe-leaving");
return true;
}
}
@@ -298,12 +326,12 @@ public class CosmeticCommand implements CommandExecutor {
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return true;
if (!sender.hasPermission("HMCCosmetic.cmd.dump") && !sender.isOp()) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
player.sendMessage("Passengers -> " + player.getPassengers());
if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
player.sendMessage("Backpack Location -> " + user.getBackpackEntity().getLocation());
player.sendMessage("Backpack Location -> " + user.getUserBackpackManager().getArmorStand().getLocation());
}
player.sendMessage("Cosmetics -> " + user.getCosmetic());
player.sendMessage("EntityId -> " + player.getEntityId());
@@ -316,19 +344,18 @@ public class CosmeticCommand implements CommandExecutor {
}
if (!sender.hasPermission("hmccosmetics.cmd.hide")) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (player == null) {
MessagesUtil.sendMessage(sender, "invalid-player");
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
CosmeticUser user = CosmeticUsers.getUser(player);
MessagesUtil.sendMessage(sender, "hide-cosmetic");
user.hideCosmetics();
if (!silent) MessagesUtil.sendMessage(sender, "hide-cosmetic");
user.hideCosmetics(CosmeticUser.HiddenReason.COMMAND);
return true;
}
case ("show") -> {
@@ -338,36 +365,89 @@ public class CosmeticCommand implements CommandExecutor {
}
if (!sender.hasPermission("hmccosmetics.cmd.show")) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (player == null) {
MessagesUtil.sendMessage(sender, "invalid-player");
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
CosmeticUser user = CosmeticUsers.getUser(player);
MessagesUtil.sendMessage(sender, "show-cosmetic");
if (!silent) MessagesUtil.sendMessage(sender, "show-cosmetic");
user.showCosmetics();
return true;
}
case ("debug") -> {
if (!sender.hasPermission("hmccosmetics.cmd.debug")) {
MessagesUtil.sendMessage(sender, "no-permission");
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (Settings.getDebugMode()) {
Settings.setDebugMode(false);
MessagesUtil.sendMessage(sender, "debug-disabled");
if (!silent) MessagesUtil.sendMessage(sender, "debug-disabled");
} else {
Settings.setDebugMode(true);
MessagesUtil.sendMessage(sender, "debug-enabled");
if (!silent) MessagesUtil.sendMessage(sender, "debug-enabled");
}
}
case ("emote") -> {
if (!sender.hasPermission("hmccosmetics.cmd.emote")) {
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (sender.hasPermission("hmccosmetics.cmd.emote.other")) {
if (args.length >= 2) player = Bukkit.getPlayer(args[1]);
}
if (player == null) {
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
CosmeticUser user = CosmeticUsers.getUser(player);
if (!user.hasCosmeticInSlot(CosmeticSlot.EMOTE)) {
if (!silent) MessagesUtil.sendMessage(sender, "emote-none");
return true;
}
CosmeticEmoteType cosmeticEmoteType = (CosmeticEmoteType) user.getCosmetic(CosmeticSlot.EMOTE);
cosmeticEmoteType.run(user);
return true;
}
case ("playemote") -> {
// /cosmetic playEmote <emoteId> [playerName]
if (!sender.hasPermission("hmccosmetics.cmd.playemote")) {
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (args.length < 2) {
if (!silent) MessagesUtil.sendMessage(player, "not-enough-args");
return true;
}
if (args.length >= 2) {
if (!PlayerAnimator.api.getAnimationManager().getRegistry().keySet().contains(args[1])) {
MessagesUtil.sendDebugMessages("Did not contain " + args[1]);
if (!silent) MessagesUtil.sendMessage(sender, "emote-invalid");
return true;
}
}
if (sender.hasPermission("hmccosmetics.cmd.playemote.other")) {
if (args.length >= 3) player = Bukkit.getPlayer(args[2]);
}
if (player == null) {
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
CosmeticUser user = CosmeticUsers.getUser(player);
user.getUserEmoteManager().playEmote(args[1]);
return true;
}
}
return true;
}

View File

@@ -7,6 +7,7 @@ import com.hibiscusmc.hmccosmetics.gui.Menu;
import com.hibiscusmc.hmccosmetics.gui.Menus;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.ticxo.playeranimator.api.PlayerAnimator;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@@ -23,9 +24,9 @@ import java.util.List;
public class CosmeticCommandTabComplete implements TabCompleter {
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String @NotNull [] args) {
List<String> completions = new ArrayList<>();
List<String> finalCompletitons = new ArrayList<>();
List<String> finalCompletions = new ArrayList<>();
if (args.length == 1) {
if (hasPermission(sender, "hmccosmetics.cmd.apply")) completions.add("apply");
@@ -39,8 +40,10 @@ public class CosmeticCommandTabComplete implements TabCompleter {
if (hasPermission(sender, "hmccosmetics.cmd.hide")) completions.add("hide");
if (hasPermission(sender, "hmccosmetics.cmd.show")) completions.add("show");
if (hasPermission(sender, "hmccosmetics.cmd.debug")) completions.add("debug");
if (hasPermission(sender, "hmccosmetics.cmd.emote")) completions.add("emote");
if (hasPermission(sender, "hmccosmetics.cmd.playemote")) completions.add("playemote");
StringUtil.copyPartialMatches(args[0], completions, finalCompletitons);
StringUtil.copyPartialMatches(args[0], completions, finalCompletions);
}
if (!(sender instanceof Player)) return completions;
@@ -56,13 +59,14 @@ public class CosmeticCommandTabComplete implements TabCompleter {
for (Cosmetic cosmetic : user.getCosmetic()) {
completions.add(cosmetic.getSlot().toString().toUpperCase());
}
completions.add("ALL");
}
case "menu" -> {
for (Menu menu : Menus.getMenu()) {
if (menu.canOpen(user.getPlayer())) completions.add(menu.getId());
}
}
case "dataclear", "wardrobe", "hide", "show" -> {
case "dataclear", "wardrobe", "hide", "show", "emote" -> {
for (Player player : Bukkit.getOnlinePlayers()) {
completions.add(player.getName());
}
@@ -77,8 +81,11 @@ public class CosmeticCommandTabComplete implements TabCompleter {
completions.add("viewerlocation");
completions.add("leavelocation");
}
case "playemote" -> {
completions.addAll(PlayerAnimator.api.getAnimationManager().getRegistry().keySet());
}
}
StringUtil.copyPartialMatches(args[1], completions, finalCompletitons);
StringUtil.copyPartialMatches(args[1], completions, finalCompletions);
}
if (args.length == 3) {
String subcommand = args[0].toLowerCase();
@@ -86,21 +93,31 @@ public class CosmeticCommandTabComplete implements TabCompleter {
case "dye" -> {
completions.add("#FFFFFF");
}
case "menu", "apply", "unapply" -> {
case "menu", "apply", "unapply", "playemote" -> {
for (Player player : Bukkit.getOnlinePlayers()) {
completions.add(player.getName());
}
}
}
StringUtil.copyPartialMatches(args[2], completions, finalCompletitons);
StringUtil.copyPartialMatches(args[2], completions, finalCompletions);
}
Collections.sort(finalCompletitons);
return finalCompletitons;
if (args.length == 4) {
String subcommand = args[0].toLowerCase();
switch (subcommand) {
case "apply" -> {
completions.add("#FFFFFF");
}
}
StringUtil.copyPartialMatches(args[3], completions, finalCompletions);
}
Collections.sort(finalCompletions);
return finalCompletions;
}
private static List<String> applyCommandComplete(CosmeticUser user, String[] args) {
@NotNull
private static List<String> applyCommandComplete(CosmeticUser user, String @NotNull [] args) {
List<String> completitions = new ArrayList<>();
if (args.length == 2) {
@@ -119,7 +136,7 @@ public class CosmeticCommandTabComplete implements TabCompleter {
return completitions;
}
private boolean hasPermission(CommandSender sender, String permission) {
private boolean hasPermission(@NotNull CommandSender sender, String permission) {
if (sender.isOp()) return true;
if (sender.hasPermission(permission)) return true;
return false;

View File

@@ -25,12 +25,22 @@ public class Settings {
private static final String PARTICLE_COUNT = "particle-count";
private static final String DYE_MENU_PATH = "dye-menu";
private static final String DYE_MENU_NAME = "title";
private static final String DYE_MENU_INPUT_SLOT = "input-slot";
private static final String DYE_MENU_OUTPUT_SLOT = "output-slot";
private static final String DEBUG_ENABLE_PETH = "debug-mode";
private static final String TICK_PERIOD_PATH = "tick-period";
private static final String UNAPPLY_DEATH_PATH = "unapply-on-death";
private static final String FORCE_PERMISSION_JOIN_PATH = "force-permission-join";
private static final String EMOTE_DISTANCE_PATH = "emote-distance";
private static final String HOOK_SETTING_PATH = "hook-settings";
private static final String HOOK_ITEMADDER_PATH = "itemsadder";
private static final String HOOK_RELOAD_CHANGE_PATH = "reload-on-change";
private static final String COSMETIC_EMOTE_CHECK_PATH = "emote-block-check";
private static String defaultMenu;
private static String dyeMenuName;
private static int dyeMenuInputSlot;
private static int dyeMenuOutputSlot;
private static int configVersion;
private static boolean requireEmptyHelmet;
private static boolean requireEmptyOffHand;
@@ -39,9 +49,13 @@ public class Settings {
private static boolean requireEmptyBoots;
private static boolean debugMode;
private static boolean unapplyOnDeath;
private static boolean forcePermissionJoin;
private static boolean itemsAdderChangeReload;
private static boolean cosmeticEmoteBlockCheck;
private static int lookDownPitch;
private static int viewDistance;
private static int tickPeriod;
private static double emoteDistance;
private static Vector balloonOffset;
public static void load(ConfigurationNode source) {
@@ -67,6 +81,9 @@ public class Settings {
requireEmptyPants = cosmeticSettings.node(REQUIRE_EMPTY_PANTS_PATH).getBoolean();
requireEmptyBoots = cosmeticSettings.node(REQUIRE_EMPTY_BOOTS_PATH).getBoolean();
unapplyOnDeath = cosmeticSettings.node(UNAPPLY_DEATH_PATH).getBoolean(false);
forcePermissionJoin = cosmeticSettings.node(FORCE_PERMISSION_JOIN_PATH).getBoolean(false);
emoteDistance = cosmeticSettings.node(EMOTE_DISTANCE_PATH).getDouble(-3);
cosmeticEmoteBlockCheck = cosmeticSettings.node(COSMETIC_EMOTE_CHECK_PATH).getBoolean(true);
tickPeriod = cosmeticSettings.node(TICK_PERIOD_PATH).getInt(-1);
lookDownPitch = cosmeticSettings.node(LOOK_DOWN_PITCH_PATH).getInt();
@@ -79,6 +96,12 @@ public class Settings {
ConfigurationNode dyeMenuSettings = source.node(DYE_MENU_PATH);
dyeMenuName = dyeMenuSettings.node(DYE_MENU_NAME).getString("Dye Menu");
dyeMenuInputSlot = dyeMenuSettings.node(DYE_MENU_INPUT_SLOT).getInt(19);
dyeMenuOutputSlot = dyeMenuSettings.node(DYE_MENU_OUTPUT_SLOT).getInt(25);
ConfigurationNode hookSettings = source.node(HOOK_SETTING_PATH);
ConfigurationNode itemsAdderSettings = hookSettings.node(HOOK_ITEMADDER_PATH);
itemsAdderChangeReload = itemsAdderSettings.node(HOOK_RELOAD_CHANGE_PATH).getBoolean(false);
}
private static Vector loadVector(final ConfigurationNode config) {
@@ -172,10 +195,15 @@ public class Settings {
public static String getDyeMenuName() {
return dyeMenuName;
}
public static int getDyeMenuInputSlot() { return dyeMenuInputSlot; }
public static int getDyeMenuOutputSlot() { return dyeMenuOutputSlot; }
public static boolean isDebugEnabled() {
return debugMode;
}
public static boolean getItemsAdderReloadChange() {
return itemsAdderChangeReload;
}
public static int getTickPeriod() {
return tickPeriod;
@@ -183,10 +211,22 @@ public class Settings {
public static boolean getUnapplyOnDeath() {
return unapplyOnDeath;
}
public static boolean getForcePermissionJoin() {
return forcePermissionJoin;
}
public static boolean getDebugMode() {
return debugMode;
}
public static double getEmoteDistance() {
return emoteDistance;
}
public static boolean getCosmeticEmoteBlockCheck() {
return cosmeticEmoteBlockCheck;
}
public static void setDebugMode(boolean newSetting) {
debugMode = newSetting;

View File

@@ -182,7 +182,7 @@ public class WardrobeSettings {
public static boolean inDistanceOfStatic(final Location location) {
if (wardrobeLocation == null) return false;
if (staticRadius == -1) return false;
if (staticRadius == -1) return true;
if (!wardrobeLocation.getWorld().equals(location.getWorld())) return false;
return wardrobeLocation.distanceSquared(location) <= staticRadius * staticRadius;
}

View File

@@ -1,10 +1,13 @@
package com.hibiscusmc.hmccosmetics.config.serializer;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.hooks.items.ItemHooks;
import com.hibiscusmc.hmccosmetics.hooks.Hooks;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.ServerUtils;
import com.hibiscusmc.hmccosmetics.util.builder.ColorBuilder;
import com.hibiscusmc.hmccosmetics.util.misc.StringUtils;
import com.hibiscusmc.hmccosmetics.util.misc.Utils;
import org.apache.commons.lang3.EnumUtils;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
@@ -71,7 +74,7 @@ public class ItemSerializer implements TypeSerializer<ItemStack> {
String material = materialNode.getString();
ItemStack item = ItemHooks.getItem(material);
ItemStack item = Hooks.getItem(material);
if (item == null) {
HMCCosmeticsPlugin.getInstance().getLogger().severe("Invalid Material -> " + material);
return new ItemStack(Material.AIR);
@@ -80,15 +83,16 @@ public class ItemSerializer implements TypeSerializer<ItemStack> {
ItemMeta itemMeta = item.getItemMeta();
if (itemMeta == null) return item;
if (!nameNode.virtual()) itemMeta.setDisplayName(StringUtils.parseStringToString(Utils.replaceIfNull(nameNode.getString(), "")));
if (!nameNode.virtual())
itemMeta.setDisplayName(StringUtils.parseStringToString(Utils.replaceIfNull(nameNode.getString(), "")));
if (!unbreakableNode.virtual()) itemMeta.setUnbreakable(unbreakableNode.getBoolean());
if (!glowingNode.virtual()) {
itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
itemMeta.addEnchant(Enchantment.LUCK, 1, true);
}
if (!loreNode.virtual()) itemMeta.setLore(Utils.replaceIfNull(loreNode.getList(String.class),
new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList()));
new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList()));
if (!modelDataNode.virtual()) itemMeta.setCustomModelData(modelDataNode.getInt());
if (!nbtNode.virtual()) {
@@ -104,11 +108,16 @@ public class ItemSerializer implements TypeSerializer<ItemStack> {
}
}
if (!itemFlagsNode.virtual()) {
for (ConfigurationNode flagNode : itemFlagsNode.childrenMap().values()) {
if (ItemFlag.valueOf(flagNode.key().toString()) == null) continue;
itemMeta.addItemFlags(ItemFlag.valueOf(flagNode.key().toString()));
try {
if (!itemFlagsNode.virtual()) {
for (String itemFlag : itemFlagsNode.getList(String.class)) {
if (!EnumUtils.isValidEnum(ItemFlag.class, itemFlag)) continue;
MessagesUtil.sendDebugMessages("Added " + itemFlag + " to the item!");
itemMeta.addItemFlags(ItemFlag.valueOf(itemFlag));
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (item.getType() == Material.PLAYER_HEAD) {
@@ -126,7 +135,11 @@ public class ItemSerializer implements TypeSerializer<ItemStack> {
if (!colorNode.virtual()) {
if (ColorBuilder.canBeColored(item.getType())) {
itemMeta = ColorBuilder.color(itemMeta, Color.fromRGB(redNode.getInt(0), greenNode.getInt(0), blueNode.getInt(0)));
if (!redNode.virtual()) {
itemMeta = ColorBuilder.color(itemMeta, Color.fromRGB(redNode.getInt(0), greenNode.getInt(0), blueNode.getInt(0)));
} else {
itemMeta = ColorBuilder.color(itemMeta, ServerUtils.hex2Rgb(colorNode.getString("#FFFFFF")));
}
}
}
@@ -136,7 +149,6 @@ public class ItemSerializer implements TypeSerializer<ItemStack> {
item.setItemMeta(itemMeta);
return item;
}
@Override
public void serialize(final Type type, @Nullable final ItemStack obj, final ConfigurationNode node) throws SerializationException {

View File

@@ -5,13 +5,14 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import java.util.logging.Level;
public class Cosmetic {
public abstract class Cosmetic {
private String id;
private String permission;
@@ -19,8 +20,9 @@ public class Cosmetic {
private CosmeticSlot slot;
private boolean dyable;
protected Cosmetic(String id, ConfigurationNode config) {
protected Cosmetic(String id, @NotNull ConfigurationNode config) {
this.id = id;
if (!config.node("permission").virtual()) {
this.permission = config.node("permission").getString();
} else {
@@ -30,20 +32,20 @@ public class Cosmetic {
if (!config.node("item").virtual()) this.item = generateItemStack(config.node("item"));
MessagesUtil.sendDebugMessages("Slot: " + config.node("slot").getString());
setSlot(CosmeticSlot.valueOf(config.node("slot").getString()));
setSlot(CosmeticSlot.valueOf(config.node("slot").getString()));
setDyable(config.node("dyeable").getBoolean(false));
MessagesUtil.sendDebugMessages("Dyeable " + dyable);
Cosmetics.addCosmetic(this);
}
public String getId() {
return this.id;
}
public String getPermission() {
return this.permission;
public void setId(String id) {
this.id = id;
}
public CosmeticSlot getSlot() {
@@ -53,17 +55,17 @@ public class Cosmetic {
public void setSlot(CosmeticSlot slot) {
this.slot = slot;
}
public String getPermission() {
return this.permission;
}
public void setPermission(String permission) {
this.permission = permission;
}
public boolean requiresPermission() {
if (permission == null) return false;
return true;
}
public void setId(String id) {
this.id = id;
return permission != null;
}
public void setDyable(boolean dyable) {
@@ -74,10 +76,7 @@ public class Cosmetic {
return this.dyable;
}
public void update(CosmeticUser user) {
// Override
}
public abstract void update(CosmeticUser user);
@Nullable
public ItemStack getItem() {

View File

@@ -8,5 +8,6 @@ public enum CosmeticSlot {
MAINHAND,
OFFHAND,
BACKPACK,
BALLOON
BALLOON,
EMOTE
}

View File

@@ -3,12 +3,11 @@ package com.hibiscusmc.hmccosmetics.cosmetic;
import com.google.common.collect.HashBiMap;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBalloonType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticMainhandType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.*;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.apache.commons.lang3.EnumUtils;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.CommentedConfigurationNode;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
@@ -20,7 +19,7 @@ import java.util.logging.Level;
public class Cosmetics {
private static HashBiMap<String, Cosmetic> COSMETICS = HashBiMap.create();
private static final HashBiMap<String, Cosmetic> COSMETICS = HashBiMap.create();
public static void addCosmetic(Cosmetic cosmetic) {
COSMETICS.put(cosmetic.getId(), cosmetic);
@@ -38,10 +37,14 @@ public class Cosmetics {
return COSMETICS.get(id);
}
@Contract(pure = true)
@NotNull
public static Set<Cosmetic> values() {
return COSMETICS.values();
}
@Contract(pure = true)
@NotNull
public static Set<String> keys() {
return COSMETICS.keySet();
}
@@ -79,7 +82,7 @@ public class Cosmetics {
}
}
private static void setupCosmetics(CommentedConfigurationNode config) {
private static void setupCosmetics(@NotNull CommentedConfigurationNode config) {
for (ConfigurationNode cosmeticConfig : config.childrenMap().values()) {
try {
String id = cosmeticConfig.key().toString();
@@ -97,6 +100,7 @@ public class Cosmetics {
case BALLOON -> new CosmeticBalloonType(id, cosmeticConfig);
case BACKPACK -> new CosmeticBackpackType(id, cosmeticConfig);
case MAINHAND -> new CosmeticMainhandType(id, cosmeticConfig);
case EMOTE -> new CosmeticEmoteType(id, cosmeticConfig);
default -> new CosmeticArmorType(id, cosmeticConfig);
}
} catch (Exception e) {

View File

@@ -7,11 +7,12 @@ import com.hibiscusmc.hmccosmetics.util.packets.PacketManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.ConfigurationNode;
public class CosmeticArmorType extends Cosmetic {
private EquipmentSlot equipSlot;
private final EquipmentSlot equipSlot;
public CosmeticArmorType(String id, ConfigurationNode config) {
super(id, config);
@@ -20,7 +21,7 @@ public class CosmeticArmorType extends Cosmetic {
}
@Override
public void update(CosmeticUser user) {
public void update(@NotNull CosmeticUser user) {
Player player = Bukkit.getPlayer(user.getUniqueId());
if (player == null) return;
if (equipSlot.equals(EquipmentSlot.OFF_HAND)) {
@@ -32,6 +33,4 @@ public class CosmeticArmorType extends Cosmetic {
public EquipmentSlot getEquipSlot() {
return this.equipSlot;
}
}

View File

@@ -2,38 +2,57 @@ package com.hibiscusmc.hmccosmetics.cosmetic.types;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.manager.UserBackpackManager;
import com.hibiscusmc.hmccosmetics.util.packets.PacketManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.ConfigurationNode;
public class CosmeticBackpackType extends Cosmetic {
ConfigurationNode config;
private final String modelName;
private UserBackpackManager.BackpackType backpackType;
public CosmeticBackpackType(String id, ConfigurationNode config) {
super(id, config);
this.config = config;
modelName = config.node("model").getString();
backpackType = UserBackpackManager.BackpackType.valueOf(config.node("type").getString("NORMAL").toUpperCase());
}
@Override
public void update(CosmeticUser user) {
public void update(@NotNull CosmeticUser user) {
Player player = Bukkit.getPlayer(user.getUniqueId());
Location loc = player.getLocation().clone();
if (player == null) return;
if (user.isInWardrobe()) return;
Location loc = player.getLocation().clone().add(0, 2, 0);
if (loc.getWorld() != user.getBackpackEntity().getWorld()) {
user.getBackpackEntity().teleport(loc);
if (user.isInWardrobe() || !user.isBackpackSpawned()) return;
if (loc.getWorld() != user.getUserBackpackManager().getArmorStand().getWorld()) {
user.getUserBackpackManager().getArmorStand().teleport(loc);
}
user.getBackpackEntity().teleport(loc);
user.getUserBackpackManager().getArmorStand().teleport(loc);
PacketManager.sendRidingPacket(player.getEntityId(), user.getBackpackEntity().getEntityId(), loc);
if (user.getUserBackpackManager().getBackpackType().equals(UserBackpackManager.BackpackType.FIRST_PERSON)) {
user.getUserBackpackManager().teleportEffectEntity(loc);
PacketManager.sendRidingPacket(player.getEntityId(), user.getUserBackpackManager().getAreaEffectEntityId(), loc);
PacketManager.sendRidingPacket(user.getUserBackpackManager().getAreaEffectEntityId(), user.getUserBackpackManager().getFirstArmorStandId(), loc);
} else {
PacketManager.sendRidingPacket(player.getEntityId(), user.getUserBackpackManager().getFirstArmorStandId(), loc);
}
user.getBackpackEntity().setRotation(loc.getYaw(), loc.getPitch());
user.showBackpack();
user.getUserBackpackManager().getArmorStand().setRotation(loc.getYaw(), loc.getPitch());
user.getUserBackpackManager().showBackpack();
}
public String getModelName() {
return modelName;
}
public UserBackpackManager.BackpackType getBackpackType() {
return backpackType;
}
}

View File

@@ -2,56 +2,82 @@ package com.hibiscusmc.hmccosmetics.cosmetic.types;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.entities.BalloonEntity;
import com.hibiscusmc.hmccosmetics.user.manager.UserBalloonManager;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.packets.PacketManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import java.util.List;
public class CosmeticBalloonType extends Cosmetic {
private String modelName;
private final String modelName;
private List<String> dyableParts;
public CosmeticBalloonType(String id, ConfigurationNode config) {
super(id, config);
String modelId = config.node("model").getString();
try {
if (!config.node("dyable-parts").virtual()) {
dyableParts = config.node("dyable-parts").getList(String.class);
}
} catch (SerializationException e) {
// Seriously?
throw new RuntimeException(e);
}
this.modelName = modelId;
}
@Override
public void update(CosmeticUser user) {
public void update(@NotNull CosmeticUser user) {
Player player = Bukkit.getPlayer(user.getUniqueId());
Location currentLocation = user.getBalloonEntity().getLocation().clone();
Location newLocation = player.getLocation().clone().add(Settings.getBalloonOffset()).clone();
if (player == null) return;
UserBalloonManager userBalloonManager = user.getBalloonManager();
if (player == null || userBalloonManager == null) return;
if (user.isInWardrobe()) return;
Location newLocation = player.getLocation();
Location currentLocation = user.getBalloonManager().getLocation();
newLocation = newLocation.clone().add(Settings.getBalloonOffset());
List<Player> viewer = PacketManager.getViewers(player.getLocation());
viewer.add(player);
BalloonEntity balloonEntity = user.getBalloonEntity();
if (player.getLocation().getWorld() != balloonEntity.getLocation().getWorld()) {
balloonEntity.getModelEntity().teleport(newLocation);
PacketManager.sendTeleportPacket(balloonEntity.getPufferfishBalloonId(), newLocation, false, viewer);
if (player.getLocation().getWorld() != userBalloonManager.getLocation().getWorld()) {
userBalloonManager.getModelEntity().teleport(newLocation);
PacketManager.sendTeleportPacket(userBalloonManager.getPufferfishBalloonId(), newLocation, false, viewer);
return;
}
Vector velocity = newLocation.clone().toVector().subtract(currentLocation.clone().toVector());
balloonEntity.setLocation(newLocation);
balloonEntity.setVelocity(velocity);
Vector velocity = newLocation.toVector().subtract(currentLocation.toVector());
userBalloonManager.setVelocity(velocity.multiply(1.1));
userBalloonManager.setLocation(newLocation);
PacketManager.sendTeleportPacket(balloonEntity.getPufferfishBalloonId(), newLocation, false, viewer);
if (!user.getHidden()) PacketManager.sendLeashPacket(balloonEntity.getPufferfishBalloonId(), player.getEntityId(), viewer);
PacketManager.sendTeleportPacket(userBalloonManager.getPufferfishBalloonId(), newLocation, false, viewer);
if (!user.getHidden()) PacketManager.sendLeashPacket(userBalloonManager.getPufferfishBalloonId(), player.getEntityId(), viewer);
}
public String getModelName() {
return this.modelName;
}
public List<String> getDyableParts() {
return dyableParts;
}
public boolean isDyablePart(String name) {
// If player does not define parts, dye whole model
if (dyableParts == null) return true;
if (dyableParts.isEmpty()) return true;
return dyableParts.contains(name);
}
}

View File

@@ -0,0 +1,32 @@
package com.hibiscusmc.hmccosmetics.cosmetic.types;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.ConfigurationNode;
public class CosmeticEmoteType extends Cosmetic {
private final String animationId;
public CosmeticEmoteType(String id, ConfigurationNode config) {
super(id, config);
animationId = config.node("animation").getString();
MessagesUtil.sendDebugMessages("CosmeticEmoteType Animation id " + animationId);
}
@Override
public void update(CosmeticUser user) {
// Nothing
}
public void run(@NotNull CosmeticUser user) {
user.getUserEmoteManager().playEmote(this);
}
public String getAnimationId() {
return animationId;
}
}

View File

@@ -5,6 +5,7 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.PlayerUtils;
import com.hibiscusmc.hmccosmetics.util.packets.PacketManager;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.ConfigurationNode;
public class CosmeticMainhandType extends Cosmetic {
@@ -14,10 +15,9 @@ public class CosmeticMainhandType extends Cosmetic {
}
@Override
public void update(CosmeticUser user) {
public void update(@NotNull CosmeticUser user) {
Player player = user.getPlayer();
PacketManager.equipmentSlotUpdate(player.getEntityId(), user, getSlot(), PlayerUtils.getNearbyPlayers(player));
}
}

View File

@@ -16,23 +16,23 @@ public class Database {
private static Data data;
@Deprecated
private static InternalData INTERNAL_DATA = new InternalData();
private static MySQLData MYSQL_DATA = new MySQLData();
private static SQLiteData SQLITE_DATA = new SQLiteData();
private static final MySQLData MYSQL_DATA = new MySQLData();
private static final SQLiteData SQLITE_DATA = new SQLiteData();
public Database() {
String databaseType = DatabaseSettings.getDatabaseType();
data = INTERNAL_DATA; // default
if (databaseType.equalsIgnoreCase("INTERNAL")) {
data = INTERNAL_DATA;
}
data = SQLITE_DATA; // default
if (databaseType.equalsIgnoreCase("MySQL")) {
data = MYSQL_DATA;
}
/* SQLite is the default database. Might change in the future, so keep code here in case.
if (databaseType.equalsIgnoreCase("sqlite")) {
data = SQLITE_DATA;
}
*/
MessagesUtil.sendDebugMessages("Database is " + data);
setup();

View File

@@ -1,39 +1,42 @@
package com.hibiscusmc.hmccosmetics.database.types;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.apache.commons.lang3.EnumUtils;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class Data {
public abstract class Data {
public void setup() {
// Override
}
public abstract void setup();
public void save(CosmeticUser user) {
// Override
}
public abstract void save(CosmeticUser user);
@Nullable
public CosmeticUser get(UUID uniqueId) {
// Override
return null;
}
public abstract CosmeticUser get(UUID uniqueId);
public abstract void clear(UUID uniqueId);
public void clear(UUID uniqueId) {
// Override
}
// BACKPACK=colorfulbackpack&RRGGBB,HELMET=niftyhat,BALLOON=colorfulballoon,CHESTPLATE=niftychestplate
public String steralizeData(CosmeticUser user) {
@NotNull
public final String serializeData(@NotNull CosmeticUser user) {
String data = "";
if (user.getHidden()) {
if (shouldHiddenSave(user.getHiddenReason())) {
data = "HIDDEN=" + user.getHiddenReason();
}
}
for (Cosmetic cosmetic : user.getCosmetic()) {
Color color = user.getCosmeticColor(cosmetic.getSlot());
String input = cosmetic.getSlot() + "=" + cosmetic.getId();
@@ -47,8 +50,10 @@ public class Data {
return data;
}
public Map<CosmeticSlot, Map<Cosmetic, Color>> desteralizedata(String raw) {
@NotNull
public final Map<CosmeticSlot, Map<Cosmetic, Color>> deserializeData(CosmeticUser user, @NotNull String raw) {
Map<CosmeticSlot, Map<Cosmetic, Color>> cosmetics = new HashMap<>();
boolean checkPermission = Settings.getForcePermissionJoin();
String[] rawData = raw.split(",");
for (String a : rawData) {
@@ -57,16 +62,33 @@ public class Data {
CosmeticSlot slot = null;
Cosmetic cosmetic = null;
MessagesUtil.sendDebugMessages("First split (suppose slot) " + splitData[0]);
if (splitData[0].equalsIgnoreCase("HIDDEN")) {
if (EnumUtils.isValidEnum(CosmeticUser.HiddenReason.class, splitData[1])) {
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> {
user.hideCosmetics(CosmeticUser.HiddenReason.valueOf(splitData[1]));
});
}
continue;
}
if (CosmeticSlot.valueOf(splitData[0]) != null) slot = CosmeticSlot.valueOf(splitData[0]);
if (splitData[1].contains("&")) {
String[] colorSplitData = splitData[1].split("&");
if (Cosmetics.hasCosmetic(colorSplitData[0])) cosmetic = Cosmetics.getCosmetic(colorSplitData[0]);
if (slot == null || cosmetic == null) continue;
if (cosmetic.requiresPermission() && checkPermission) {
if (!user.getPlayer().hasPermission(cosmetic.getPermission())) {
continue;
}
}
cosmetics.put(slot, Map.of(cosmetic, Color.fromRGB(Integer.parseInt(colorSplitData[1]))));
} else {
if (Cosmetics.hasCosmetic(splitData[1])) cosmetic = Cosmetics.getCosmetic(splitData[1]);
if (slot == null || cosmetic == null) continue;
if (cosmetic.requiresPermission() && checkPermission) {
if (!user.getPlayer().hasPermission(cosmetic.getPermission())) {
continue;
}
}
HashMap<Cosmetic, Color> cosmeticColorHashMap = new HashMap<>();
cosmeticColorHashMap.put(cosmetic, null);
cosmetics.put(slot, cosmeticColorHashMap);
@@ -74,4 +96,15 @@ public class Data {
}
return cosmetics;
}
private boolean shouldHiddenSave(CosmeticUser.@NotNull HiddenReason reason) {
switch (reason) {
case EMOTE, NONE -> {
return false;
}
default -> {
return true;
}
}
}
}

View File

@@ -14,6 +14,7 @@ import org.bukkit.persistence.PersistentDataType;
import java.util.Map;
import java.util.UUID;
@Deprecated
public class InternalData extends Data {
NamespacedKey key = new NamespacedKey(HMCCosmeticsPlugin.getInstance(), "cosmetics");
@@ -27,7 +28,7 @@ public class InternalData extends Data {
public void save(CosmeticUser user) {
Player player = Bukkit.getPlayer(user.getUniqueId());
player.getPersistentDataContainer().set(key, PersistentDataType.STRING, steralizeData(user));
player.getPersistentDataContainer().set(key, PersistentDataType.STRING, serializeData(user));
}
@Override
@@ -38,7 +39,7 @@ public class InternalData extends Data {
if (!player.getPersistentDataContainer().has(key, PersistentDataType.STRING)) return user;
String rawData = player.getPersistentDataContainer().get(key, PersistentDataType.STRING);
Map<CosmeticSlot, Map<Cosmetic, Color>> a = desteralizedata(rawData);
Map<CosmeticSlot, Map<Cosmetic, Color>> a = deserializeData(user, rawData);
for (Map<Cosmetic, Color> cosmeticColors : a.values()) {
for (Cosmetic cosmetic : cosmeticColors.keySet()) {
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> {

View File

@@ -2,18 +2,15 @@ package com.hibiscusmc.hmccosmetics.database.types;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.DatabaseSettings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.*;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
public class MySQLData extends Data {
public class MySQLData extends SQLData {
// Connection Information
private String host;
@@ -22,6 +19,7 @@ public class MySQLData extends Data {
private String password;
private int port;
@Nullable
private Connection connection;
@Override
@@ -35,11 +33,12 @@ public class MySQLData extends Data {
HMCCosmeticsPlugin plugin = HMCCosmeticsPlugin.getInstance();
try {
openConnection();
if (connection == null) throw new NullPointerException("Connection is null");
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `COSMETICDATABASE` " +
"(UUID varchar(36) PRIMARY KEY, " +
"COSMETICS MEDIUMTEXT " +
");").execute();
} catch (SQLException e) {
} catch (SQLException | NullPointerException e) {
plugin.getLogger().severe("");
plugin.getLogger().severe("");
plugin.getLogger().severe("MySQL DATABASE CAN NOT BE REACHED.");
@@ -52,104 +51,58 @@ public class MySQLData extends Data {
throw new RuntimeException(e);
}
}
@Override
public void save(CosmeticUser user) {
Runnable run = () -> {
try {
PreparedStatement preparedSt = preparedStatement("REPLACE INTO COSMETICDATABASE(UUID,COSMETICS) VALUES(?,?);");
preparedSt.setString(1, user.getUniqueId().toString());
preparedSt.setString(2, steralizeData(user));
preparedSt.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
};
if (!HMCCosmeticsPlugin.isDisable()) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), run);
} else {
run.run();
}
}
@Override
public CosmeticUser get(UUID uniqueId) {
CosmeticUser user = new CosmeticUser(uniqueId);
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
try {
PreparedStatement preparedStatement = preparedStatement("SELECT * FROM COSMETICDATABASE WHERE UUID = ?;");
preparedStatement.setString(1, uniqueId.toString());
ResultSet rs = preparedStatement.executeQuery();
if (rs.next()) {
String rawData = rs.getString("COSMETICS");
Map<CosmeticSlot, Map<Cosmetic, Color>> cosmetics = desteralizedata(rawData);
for (Map<Cosmetic, Color> cosmeticColors : cosmetics.values()) {
for (Cosmetic cosmetic : cosmeticColors.keySet()) {
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> {
// This can not be async.
user.addPlayerCosmetic(cosmetic, cosmeticColors.get(cosmetic));
});
}
}
}
} catch (SQLException e) {
e.printStackTrace();
}
});
return user;
}
@Override
public void clear(UUID unqiueId) {
public void clear(UUID uniqueId) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
try {
PreparedStatement preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;");
preparedSt.setString(1, unqiueId.toString());
preparedSt.setString(1, uniqueId.toString());
preparedSt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
});
// TODO
}
private void openConnection() throws SQLException {
if (connection != null && !connection.isClosed()) {
return;
// Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
// ...
// });
// connection = DriverManager.getConnection("jdbc:mysql://" + DatabaseSettings.getHost() + ":" + DatabaseSettings.getPort() + "/" + DatabaseSettings.getDatabase(), setupProperties());
// Connection isn't null AND Connection isn't closed :: return
try {
if (isConnectionOpen()) {
return;
} else if (connection != null) close(); // Close connection if still active
} catch (RuntimeException e) {
e.printStackTrace(); // If isConnectionOpen() throws error
}
//Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
//close Connection if still active
if (connection != null) {
close();
}
//connect to database host
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database, setupProperties());
} catch (SQLException e) {
System.out.println(e.getMessage());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
//});
//connection = DriverManager.getConnection("jdbc:mysql://" + DatabaseSettings.getHost() + ":" + DatabaseSettings.getPort() + "/" + DatabaseSettings.getDatabase(), setupProperties());
// Connect to database host
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database, setupProperties());
} catch (SQLException e) {
System.out.println(e.getMessage());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public void close() {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
try {
if (connection == null) throw new NullPointerException("Connection is null");
connection.close();
} catch (SQLException e) {
} catch (SQLException | NullPointerException e) {
System.out.println(e.getMessage());
}
});
}
@NotNull
private Properties setupProperties() {
Properties props = new Properties();
props.put("user", user);
@@ -158,28 +111,29 @@ public class MySQLData extends Data {
return props;
}
private boolean isConnectionOpen() {
private boolean isConnectionOpen() throws RuntimeException {
try {
if (connection == null || connection.isClosed()) {
return false;
} else {
return true;
}
return connection != null && !connection.isClosed();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public PreparedStatement preparedStatement(String query) {
PreparedStatement ps = null;
if (!isConnectionOpen()) {
HMCCosmeticsPlugin.getInstance().getLogger().info("Connection is not open");
}
try {
if (connection == null) throw new NullPointerException("Connection is null");
ps = connection.prepareStatement(query);
} catch (SQLException e) {
} catch (SQLException | NullPointerException e) {
e.printStackTrace();
}
return ps;
}
}

View File

@@ -0,0 +1,68 @@
package com.hibiscusmc.hmccosmetics.database.types;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.UUID;
public abstract class SQLData extends Data {
@Override
@SuppressWarnings({"Duplicates", "resource"}) // Duplicate is from deprecated InternalData
public CosmeticUser get(UUID uniqueId) {
CosmeticUser user = new CosmeticUser(uniqueId);
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
try {
PreparedStatement preparedStatement = preparedStatement("SELECT * FROM COSMETICDATABASE WHERE UUID = ?;");
preparedStatement.setString(1, uniqueId.toString());
ResultSet rs = preparedStatement.executeQuery();
if (rs.next()) {
String rawData = rs.getString("COSMETICS");
Map<CosmeticSlot, Map<Cosmetic, Color>> cosmetics = deserializeData(user, rawData);
for (Map<Cosmetic, Color> cosmeticColors : cosmetics.values()) {
for (Cosmetic cosmetic : cosmeticColors.keySet()) {
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> {
// This can not be async.
user.addPlayerCosmetic(cosmetic, cosmeticColors.get(cosmetic));
});
}
}
}
} catch (SQLException e) {
e.printStackTrace();
}
});
return user;
}
@Override
@SuppressWarnings("resource")
public void save(CosmeticUser user) {
Runnable run = () -> {
try {
PreparedStatement preparedSt = preparedStatement("REPLACE INTO COSMETICDATABASE(UUID,COSMETICS) VALUES(?,?);");
preparedSt.setString(1, user.getUniqueId().toString());
preparedSt.setString(2, serializeData(user));
preparedSt.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
};
if (!HMCCosmeticsPlugin.isDisable()) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), run);
} else {
run.run();
}
}
public abstract PreparedStatement preparedStatement(String query);
}

View File

@@ -1,31 +1,28 @@
package com.hibiscusmc.hmccosmetics.database.types;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import java.io.File;
import java.io.IOException;
import java.sql.*;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
public class SQLiteData extends Data {
public class SQLiteData extends SQLData {
private Connection connection;
@Override
public void setup() {
File dataFolder = new File(HMCCosmeticsPlugin.getInstance().getDataFolder(), "database.db");
boolean exists = dataFolder.exists();
if (!dataFolder.exists()){
if (!exists) {
try {
dataFolder.createNewFile();
boolean created = dataFolder.createNewFile();
if (!created) throw new IOException("File didn't exist but now does");
} catch (IOException e) {
MessagesUtil.sendDebugMessages("File write error. Database will not work properly", Level.SEVERE);
}
@@ -39,66 +36,18 @@ public class SQLiteData extends Data {
"(UUID varchar(36) PRIMARY KEY, " +
"COSMETICS MEDIUMTEXT " +
");").execute();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void save(CosmeticUser user) {
Runnable run = () -> {
try {
PreparedStatement preparedSt = preparedStatement("REPLACE INTO COSMETICDATABASE(UUID,COSMETICS) VALUES(?,?);");
preparedSt.setString(1, user.getUniqueId().toString());
preparedSt.setString(2, steralizeData(user));
preparedSt.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
};
if (!HMCCosmeticsPlugin.isDisable()) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), run);
} else {
run.run();
}
}
@Override
public CosmeticUser get(UUID uniqueId) {
CosmeticUser user = new CosmeticUser(uniqueId);
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
try {
PreparedStatement preparedStatement = preparedStatement("SELECT * FROM COSMETICDATABASE WHERE UUID = ?;");
preparedStatement.setString(1, uniqueId.toString());
ResultSet rs = preparedStatement.executeQuery();
if (rs.next()) {
String rawData = rs.getString("COSMETICS");
Map<CosmeticSlot, Map<Cosmetic, Color>> cosmetics = desteralizedata(rawData);
for (Map<Cosmetic, Color> cosmeticColors : cosmetics.values()) {
for (Cosmetic cosmetic : cosmeticColors.keySet()) {
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> {
// This can not be async.
user.addPlayerCosmetic(cosmetic, cosmeticColors.get(cosmetic));
});
}
}
}
} catch (SQLException e) {
e.printStackTrace();
}
});
return user;
}
@Override
public void clear(UUID unqiueId) {
@SuppressWarnings("resource")
public void clear(UUID uniqueId) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
try {
PreparedStatement preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;");
preparedSt.setString(1, unqiueId.toString());
preparedSt.setString(1, uniqueId.toString());
preparedSt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
@@ -106,56 +55,47 @@ public class SQLiteData extends Data {
});
}
private void openConnection() throws SQLException {
if (connection != null && !connection.isClosed()) {
return;
}
//Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
// Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
// ...
// });
// connection = DriverManager.getConnection("jdbc:mysql://" + DatabaseSettings.getHost() + ":" + DatabaseSettings.getPort() + "/" + DatabaseSettings.getDatabase(), setupProperties());
//close Connection if still active
if (connection != null) {
//close();
}
if (connection != null && !connection.isClosed()) return;
// Close Connection if still active
File dataFolder = new File(HMCCosmeticsPlugin.getInstance().getDataFolder(), "database.db");
//connect to database host
// Connect to database host
try {
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection("jdbc:sqlite:" + dataFolder);
} catch (SQLException e) {
System.out.println(e.getMessage());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
//});
//connection = DriverManager.getConnection("jdbc:mysql://" + DatabaseSettings.getHost() + ":" + DatabaseSettings.getPort() + "/" + DatabaseSettings.getDatabase(), setupProperties());
}
@Override
public PreparedStatement preparedStatement(String query) {
PreparedStatement ps = null;
if (!isConnectionOpen()) {
HMCCosmeticsPlugin.getInstance().getLogger().info("Connection is not open");
}
try {
ps = connection.prepareStatement(query);
} catch (SQLException e) {
e.printStackTrace();
}
return ps;
}
private boolean isConnectionOpen() {
try {
if (connection == null || connection.isClosed()) {
return false;
} else {
return true;
}
return connection != null && !connection.isClosed();
} catch (SQLException e) {
throw new RuntimeException(e);
}

View File

@@ -1,121 +0,0 @@
package com.hibiscusmc.hmccosmetics.entities;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.nms.NMSHandlers;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.ticxo.modelengine.api.ModelEngineAPI;
import com.ticxo.modelengine.api.model.ActiveModel;
import com.ticxo.modelengine.api.model.ModeledEntity;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.UUID;
import java.util.logging.Level;
// This includes the Pufferfish (The Pufferfish that's what the player leashes to) and the model (MEGEntity)
public class BalloonEntity {
private final int balloonID;
private final UUID uniqueID;
private final Entity modelEntity;
private ModeledEntity modeledEntity;
public BalloonEntity(Location location) {
this.uniqueID = UUID.randomUUID();
this.balloonID = NMSHandlers.getHandler().getNextEntityId();
this.modelEntity = NMSHandlers.getHandler().getMEGEntity(location.add(Settings.getBalloonOffset()));
}
public void spawnModel(final String id, Color color) {
MessagesUtil.sendDebugMessages("Attempting Spawning for " + id);
if (ModelEngineAPI.api.getModelRegistry().getBlueprint(id) == null) {
MessagesUtil.sendDebugMessages("Invalid Model Engine Blueprint " + id, Level.SEVERE);
return;
}
ModeledEntity modeledEntity = ModelEngineAPI.getOrCreateModeledEntity(modelEntity);
ActiveModel model = ModelEngineAPI.createActiveModel(ModelEngineAPI.getBlueprint(id));
model.setCanHurt(false);
modeledEntity.addModel(model, false);
if (color != null) {
modeledEntity.getModels().forEach((d, singleModel) -> {
singleModel.getRendererHandler().setColor(color);
singleModel.getRendererHandler().update();
});
}
this.modeledEntity = modeledEntity;
}
public void remove() {
final ModeledEntity entity = ModelEngineAPI.api.getModeledEntity(modelEntity.getUniqueId());
if (entity == null) return;
for (final Player player : entity.getRangeManager().getPlayerInRange()) {
entity.hideFromPlayer(player);
}
//ModelEngineAPI.removeModeledEntity(megEntity.getUniqueId());
entity.destroy();
modelEntity.remove();
}
public void addPlayerToModel(final Player player, final String id) {
addPlayerToModel(player, id, null);
}
public void addPlayerToModel(final Player player, final String id, Color color) {
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(modelEntity.getUniqueId());
if (model == null) {
spawnModel(id, color);
MessagesUtil.sendDebugMessages("model is null");
return;
}
//if (model.getRangeManager().getPlayerInRange().contains(player)) return;
model.showToPlayer(player);
MessagesUtil.sendDebugMessages("Show to player");
}
public void removePlayerFromModel(final Player player) {
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(modelEntity.getUniqueId());
if (model == null) return;
model.hideFromPlayer(player);
MessagesUtil.sendDebugMessages("Hidden from player");
}
public Entity getModelEntity() {
return this.modelEntity;
}
public int getPufferfishBalloonId() {
return balloonID;
}
public UUID getPufferfishBalloonUniqueId() {
return uniqueID;
}
public UUID getModelUnqiueId() {
return getModelEntity().getUniqueId();
}
public int getModelId() {
return getModelEntity().getEntityId();
}
public Location getLocation() {
return this.getModelEntity().getLocation();
}
public void setLocation(Location location) {
this.getModelEntity().teleport(location);
}
public void setVelocity(Vector vector) {
this.getModelEntity().setVelocity(vector);
}
}

View File

@@ -5,7 +5,6 @@ import com.hibiscusmc.hmccosmetics.api.PlayerMenuOpenEvent;
import com.hibiscusmc.hmccosmetics.config.serializer.ItemSerializer;
import com.hibiscusmc.hmccosmetics.gui.type.Type;
import com.hibiscusmc.hmccosmetics.gui.type.Types;
import com.hibiscusmc.hmccosmetics.hooks.PAPIHook;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.misc.Adventure;
@@ -13,13 +12,13 @@ import com.hibiscusmc.hmccosmetics.util.misc.Placeholder;
import dev.triumphteam.gui.builder.item.ItemBuilder;
import dev.triumphteam.gui.guis.Gui;
import dev.triumphteam.gui.guis.GuiItem;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
@@ -28,13 +27,13 @@ import java.util.List;
public class Menu {
private String id;
private String title;
private int rows;
private ConfigurationNode config;
private String permissionNode;
private final String id;
private final String title;
private final int rows;
private final ConfigurationNode config;
private final String permissionNode;
public Menu(String id, ConfigurationNode config) {
public Menu(String id, @NotNull ConfigurationNode config) {
this.id = id;
this.config = config;
@@ -61,7 +60,7 @@ public class Menu {
openMenu(user, false);
}
public void openMenu(CosmeticUser user, boolean ignorePermission) {
public void openMenu(@NotNull CosmeticUser user, boolean ignorePermission) {
Player player = user.getPlayer();
if (player == null) return;
if (!ignorePermission && !permissionNode.isEmpty()) {
@@ -100,7 +99,8 @@ public class Menu {
}
private Gui getItems(CosmeticUser user, Gui gui) {
@Contract("_, _ -> param2")
private Gui getItems(@NotNull CosmeticUser user, Gui gui) {
Player player = user.getPlayer();
for (ConfigurationNode config : config.node("items").childrenMap().values()) {
@@ -137,8 +137,6 @@ public class Menu {
MessagesUtil.sendDebugMessages("something went wrong! " + item);
continue;
}
ItemStack originalItem = item.clone();
item = updateLore(player, item);
Type type = null;
@@ -147,6 +145,9 @@ public class Menu {
if (Types.isType(typeId)) type = Types.getType(typeId);
}
ItemStack originalItem = item.clone();
item = updateLore(user, item, type, config);
GuiItem guiItem = ItemBuilder.from(item).asGuiItem();
Type finalType = type;
@@ -155,7 +156,7 @@ public class Menu {
if (finalType != null) finalType.run(user, config, clickType);
for (int i : slots) {
gui.updateItem(i, updateLore(player, originalItem.clone()));
gui.updateItem(i, updateLore(user, originalItem.clone(), finalType, config));
MessagesUtil.sendDebugMessages("Updated slot " + i);
}
});
@@ -166,7 +167,8 @@ public class Menu {
return gui;
}
private List<Integer> getSlots(List<String> slotString) {
@NotNull
private List<Integer> getSlots(@NotNull List<String> slotString) {
List<Integer> slots = new ArrayList<>();
for (String a : slotString) {
@@ -183,6 +185,7 @@ public class Menu {
return slots;
}
@NotNull
private List<Integer> getSlots(int small, int max) {
List<Integer> slots = new ArrayList<>();
@@ -190,21 +193,11 @@ public class Menu {
return slots;
}
private ItemStack updateLore(Player player, ItemStack itemStack) {
@Contract("_, _, _, _ -> param2")
@NotNull
private ItemStack updateLore(CosmeticUser user, @NotNull ItemStack itemStack, Type type, ConfigurationNode config) {
if (itemStack.hasItemMeta()) {
List<String> processedLore = new ArrayList<>();
if (PAPIHook.isPAPIEnabled()) {
if (itemStack.getItemMeta().hasLore()) {
for (String loreLine : itemStack.getItemMeta().getLore()) {
processedLore.add(PlaceholderAPI.setPlaceholders(player, loreLine));
}
}
}
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.setLore(processedLore);
itemStack.setItemMeta(itemMeta);
itemStack.setItemMeta(type.setLore(user, config, itemStack.getItemMeta()));
}
return itemStack;
}
@@ -215,7 +208,6 @@ public class Menu {
public boolean canOpen(Player player) {
if (permissionNode.isEmpty()) return true;
if (player.isOp() || player.hasPermission(permissionNode)) return true;
return false;
return player.isOp() || player.hasPermission(permissionNode);
}
}

View File

@@ -4,6 +4,8 @@ import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.apache.commons.io.FilenameUtils;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.CommentedConfigurationNode;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
@@ -17,21 +19,23 @@ import java.util.logging.Level;
public class Menus {
private static HashMap<String, Menu> MENUS = new HashMap<>();
private static final HashMap<String, Menu> MENUS = new HashMap<>();
public static void addMenu(Menu menu) {
MENUS.put(menu.getId().toUpperCase(), menu);
}
public static Menu getMenu(String id) {
public static Menu getMenu(@NotNull String id) {
return MENUS.get(id.toUpperCase());
}
@Contract(pure = true)
@NotNull
public static Collection<Menu> getMenu() {
return MENUS.values();
}
public static boolean hasMenu(String id) {
public static boolean hasMenu(@NotNull String id) {
return MENUS.containsKey(id.toUpperCase());
}
@@ -39,6 +43,9 @@ public class Menus {
return MENUS.containsValue(menu);
}
public static Menu getDefaultMenu() { return Menus.getMenu(Settings.getDefaultMenu()); }
@NotNull
public static List<String> getMenuNames() {
List<String> names = new ArrayList<>();

View File

@@ -1,12 +1,13 @@
package com.hibiscusmc.hmccosmetics.gui.action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.jetbrains.annotations.NotNull;
public class Action {
public abstract class Action {
private String id;
private final String id;
public Action(String id) {
public Action(@NotNull String id) {
this.id = id.toUpperCase();
Actions.addAction(this);
}
@@ -15,7 +16,5 @@ public class Action {
return this.id;
}
public void run(CosmeticUser user, String raw) {
// Override
}
public abstract void run(CosmeticUser user, String raw);
}

View File

@@ -4,27 +4,36 @@ import com.hibiscusmc.hmccosmetics.gui.action.actions.*;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.List;
@SuppressWarnings("unused")
public class Actions {
private static HashMap<String, Action> actions = new HashMap<>();
private static final HashMap<String, Action> actions = new HashMap<>();
// [ID]
private static ActionMessage ACTION_MESSAGE = new ActionMessage();
private static ActionMenu ACTION_MENU = new ActionMenu();
private static ActionPlayerCommand ACTION_CONSOLE_COMMAND = new ActionPlayerCommand();
private static ActionConsoleCommand ACTION_PLAYER_COMMAND = new ActionConsoleCommand();
private static ActionCloseMenu ACTION_EXIT_MENU = new ActionCloseMenu();
private static final ActionMessage ACTION_MESSAGE = new ActionMessage();
private static final ActionMenu ACTION_MENU = new ActionMenu();
private static final ActionPlayerCommand ACTION_CONSOLE_COMMAND = new ActionPlayerCommand();
private static final ActionConsoleCommand ACTION_PLAYER_COMMAND = new ActionConsoleCommand();
private static final ActionCloseMenu ACTION_EXIT_MENU = new ActionCloseMenu();
private static final ActionSound ACTION_SOUND = new ActionSound();
private static final ActionEquip ACTION_EQUIP = new ActionEquip();
private static final ActionUnequip ACTION_UNEQUIP = new ActionUnequip();
private static final ActionParticle ACTION_PARTICLE = new ActionParticle();
private static final ActionCosmeticShow ACTION_SHOW = new ActionCosmeticShow();
private static final ActionCosmeticHide ACTION_HIDE = new ActionCosmeticHide();
private static final ActionCosmeticToggle ACTION_TOGGLE = new ActionCosmeticToggle();
public static Action getAction(String id) {
public static Action getAction(@NotNull String id) {
return actions.get(id.toUpperCase());
}
public static boolean isAction(String id) {
public static boolean isAction(@NotNull String id) {
return actions.containsKey(id.toUpperCase());
}
@@ -32,11 +41,11 @@ public class Actions {
actions.put(action.getId().toUpperCase(), action);
}
public static void runActions(CosmeticUser user, List<String> raw) {
public static void runActions(CosmeticUser user, @NotNull List<String> raw) {
for (String a : raw) {
String id = StringUtils.substringBetween(a, "[", "]").toUpperCase();
String message = StringUtils.substringAfter(a, "] ");
MessagesUtil.sendDebugMessages("ID is " + id + " // Message is " + message);
MessagesUtil.sendDebugMessages("ID is " + id + " // Raw Data is " + message);
if (isAction(id)) {
getAction(id).run(user, message);
} else {

View File

@@ -2,6 +2,7 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.jetbrains.annotations.NotNull;
public class ActionCloseMenu extends Action {
@@ -10,7 +11,7 @@ public class ActionCloseMenu extends Action {
}
@Override
public void run(CosmeticUser user, String raw) {
public void run(@NotNull CosmeticUser user, String raw) {
user.getPlayer().closeInventory();
}
}

View File

@@ -3,6 +3,7 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.jetbrains.annotations.NotNull;
public class ActionConsoleCommand extends Action {
@@ -11,8 +12,7 @@ public class ActionConsoleCommand extends Action {
}
@Override
public void run(CosmeticUser user, String raw) {
public void run(@NotNull CosmeticUser user, String raw) {
HMCCosmeticsPlugin.getInstance().getServer().dispatchCommand(user.getPlayer(), raw);
}
}

View File

@@ -0,0 +1,18 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.jetbrains.annotations.NotNull;
public class ActionCosmeticHide extends Action {
public ActionCosmeticHide() {
super("hide");
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
if (user.getHidden()) return;
user.hideCosmetics(CosmeticUser.HiddenReason.ACTION);
}
}

View File

@@ -0,0 +1,21 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.jetbrains.annotations.NotNull;
public class ActionCosmeticShow extends Action {
public ActionCosmeticShow() {
super("show");
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
if (!user.getHidden()) return;
// Do not hide if it's already off for WG
if (user.getHiddenReason() != CosmeticUser.HiddenReason.ACTION && user.getHiddenReason() != CosmeticUser.HiddenReason.COMMAND) return;
user.showCosmetics();
}
}

View File

@@ -0,0 +1,23 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.jetbrains.annotations.NotNull;
public class ActionCosmeticToggle extends Action {
public ActionCosmeticToggle() {
super("toggle");
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
if (user.getHidden()) {
if (user.getHiddenReason() != CosmeticUser.HiddenReason.ACTION && user.getHiddenReason() != CosmeticUser.HiddenReason.COMMAND) return;
user.showCosmetics();
return;
}
user.hideCosmetics(CosmeticUser.HiddenReason.ACTION);
}
}

View File

@@ -0,0 +1,21 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
public class ActionEquip extends Action {
public ActionEquip() {
super("equip");
}
@Override
public void run(CosmeticUser user, String raw) {
Cosmetic cosmetic = Cosmetics.getCosmetic(raw);
if (cosmetic == null) return;
user.addPlayerCosmetic(cosmetic);
}
}

View File

@@ -5,6 +5,9 @@ import com.hibiscusmc.hmccosmetics.gui.Menu;
import com.hibiscusmc.hmccosmetics.gui.Menus;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import java.util.logging.Level;
public class ActionMenu extends Action {
@@ -14,11 +17,22 @@ public class ActionMenu extends Action {
@Override
public void run(CosmeticUser user, String raw) {
boolean ignorePermission = false;
raw = raw.replaceAll(" ", ""); // Removes all spaces
if (raw.contains("-o")) {
raw = raw.replaceAll("-o", "");
ignorePermission = true;
}
if (!Menus.hasMenu(raw)) {
HMCCosmeticsPlugin.getInstance().getLogger().info("Invalid Action Menu -> " + raw);
MessagesUtil.sendDebugMessages("Invalid Action Menu -> " + raw, Level.WARNING);
return;
}
Menu menu = Menus.getMenu(raw);
menu.openMenu(user, true);
MessagesUtil.sendDebugMessages(raw + " | " + ignorePermission);
menu.openMenu(user, ignorePermission);
}
}

View File

@@ -3,6 +3,7 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.jetbrains.annotations.NotNull;
public class ActionMessage extends Action {
@@ -11,7 +12,7 @@ public class ActionMessage extends Action {
}
@Override
public void run(CosmeticUser user, String raw) {
public void run(@NotNull CosmeticUser user, String raw) {
MessagesUtil.sendMessageNoKey(user.getPlayer(), raw);
}
}

View File

@@ -0,0 +1,51 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.ServerUtils;
import com.hibiscusmc.hmccosmetics.util.packets.PacketManager;
import com.owen1212055.particlehelper.api.particle.types.BlockDataParticle;
import com.owen1212055.particlehelper.api.particle.types.DestinationParticle;
import com.owen1212055.particlehelper.api.particle.types.velocity.VelocityParticle;
import com.owen1212055.particlehelper.api.particle.types.vibration.VibrationParticle;
import com.owen1212055.particlehelper.api.type.ParticleType;
import com.owen1212055.particlehelper.api.type.Particles;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class ActionParticle extends Action {
public ActionParticle() {
super("particle");
}
@Override
@SuppressWarnings("ConstantConditions")
public void run(CosmeticUser user, @NotNull String raw) {
String[] rawString = raw.split(" ");
ParticleType<?, ?> particleType = Particles.fromKey(NamespacedKey.minecraft(rawString[0].toLowerCase()));
if (particleType == null) {
MessagesUtil.sendDebugMessages("The particle " + rawString[0] + " does not exist!");
return;
}
// particleType.multi() should never be null, but particleType can be.
boolean multi = particleType.multi() != null;
var particle = multi ? particleType.multi() : particleType.single();
if (particle instanceof DestinationParticle || particle instanceof BlockDataParticle
|| particle instanceof VibrationParticle || particle instanceof VelocityParticle) {
MessagesUtil.sendDebugMessages("The particle " + rawString[0] + " is not supported by this action!");
return;
}
particle = ServerUtils.addParticleValues(particle, rawString);
Location location = user.getPlayer().getLocation();
for (Player player : PacketManager.getViewers(location)) {
particle.compile().send(player, location);
}
}
}

View File

@@ -3,6 +3,7 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.jetbrains.annotations.NotNull;
public class ActionPlayerCommand extends Action {
@@ -11,7 +12,7 @@ public class ActionPlayerCommand extends Action {
}
@Override
public void run(CosmeticUser user, String raw) {
public void run(@NotNull CosmeticUser user, String raw) {
user.getPlayer().performCommand(MessagesUtil.processStringNoKeyString(user.getPlayer(), raw));
}
}

View File

@@ -0,0 +1,36 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.logging.Level;
public class ActionSound extends Action {
// [SOUND] minecraft:test 1 1
public ActionSound() {
super("sound");
}
@Override
public void run(@NotNull CosmeticUser user, @NotNull String raw) {
Player player = user.getPlayer();
String[] processedString = raw.split(" ");
String soundName = processedString[0];
float volume = 1;
float pitch = 1;
if (processedString.length > 2) {
volume = Float.parseFloat(processedString[1]);
pitch = Float.parseFloat(processedString[2]);
}
MessagesUtil.sendDebugMessages("Attempting to play " + soundName, Level.INFO);
player.playSound(player.getLocation(), soundName, volume, pitch);
}
}

View File

@@ -0,0 +1,21 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.apache.commons.lang3.EnumUtils;
public class ActionUnequip extends Action {
public ActionUnequip() {
super("unequip");
}
@Override
public void run(CosmeticUser user, String raw) {
if (!EnumUtils.isValidEnum(CosmeticSlot.class, raw)) return;
CosmeticSlot slot = CosmeticSlot.valueOf(raw);
user.removeCosmeticSlot(slot);
}
}

View File

@@ -6,6 +6,7 @@ import com.hibiscusmc.hmccolor.gui.guis.GuiItem;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.hooks.Hooks;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.misc.Placeholder;
import org.bukkit.Bukkit;
@@ -15,34 +16,38 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.MapMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.jetbrains.annotations.NotNull;
public class DyeMenu {
// Yes, I do know how tacted on this feels.
public static void openMenu(CosmeticUser user, Cosmetic cosmetic) {
public static void openMenu(@NotNull CosmeticUser user, Cosmetic cosmetic) {
Player player = user.getPlayer();
if (player == null) return;
if (!Hooks.isActiveHook("HMCColor")) {
addCosmetic(user, cosmetic, null);
return;
}
ItemStack originalItem = user.getUserCosmeticItem(cosmetic);
if (originalItem == null || !cosmetic.isDyable()) return;
Player player = user.getPlayer();
Gui gui = HMCColorApi.INSTANCE.colorMenu();
gui.updateTitle(Placeholder.applyPapiPlaceholders(player, Settings.getDyeMenuName()));
gui.setItem(19, new GuiItem(originalItem));
gui.setItem(Settings.getDyeMenuInputSlot(), new GuiItem(originalItem));
gui.setDefaultTopClickAction(event -> {
if (event.getSlot() == 25) {
ItemStack item = event.getInventory().getItem(25);
if (event.getSlot() == Settings.getDyeMenuOutputSlot()) {
ItemStack item = event.getInventory().getItem(Settings.getDyeMenuOutputSlot());
if (item == null) return;
ItemMeta meta = item.getItemMeta();
if (meta == null) return;
Color color = meta instanceof LeatherArmorMeta ? ((LeatherArmorMeta) meta).getColor() :
meta instanceof PotionMeta ? ((PotionMeta) meta).getColor() : null;
Color color = meta instanceof LeatherArmorMeta leatherMeta ? leatherMeta.getColor() :
meta instanceof PotionMeta potionMeta ? potionMeta.getColor() :
meta instanceof MapMeta mapMeta ? mapMeta.getColor() : null;
if (color == null) return;
//user.removeCosmeticSlot(cosmetic);
user.addPlayerCosmetic(cosmetic, color);
player.setItemOnCursor(new ItemStack(Material.AIR));
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), player::closeInventory, 2);
addCosmetic(user, cosmetic, color);
} else event.setCancelled(true);
});
@@ -50,4 +55,14 @@ public class DyeMenu {
gui.setCloseGuiAction(event -> {});
gui.open(player);
}
private static void addCosmetic(@NotNull CosmeticUser user, Cosmetic cosmetic, Color color) {
Player player = user.getPlayer();
user.addPlayerCosmetic(cosmetic, color);
player.setItemOnCursor(new ItemStack(Material.AIR));
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
player.closeInventory();
user.updateCosmetic(cosmetic.getSlot());
}, 2);
}
}

View File

@@ -5,9 +5,9 @@ import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.meta.ItemMeta;
import org.spongepowered.configurate.ConfigurationNode;
public class Type {
public abstract class Type {
private String id;
private final String id;
public Type(String id) {
this.id = id;
@@ -21,12 +21,8 @@ public class Type {
public void run(CosmeticUser user, ConfigurationNode config) {
run(user, config, null);
}
public void run(CosmeticUser user, ConfigurationNode config, ClickType clickType) {
// Override
}
public ItemMeta setLore(CosmeticUser user, ConfigurationNode config, ItemMeta itemMeta) {
//TODO: Finish this
return null; // Override
}
public abstract void run(CosmeticUser user, ConfigurationNode config, ClickType clickType);
public abstract ItemMeta setLore(CosmeticUser user, ConfigurationNode config, ItemMeta itemMeta);
}

View File

@@ -2,21 +2,22 @@ package com.hibiscusmc.hmccosmetics.gui.type;
import com.hibiscusmc.hmccosmetics.gui.type.types.TypeCosmetic;
import com.hibiscusmc.hmccosmetics.gui.type.types.TypeEmpty;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
public class Types {
private static HashMap<String, Type> types = new HashMap<>();
private static final HashMap<String, Type> types = new HashMap<>();
private static TypeCosmetic TYPE_COSMETIC = new TypeCosmetic();
private static TypeEmpty TYPE_EMPTY = new TypeEmpty();
public static Type getType(String id) {
public static Type getType(@NotNull String id) {
return types.get(id.toUpperCase());
}
public static boolean isType(String id) {
public static boolean isType(@NotNull String id) {
return types.containsKey(id.toUpperCase());
}

View File

@@ -1,18 +1,31 @@
package com.hibiscusmc.hmccosmetics.gui.type.types;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType;
import com.hibiscusmc.hmccosmetics.gui.action.Actions;
import com.hibiscusmc.hmccosmetics.gui.special.DyeMenu;
import com.hibiscusmc.hmccosmetics.gui.type.Type;
import com.hibiscusmc.hmccosmetics.hooks.Hooks;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.misc.StringUtils;
import com.hibiscusmc.hmccosmetics.util.misc.Utils;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class TypeCosmetic extends Type {
@@ -21,17 +34,18 @@ public class TypeCosmetic extends Type {
}
@Override
public void run(CosmeticUser user, ConfigurationNode config, ClickType clickType) {
public void run(CosmeticUser user, @NotNull ConfigurationNode config, ClickType clickType) {
if (config.node("cosmetic").virtual()) return;
String cosmeticName = config.node("cosmetic").getString();
Cosmetic cosmetic = Cosmetics.getCosmetic(cosmeticName);
Player player = user.getPlayer();
if (cosmetic == null) {
MessagesUtil.sendMessage(user.getPlayer(), "invalid-cosmetic");
MessagesUtil.sendMessage(player, "invalid-cosmetic");
return;
}
if (!user.canEquipCosmetic(cosmetic)) {
MessagesUtil.sendMessage(user.getPlayer(), "no-cosmetic-permission");
MessagesUtil.sendMessage(player, "no-cosmetic-permission");
return;
}
@@ -70,7 +84,84 @@ public class TypeCosmetic extends Type {
} catch (SerializationException e) {
throw new RuntimeException(e);
}
// Fixes issue with offhand cosmetics not appearing. Yes, I know this is dumb
Runnable run = () -> user.updateCosmetic(cosmetic.getSlot());
if (cosmetic instanceof CosmeticArmorType) {
if (((CosmeticArmorType) cosmetic).getEquipSlot().equals(EquipmentSlot.OFF_HAND)) {
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), run, 1);
return;
}
}
run.run();
}
user.updateCosmetic(cosmetic.getSlot());
@Override
public ItemMeta setLore(CosmeticUser user, @NotNull ConfigurationNode config, ItemMeta itemMeta) {
List<String> processedLore = new ArrayList<>();
if (config.node("cosmetic").virtual()) return processLoreLines(user, itemMeta);;
String cosmeticName = config.node("cosmetic").getString();
Cosmetic cosmetic = Cosmetics.getCosmetic(cosmeticName);
if (cosmetic == null) {
return processLoreLines(user, itemMeta);
}
if (user.canEquipCosmetic(cosmetic)) {
return processLoreLines(user, itemMeta);
} else {
ConfigurationNode itemConfig = config.node("item");
if (itemConfig.virtual()) return itemMeta;
if (itemConfig.node("locked-name").virtual() && itemConfig.node("locked-lore").virtual()) {
return processLoreLines(user, itemMeta);
}
try {
List<String> lockedLore = itemMeta.getLore();
String lockedName = itemMeta.getDisplayName();
if (!itemConfig.node("locked-lore").virtual()) {
lockedLore = Utils.replaceIfNull(itemConfig.node("locked-lore").getList(String.class),
new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
}
if (!itemConfig.node("locked-name").virtual()) {
lockedName = StringUtils.parseStringToString(Utils.replaceIfNull(itemConfig.node("locked-name").getString(), ""));
}
if (Hooks.isActiveHook("PlaceHolderAPI")) {
lockedName = PlaceholderAPI.setPlaceholders(user.getPlayer(), lockedName);
}
itemMeta.setDisplayName(lockedName);
if (itemMeta.hasLore()) {
itemMeta.getLore().clear();
for (String loreLine : lockedLore) {
if (Hooks.isActiveHook("PlaceHolderAPI")) loreLine = PlaceholderAPI.setPlaceholders(user.getPlayer(), loreLine);
processedLore.add(loreLine);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
itemMeta.setLore(processedLore);
return itemMeta;
}
@Contract("_, _ -> param2")
@NotNull
@SuppressWarnings("Duplicates")
private ItemMeta processLoreLines(CosmeticUser user, @NotNull ItemMeta itemMeta) {
List<String> processedLore = new ArrayList<>();
if (itemMeta.hasLore()) {
for (String loreLine : itemMeta.getLore()) {
if (Hooks.isActiveHook("PlaceholderAPI"))
loreLine = PlaceholderAPI.setPlaceholders(user.getPlayer(), loreLine);
processedLore.add(loreLine);
}
}
itemMeta.setLore(processedLore);
return itemMeta;
}
}

View File

@@ -2,8 +2,12 @@ package com.hibiscusmc.hmccosmetics.gui.type.types;
import com.hibiscusmc.hmccosmetics.gui.action.Actions;
import com.hibiscusmc.hmccosmetics.gui.type.Type;
import com.hibiscusmc.hmccosmetics.hooks.Hooks;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
@@ -13,7 +17,6 @@ import java.util.List;
public class TypeEmpty extends Type {
// This can be used as an example for making your own types.
public TypeEmpty() {
super("empty");
// This is an empty type, meaning, when a menu item has a type of "empty" it will run the code in the method run.
@@ -21,7 +24,7 @@ public class TypeEmpty extends Type {
// This is the code that's run when the item is clicked.
@Override
public void run(CosmeticUser user, ConfigurationNode config, ClickType clickType) {
public void run(CosmeticUser user, @NotNull ConfigurationNode config, ClickType clickType) {
List<String> actionStrings = new ArrayList<>(); // List where we keep the actions the server will execute.
ConfigurationNode actionConfig = config.node("actions"); // Configuration node that actions are under.
@@ -29,7 +32,7 @@ public class TypeEmpty extends Type {
try {
// This gets the actions with the item. We can add more, such as with the Cosmetic type, an equip and unequip action set.
// We add that to a List of Strings, before running those actions through the server. This is not the area where we deal
// with actions, mearly what should be done for each item.
// with actions, merely what should be done for each item.
if (!actionConfig.node("any").virtual()) actionStrings.addAll(actionConfig.node("any").getList(String.class));
if (clickType != null) {
@@ -48,6 +51,22 @@ public class TypeEmpty extends Type {
}
}
@Override
@SuppressWarnings("Duplicates")
public ItemMeta setLore(CosmeticUser user, ConfigurationNode config, @NotNull ItemMeta itemMeta) {
List<String> processedLore = new ArrayList<>();
if (itemMeta.hasLore()) {
for (String loreLine : itemMeta.getLore()) {
if (Hooks.isActiveHook("PlaceholderAPI"))
loreLine = PlaceholderAPI.setPlaceholders(user.getPlayer(), loreLine);
processedLore.add(loreLine);
}
}
return itemMeta;
}
// That's it! Now, add it as a static in another one of your classes (such as your main class) and you are good to go.
// If you need help with that, check the Types class.
}

View File

@@ -0,0 +1,46 @@
package com.hibiscusmc.hmccosmetics.hooks;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
public class Hook implements Listener {
private final String id;
private boolean active;
private boolean itemHook;
public Hook(String id) {
this.id = id;
active = false;
Hooks.addHook(this);
}
public void load() {
// Override
}
public ItemStack getItem(String itemId) {
return null;
// Override
}
public String getId() {
return id;
}
public void setActive(boolean active) {
this.active = active;
}
public boolean getActive() {
return this.active;
}
public void setEnabledItemHook(boolean enabled) {
itemHook = enabled;
}
public boolean hasEnabledItemHook() {
return itemHook;
}
}

View File

@@ -0,0 +1,79 @@
package com.hibiscusmc.hmccosmetics.hooks;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.hooks.items.*;
import com.hibiscusmc.hmccosmetics.hooks.misc.HookCMI;
import com.hibiscusmc.hmccosmetics.hooks.misc.HookHMCColor;
import com.hibiscusmc.hmccosmetics.hooks.misc.HookPremiumVanish;
import com.hibiscusmc.hmccosmetics.hooks.misc.HookSuperVanish;
import com.hibiscusmc.hmccosmetics.hooks.placeholders.HookPlaceholderAPI;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
public class Hooks {
private static final HashMap<String, Hook> hooks = new HashMap<>();
private static HookOraxen ORAXEN_HOOK = new HookOraxen();
private static HookItemAdder ITEMADDER_HOOK = new HookItemAdder();
private static HookLooty LOOTY_HOOK = new HookLooty();
private static HookMythic MYTHIC_HOOK = new HookMythic();
private static HookHMCCosmetics HMCCOSMETIC_HOOK = new HookHMCCosmetics();
private static HookPlaceholderAPI PAPI_HOOK = new HookPlaceholderAPI();
private static HookPremiumVanish PREMIUM_VANISH_HOOK = new HookPremiumVanish();
private static HookSuperVanish SUPER_VANISH_HOOK = new HookSuperVanish();
private static HookHMCColor HMC_COLOR_HOOK = new HookHMCColor();
private static HookCMI CMI_HOOK = new HookCMI();
public static Hook getHook(@NotNull String id) {
return hooks.get(id.toLowerCase());
}
public static boolean isItemHook(@NotNull String id) {
return hooks.containsKey(id.toLowerCase());
}
public static void addHook(Hook hook) {
hooks.put(hook.getId().toLowerCase(), hook);
}
public static void setup() {
for (Hook hook : hooks.values()) {
if (Bukkit.getPluginManager().getPlugin(hook.getId()) != null) {
HMCCosmeticsPlugin.getInstance().getServer().getPluginManager().registerEvents(hook, HMCCosmeticsPlugin.getInstance());
hook.setActive(true);
hook.load();
HMCCosmeticsPlugin.getInstance().getLogger().info("Successfully hooked into " + hook.getId());
}
}
}
@Nullable
public static ItemStack getItem(@NotNull String raw) {
if (!raw.contains(":")) {
Material mat = Material.getMaterial(raw.toUpperCase());
if (mat == null) return null;
return new ItemStack(mat);
}
// Ex. Oraxen:BigSword
// split[0] is the plugin name
// split[1] is the item name
String[] split = raw.split(":", 2);
if (!isItemHook(split[0])) return null;
Hook hook = getHook(split[0]);
if (!hook.hasEnabledItemHook()) return null;
if (!hook.getActive()) return null;
return hook.getItem(split[1]);
}
public static boolean isActiveHook(String id) {
Hook hook = getHook(id);
if (hook == null) return false;
return hook.getActive();
}
}

View File

@@ -2,18 +2,20 @@ package com.hibiscusmc.hmccosmetics.hooks.items;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.hooks.Hook;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
public class HMCCosmeticsHook extends ItemHook implements Listener {
public class HookHMCCosmetics extends Hook implements Listener {
public HMCCosmeticsHook() {
public HookHMCCosmetics() {
super("HMCCosmetics");
setEnabledItemHook(true);
}
@Override
public ItemStack get(String itemid) {
Cosmetic cosmetic = Cosmetics.getCosmetic(itemid);
public ItemStack getItem(String itemId) {
Cosmetic cosmetic = Cosmetics.getCosmetic(itemId);
if (cosmetic == null) return null;
return cosmetic.getItem();
}

View File

@@ -1,6 +1,8 @@
package com.hibiscusmc.hmccosmetics.hooks.items;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.hooks.Hook;
import dev.lone.itemsadder.api.CustomStack;
import dev.lone.itemsadder.api.Events.ItemsAdderLoadDataEvent;
import org.bukkit.Material;
@@ -8,20 +10,19 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
public class ItemAdderHook extends ItemHook implements Listener {
// I hate IA, this overcomplicate stuff is so unneeded if it just did its stuff when its needed.
public class HookItemAdder extends Hook implements Listener {
private boolean enabled = false;
public ItemAdderHook() {
public HookItemAdder() {
super("itemsadder");
setEnabledItemHook(true);
}
@Override
public ItemStack get(String itemid) {
public ItemStack getItem(String itemId) {
if (enabled) {
CustomStack stack = CustomStack.getInstance(itemid);
CustomStack stack = CustomStack.getInstance(itemId);
if (stack == null) return null;
return stack.getItemStack();
} else {
@@ -31,6 +32,7 @@ public class ItemAdderHook extends ItemHook implements Listener {
@EventHandler
public void onItemAdderDataLoad(ItemsAdderLoadDataEvent event) {
if (enabled && !Settings.getItemsAdderReloadChange()) return; // Defaultly it will only run once at startup. If hook setting is enable
this.enabled = true;
HMCCosmeticsPlugin.setup();
}

View File

@@ -0,0 +1,22 @@
package com.hibiscusmc.hmccosmetics.hooks.items;
import com.hibiscusmc.hmccosmetics.hooks.Hook;
import com.mineinabyss.geary.prefabs.PrefabKey;
import com.mineinabyss.looty.LootyFactory;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
public class HookLooty extends Hook implements Listener {
public HookLooty() {
super("looty");
setEnabledItemHook(true);
}
@Override
public ItemStack getItem(String itemId) {
PrefabKey prefabKey = PrefabKey.Companion.ofOrNull(itemId);
if (prefabKey == null) return null;
return LootyFactory.INSTANCE.createFromPrefab(prefabKey);
}
}

View File

@@ -1,16 +1,18 @@
package com.hibiscusmc.hmccosmetics.hooks.items;
import com.hibiscusmc.hmccosmetics.hooks.Hook;
import io.lumine.mythic.bukkit.MythicBukkit;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
public class MythicHook extends ItemHook implements Listener {
public MythicHook() {
public class HookMythic extends Hook implements Listener {
public HookMythic() {
super("mythicmobs");
setEnabledItemHook(true);
}
@Override
public ItemStack get(String itemid) {
return MythicBukkit.inst().getItemManager().getItemStack(itemid);
public ItemStack getItem(String itemId) {
return MythicBukkit.inst().getItemManager().getItemStack(itemId);
}
}

View File

@@ -0,0 +1,22 @@
package com.hibiscusmc.hmccosmetics.hooks.items;
import com.hibiscusmc.hmccosmetics.hooks.Hook;
import io.th0rgal.oraxen.api.OraxenItems;
import io.th0rgal.oraxen.items.ItemBuilder;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
public class HookOraxen extends Hook implements Listener {
public HookOraxen() {
super("oraxen");
setEnabledItemHook(true);
}
@Override
public ItemStack getItem(String itemId) {
ItemBuilder builder = OraxenItems.getItemById(itemId);
if (builder == null) return null;
return builder.build();
}
}

View File

@@ -1,33 +0,0 @@
package com.hibiscusmc.hmccosmetics.hooks.items;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
public class ItemHook implements Listener {
private String id;
private boolean active;
public ItemHook(String id) {
this.id = id;
active = false;
ItemHooks.addItemHook(this);
}
public ItemStack get(String itemid) {
return null;
// Override
}
public String getId() {
return id;
}
public void setActive(boolean active) {
this.active = active;
}
public boolean getActive() {
return this.active;
}
}

View File

@@ -1,57 +0,0 @@
package com.hibiscusmc.hmccosmetics.hooks.items;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
public class ItemHooks {
private static HashMap<String, ItemHook> itemHooks = new HashMap<>();
private static OraxenHook ORAXEN_HOOK = new OraxenHook();
private static ItemAdderHook ITEMADDER_HOOK = new ItemAdderHook();
private static MythicHook MYTHIC_HOOK = new MythicHook();
private static HMCCosmeticsHook HMCCOSMETIC_HOOK = new HMCCosmeticsHook();
public static ItemHook getItemHook(String id) {
return itemHooks.get(id.toLowerCase());
}
public static boolean isItemHook(String id) {
return itemHooks.containsKey(id.toLowerCase());
}
public static void addItemHook(ItemHook hook) {
itemHooks.put(hook.getId().toLowerCase(), hook);
}
public static void setup() {
for (ItemHook itemHook : itemHooks.values()) {
if (Bukkit.getPluginManager().getPlugin(itemHook.getId()) != null) {
HMCCosmeticsPlugin.getInstance().getServer().getPluginManager().registerEvents(itemHook, HMCCosmeticsPlugin.getInstance());
itemHook.setActive(true);
HMCCosmeticsPlugin.getInstance().getLogger().info("Successfully hooked into " + itemHook.getId());
}
}
}
public static ItemStack getItem(String raw) {
if (!raw.contains(":")) {
Material mat = Material.getMaterial(raw.toUpperCase());
if (mat == null) return null;
return new ItemStack(mat);
}
// Ex. Oraxen:BigSword
// split[0] is the plugin name
// split[1] is the item name
String[] split = raw.split(":", 2);
if (!isItemHook(split[0])) return null;
ItemHook itemHook = getItemHook(split[0]);
if (!itemHook.getActive()) return null;
ItemStack item = itemHook.get(split[1]);
return item;
}
}

View File

@@ -1,17 +0,0 @@
package com.hibiscusmc.hmccosmetics.hooks.items;
import io.th0rgal.oraxen.api.OraxenItems;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
public class OraxenHook extends ItemHook implements Listener {
public OraxenHook() {
super("oraxen");
}
@Override
public ItemStack get(String itemid) {
return OraxenItems.getItemById(itemid).build();
}
}

View File

@@ -0,0 +1,34 @@
package com.hibiscusmc.hmccosmetics.hooks.misc;
import com.Zrips.CMI.events.CMIPlayerUnVanishEvent;
import com.Zrips.CMI.events.CMIPlayerVanishEvent;
import com.hibiscusmc.hmccosmetics.hooks.Hook;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
public class HookCMI extends Hook implements Listener {
public HookCMI() {
super("CMI");
}
@EventHandler
public void onPlayerVanish(@NotNull CMIPlayerVanishEvent event) {
Player player = event.getPlayer();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
user.hideCosmetics(CosmeticUser.HiddenReason.PLUGIN);
}
@EventHandler
public void onPlayerShow(@NotNull CMIPlayerUnVanishEvent event) {
Player player = event.getPlayer();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
user.showCosmetics();
}
}

View File

@@ -0,0 +1,11 @@
package com.hibiscusmc.hmccosmetics.hooks.misc;
import com.hibiscusmc.hmccosmetics.hooks.Hook;
import org.bukkit.event.Listener;
public class HookHMCColor extends Hook implements Listener {
public HookHMCColor() {
super("HMCColor");
}
}

View File

@@ -0,0 +1,37 @@
package com.hibiscusmc.hmccosmetics.hooks.misc;
import com.hibiscusmc.hmccosmetics.hooks.Hook;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import de.myzelyam.api.vanish.PlayerHideEvent;
import de.myzelyam.api.vanish.PlayerShowEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
public class HookPremiumVanish extends Hook implements Listener {
// NOTE: Supervanish and Premium Vanish both use the same api
public HookPremiumVanish() {
super("PremiumVanish");
}
@EventHandler
public void onPlayerVanish(@NotNull PlayerHideEvent event) {
Player player = event.getPlayer();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
user.hideCosmetics(CosmeticUser.HiddenReason.PLUGIN);
}
@EventHandler
public void onPlayerShow(@NotNull PlayerShowEvent event) {
Player player = event.getPlayer();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
user.showCosmetics();
}
}

View File

@@ -0,0 +1,36 @@
package com.hibiscusmc.hmccosmetics.hooks.misc;
import com.hibiscusmc.hmccosmetics.hooks.Hook;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import de.myzelyam.api.vanish.PlayerHideEvent;
import de.myzelyam.api.vanish.PlayerShowEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
public class HookSuperVanish extends Hook implements Listener {
// NOTE: Supervanish and Premium Vanish both use the same api
public HookSuperVanish() {
super("SuperVanish");
}
@EventHandler
public void onPlayerVanish(@NotNull PlayerHideEvent event) {
Player player = event.getPlayer();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
user.hideCosmetics(CosmeticUser.HiddenReason.PLUGIN);
}
@EventHandler
public void onPlayerShow(@NotNull PlayerShowEvent event) {
Player player = event.getPlayer();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
user.showCosmetics();
}
}

View File

@@ -1,4 +1,4 @@
package com.hibiscusmc.hmccosmetics.hooks;
package com.hibiscusmc.hmccosmetics.hooks.placeholders;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
@@ -16,31 +16,34 @@ import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
public class PAPIHook extends PlaceholderExpansion {
public class HMCPlaceholderExpansion extends PlaceholderExpansion {
private static boolean papiEnabled = false;
public PAPIHook() {
public HMCPlaceholderExpansion() {
papiEnabled = true;
}
@Override
public @NotNull String getIdentifier() {
@NotNull
public String getIdentifier() {
return "HMCCosmetics";
}
@Override
public @NotNull String getAuthor() {
@NotNull
public String getAuthor() {
return "HibiscusMC";
}
@Override
public @NotNull String getVersion() {
@NotNull
public String getVersion() {
return HMCCosmeticsPlugin.getInstance().getDescription().getVersion();
}
@Override
public String onRequest(OfflinePlayer player, String params) {
public String onRequest(@NotNull OfflinePlayer player, @NotNull String params) {
if (!player.isOnline()) return null;
CosmeticUser user = CosmeticUsers.getUser(player.getPlayer());
if (user == null) return null;
@@ -54,7 +57,9 @@ public class PAPIHook extends PlaceholderExpansion {
}
if (placeholderArgs.get(1) != null) {
Cosmetic cosmetic = Cosmetics.getCosmetic(placeholderArgs.get(1));
if (user.getCosmetic(cosmetic.getSlot()).getId() == cosmetic.getId()) return "true";
Cosmetic currentCosmetic = user.getCosmetic(cosmetic.getSlot());
if (cosmetic == null || currentCosmetic == null) return "false";
if (currentCosmetic.getId() == cosmetic.getId()) return "true";
return "false";
}
case "current":
@@ -64,6 +69,7 @@ public class PAPIHook extends PlaceholderExpansion {
if (placeholderArgs.get(1) != null) {
CosmeticSlot slot = CosmeticSlot.valueOf(placeholderArgs.get(1).toUpperCase());
if (slot == null) return null;
if (user.getCosmetic(slot) == null) return null;
if (placeholderArgs.size() == 2) return user.getCosmetic(slot).getId();
switch (placeholderArgs.get(2).toLowerCase()) {
case "material" -> {
@@ -129,13 +135,13 @@ public class PAPIHook extends PlaceholderExpansion {
return null;
}
public String getMaterial(Cosmetic cosmetic) {
public String getMaterial(@NotNull Cosmetic cosmetic) {
ItemStack item = cosmetic.getItem();
if (item == null) return null;
return cosmetic.getItem().getType().toString();
}
public String getModelData(Cosmetic cosmetic) {
public String getModelData(@NotNull Cosmetic cosmetic) {
ItemStack item = cosmetic.getItem();
if (item == null) return null;
if (!item.hasItemMeta()) return null;
@@ -143,7 +149,7 @@ public class PAPIHook extends PlaceholderExpansion {
return String.valueOf(itemMeta.getCustomModelData());
}
public String getItemName(Cosmetic cosmetic) {
public String getItemName(@NotNull Cosmetic cosmetic) {
ItemStack item = cosmetic.getItem();
if (item == null) return null;
if (!item.hasItemMeta()) return null;
@@ -151,7 +157,7 @@ public class PAPIHook extends PlaceholderExpansion {
return itemMeta.getDisplayName();
}
public String getItemLore(Cosmetic cosmetic) {
public String getItemLore(@NotNull Cosmetic cosmetic) {
ItemStack item = cosmetic.getItem();
if (item == null) return null;
if (item.hasItemMeta()) {
@@ -159,8 +165,4 @@ public class PAPIHook extends PlaceholderExpansion {
}
return null;
}
public static boolean isPAPIEnabled() {
return papiEnabled;
}
}

View File

@@ -0,0 +1,15 @@
package com.hibiscusmc.hmccosmetics.hooks.placeholders;
import com.hibiscusmc.hmccosmetics.hooks.Hook;
public class HookPlaceholderAPI extends Hook {
public HookPlaceholderAPI() {
super("PlaceholderAPI");
}
@Override
public void load() {
new HMCPlaceholderExpansion().register();
}
}

View File

@@ -12,11 +12,12 @@ import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.jetbrains.annotations.NotNull;
public class WGListener implements Listener {
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
public void onPlayerMove(@NotNull PlayerMoveEvent event) {
CosmeticUser user = CosmeticUsers.getUser(event.getPlayer());
if (user == null) return;
Location location = event.getPlayer().getLocation();
@@ -24,16 +25,19 @@ public class WGListener implements Listener {
RegionContainer region = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionQuery query = region.createQuery();
ApplicableRegionSet set = query.getApplicableRegions(loc);
// TODO: Add more cosmetics
if (set.getRegions().size() == 0) {
user.showCosmetics();
if (user.getHidden()) {
if (user.getHiddenReason() == CosmeticUser.HiddenReason.WORLDGUARD && set.getRegions().size() == 0) {
user.showCosmetics();
}
}
for (ProtectedRegion protectedRegion : set.getRegions()) {
if (protectedRegion.getFlags().containsKey(WGHook.getCosmeticEnableFlag())) {
user.hideCosmetics();
if (protectedRegion.getFlags().get(WGHook.getCosmeticEnableFlag()).toString().equalsIgnoreCase("ALLOW")) return;
user.hideCosmetics(CosmeticUser.HiddenReason.WORLDGUARD);
return;
}
if (protectedRegion.getFlags().containsKey(WGHook.getCosmeticWardrobeFlag())) {
if (!protectedRegion.getFlags().get(WGHook.getCosmeticWardrobeFlag()).toString().equalsIgnoreCase("ALLOW")) return;
user.enterWardrobe();
}
}

View File

@@ -13,11 +13,24 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.jetbrains.annotations.NotNull;
public class PlayerConnectionListener implements Listener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
public void onPlayerJoin(@NotNull PlayerJoinEvent event) {
if (event.getPlayer().isOp() || event.getPlayer().hasPermission("hmccosmetics.notifyupdate")) {
if (!HMCCosmeticsPlugin.getLatestVersion().equalsIgnoreCase(HMCCosmeticsPlugin.getInstance().getDescription().getVersion()) && HMCCosmeticsPlugin.getLatestVersion() != null)
MessagesUtil.sendMessageNoKey(
event.getPlayer(),
"<br>" +
"<GRAY>There is a new version of <light_purple><Bold>HMCCosmetics<reset><gray> available!<br>" +
"<GRAY>Current version: <red>" + HMCCosmeticsPlugin.getInstance().getDescription().getVersion() + " <GRAY>| Latest version: <light_purple>" + HMCCosmeticsPlugin.getLatestVersion() + "<br>" +
"<GRAY>Download it on <gold><click:OPEN_URL:'https://www.spigotmc.org/resources/100107/'>Spigot<reset> <gray>or <gold><click:OPEN_URL:'https://polymart.org/resource/1879'>Polymart<reset><gray>!" +
"<br>"
);
}
Runnable run = () -> {
CosmeticUser user = Database.get(event.getPlayer().getUniqueId());
CosmeticUsers.addUser(user);
@@ -34,7 +47,7 @@ public class PlayerConnectionListener implements Listener {
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
public void onPlayerQuit(@NotNull PlayerQuitEvent event) {
CosmeticUser user = CosmeticUsers.getUser(event.getPlayer());
if (user == null) { // Remove any passengers if a user failed to initialize. Bugs can cause this to happen
if (!event.getPlayer().getPassengers().isEmpty()) {
@@ -46,6 +59,10 @@ public class PlayerConnectionListener implements Listener {
}
}
if (user.isInWardrobe()) user.leaveWardrobe();
if (user.getUserEmoteManager().isPlayingEmote()) {
user.getUserEmoteManager().stopEmote();
event.getPlayer().setInvisible(false);
}
Database.save(user);
user.destroy();
CosmeticUsers.removeUser(user.getUniqueId());

View File

@@ -13,6 +13,9 @@ import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBalloonType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticEmoteType;
import com.hibiscusmc.hmccosmetics.gui.Menu;
import com.hibiscusmc.hmccosmetics.gui.Menus;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
@@ -20,21 +23,22 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.InventoryUtils;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Pose;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.entity.*;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.*;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -47,6 +51,7 @@ public class PlayerGameListener implements Listener {
registerMenuChangeListener();
registerPlayerEquipmentListener();
registerPlayerArmListener();
registerEntityUseListener();
//registerLookMovement();
//registerMoveListener();
@@ -76,8 +81,12 @@ public class PlayerGameListener implements Listener {
public void onPlayerShift(PlayerToggleSneakEvent event) {
CosmeticUser user = CosmeticUsers.getUser(event.getPlayer().getUniqueId());
if (!event.isSneaking()) return;
if (user == null) return;
if (event.isSneaking()) {
user.getUserEmoteManager().stopEmote();
}
if (!event.isSneaking()) return;
if (!user.isInWardrobe()) return;
user.leaveWardrobe();
@@ -93,10 +102,10 @@ public class PlayerGameListener implements Listener {
return;
}
if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
user.hideBackpack();
if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK) && user.getUserBackpackManager() != null) {
user.getUserBackpackManager().hideBackpack();
user.getBackpackEntity().teleport(event.getTo());
user.getUserBackpackManager().getArmorStand().teleport(event.getTo());
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
user.updateCosmetic();
@@ -106,8 +115,10 @@ public class PlayerGameListener implements Listener {
if (event.getCause().equals(PlayerTeleportEvent.TeleportCause.NETHER_PORTAL) || event.getCause().equals(PlayerTeleportEvent.TeleportCause.END_PORTAL)) return;
if (user.hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
final CosmeticBalloonType cosmeticBalloonType = (CosmeticBalloonType) user.getCosmetic(CosmeticSlot.BALLOON);
user.despawnBalloon();
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
user.updateCosmetic(CosmeticSlot.BALLOON);
user.spawnBalloon(cosmeticBalloonType);
}, 2);
}
}
@@ -122,14 +133,14 @@ public class PlayerGameListener implements Listener {
return;
}
final Cosmetic cosmetic = user.getCosmetic(CosmeticSlot.BALLOON);
final Color color = user.getCosmeticColor(CosmeticSlot.BALLOON);
user.removeCosmeticSlot(CosmeticSlot.BALLOON);
if (user.hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
user.despawnBalloon();
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
user.addPlayerCosmetic(cosmetic, color);
user.updateCosmetic();
}, 4);
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
user.spawnBalloon((CosmeticBalloonType) user.getCosmetic(CosmeticSlot.BALLOON));
user.updateCosmetic();
}, 4);
}
}
@EventHandler
@@ -144,14 +155,35 @@ public class PlayerGameListener implements Listener {
@EventHandler
public void onPlayerLook(PlayerMoveEvent event) {
if (event.isCancelled()) return;
Player player = event.getPlayer();
// TODO: Move to packets
CosmeticUser user = CosmeticUsers.getUser(event.getPlayer().getUniqueId());
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
// Really need to look into optimization of this
user.updateCosmetic(CosmeticSlot.BACKPACK);
user.updateCosmetic(CosmeticSlot.BALLOON);
}
@EventHandler
public void onPlayerPoseChange(EntityPoseChangeEvent event) {
if (!(event.getEntity() instanceof Player)) return;
Player player = ((Player) event.getEntity()).getPlayer();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
if (!user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) return;
Pose pose = event.getPose();
if (pose.equals(Pose.STANDING)) {
if (!user.isBackpackSpawned()) {
user.spawnBackpack((CosmeticBackpackType) user.getCosmetic(CosmeticSlot.BACKPACK));
}
return;
}
if (pose.equals(Pose.SLEEPING) || pose.equals(Pose.SWIMMING) || pose.equals(Pose.FALL_FLYING)) {
user.despawnBackpack();
}
}
@EventHandler
public void onPlayerArmorDamage(PlayerItemDamageEvent event) {
// Possibly look into cancelling the event, then handling the damage on our own.
@@ -191,11 +223,43 @@ public class PlayerGameListener implements Listener {
CosmeticUser user = CosmeticUsers.getUser(event.getPlayer().getUniqueId());
if (user == null) return;
// Really need to look into optimization of this
if (user.hasCosmeticInSlot(CosmeticSlot.EMOTE) && event.getPlayer().isSneaking() && event.getPlayer().hasPermission("hmccosmetics.emote.shiftrun")) {
CosmeticEmoteType cosmeticEmoteType = (CosmeticEmoteType) user.getCosmetic(CosmeticSlot.EMOTE);
cosmeticEmoteType.run(user);
event.setCancelled(true);
return;
}
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
user.updateCosmetic(CosmeticSlot.OFFHAND);
}, 2);
}
@EventHandler
public void onPlayerPickupItem(EntityPickupItemEvent event) {
if (!(event.getEntity() instanceof Player)) return;
CosmeticUser user = CosmeticUsers.getUser(event.getEntity().getUniqueId());
if (user == null) return;
if (user.isInWardrobe()) event.setCancelled(true);
}
@EventHandler
public void playerInvisibility(EntityPotionEffectEvent event) {
if (event.isCancelled()) return;
if (!event.getModifiedType().equals(PotionEffectType.INVISIBILITY)) return;
if (!event.getEntityType().equals(EntityType.PLAYER)) return;
Player player = (Player) event.getEntity();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
if (event.getAction().equals(EntityPotionEffectEvent.Action.ADDED)) {
user.hideCosmetics(CosmeticUser.HiddenReason.POTION);
return;
}
if (event.getAction().equals(EntityPotionEffectEvent.Action.CLEARED) || event.getAction().equals(EntityPotionEffectEvent.Action.REMOVED)) {
user.showCosmetics();
return;
}
}
@EventHandler
public void onMainHandSwitch(PlayerItemHeldEvent event) {
CosmeticUser user = CosmeticUsers.getUser(event.getPlayer());
@@ -278,6 +342,7 @@ public class PlayerGameListener implements Listener {
}
}
packet.getItemListModifier().write(0, slotData);
packet.getItemModifier().write(0, event.getPacket().getItemModifier().read(0));
event.setPacket(packet);
MessagesUtil.sendDebugMessages("Menu Fired, updated cosmetics " + " on slotdata " + windowID + " with " + slotData.size());
/*
@@ -298,13 +363,11 @@ public class PlayerGameListener implements Listener {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_EQUIPMENT) {
@Override
public void onPacketSending(PacketEvent event) {
MessagesUtil.sendDebugMessages("equipment packet is activated");
Player player = event.getPlayer(); // Player that's sent
int entityID = event.getPacket().getIntegers().read(0);
// User
CosmeticUser user = CosmeticUsers.getUser(entityID);
if (user == null) {
MessagesUtil.sendDebugMessages("equipment packet is activated - user null");
return;
}
@@ -331,8 +394,12 @@ public class PlayerGameListener implements Listener {
Player player = event.getPlayer();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
if (user.getUserEmoteManager().isPlayingEmote()) {
event.setCancelled(true);
return;
}
if (!user.isInWardrobe()) return;
Menu menu = Menus.getMenu(Settings.getDefaultMenu());
Menu menu = Menus.getDefaultMenu();
if (menu == null) return;
menu.openMenu(user);
event.setCancelled(true);
@@ -340,6 +407,21 @@ public class PlayerGameListener implements Listener {
});
}
private void registerEntityUseListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Client.USE_ENTITY) {
@Override
public void onPacketReceiving(PacketEvent event) {
if (!(event.getPlayer() instanceof Player)) return;
Player player = event.getPlayer();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
if (user.getUserEmoteManager().isPlayingEmote() || user.isInWardrobe()) {
event.setCancelled(true);
}
}
});
}
private void registerLookMovement() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Client.LOOK) {
@Override

View File

@@ -3,9 +3,10 @@ package com.hibiscusmc.hmccosmetics.nms;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBalloonType;
import com.hibiscusmc.hmccosmetics.entities.BalloonEntity;
import com.hibiscusmc.hmccosmetics.user.manager.UserBalloonManager;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.Location;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -18,13 +19,15 @@ public interface NMSHandler {
Entity getEntity(int entityId);
Entity getInvisibleArmorstand(Location loc);
Entity getHMCArmorStand(Location loc);
Entity getMEGEntity(Location loc);
ArmorStand getMEGEntity(Location loc);
Entity spawnBackpack(CosmeticUser user, CosmeticBackpackType cosmeticBackpackType);
BalloonEntity spawnBalloon(CosmeticUser user, CosmeticBalloonType cosmeticBalloonType);
Entity spawnHMCParticleCloud(Location location);
UserBalloonManager spawnBalloon(CosmeticUser user, CosmeticBalloonType cosmeticBalloonType);
void equipmentSlotUpdate(
int entityId,

View File

@@ -8,7 +8,7 @@ import java.util.logging.Level;
public class NMSHandlers {
private static final String[] SUPPORTED_VERSION = new String[]{"v1_19_R1", "v1_19_R2"};
private static final String[] SUPPORTED_VERSION = new String[]{"v1_17_R1", "v1_18_R2", "v1_19_R1", "v1_19_R2"};
private static NMSHandler handler;
private static String version;
@@ -34,10 +34,9 @@ public class NMSHandlers {
if (!selectedVersion.contains(packageVersion)) {
continue;
}
MessagesUtil.sendDebugMessages(packageVersion + " has been detected.", Level.SEVERE);
MessagesUtil.sendDebugMessages(packageVersion + " has been detected.", Level.INFO);
version = packageVersion;
try {
//Class.forName("org.bukkit.craftbukkit." + version + ".block.CraftBlock").getName();
handler = (NMSHandler) Class.forName("com.hibiscusmc.hmccosmetics.nms." + packageVersion + ".NMSHandler").getConstructor().newInstance();
return;
} catch (ClassNotFoundException | InvocationTargetException | InstantiationException |

View File

@@ -6,25 +6,23 @@ import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.config.WardrobeSettings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBalloonType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticMainhandType;
import com.hibiscusmc.hmccosmetics.entities.BalloonEntity;
import com.hibiscusmc.hmccosmetics.cosmetic.types.*;
import com.hibiscusmc.hmccosmetics.user.manager.UserBackpackManager;
import com.hibiscusmc.hmccosmetics.user.manager.UserBalloonManager;
import com.hibiscusmc.hmccosmetics.nms.NMSHandlers;
import com.hibiscusmc.hmccosmetics.user.manager.UserEmoteManager;
import com.hibiscusmc.hmccosmetics.user.manager.UserWardrobeManager;
import com.hibiscusmc.hmccosmetics.util.InventoryUtils;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.PlayerUtils;
import com.hibiscusmc.hmccosmetics.util.packets.PacketManager;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.*;
import org.bukkit.scheduler.BukkitTask;
import java.util.*;
@@ -35,21 +33,19 @@ public class CosmeticUser {
private UUID uniqueId;
private int taskId;
private HashMap<CosmeticSlot, Cosmetic> playerCosmetics = new HashMap<>();
private Wardrobe wardrobe;
private ArmorStand invisibleArmorstand;
private BalloonEntity balloonEntity;
private UserWardrobeManager userWardrobeManager;
private UserBalloonManager userBalloonManager;
private UserBackpackManager userBackpackManager;
private UserEmoteManager userEmoteManager;
// Cosmetic Settings/Toggles
private boolean hideBackpack;
private boolean hideCosmetics;
private HiddenReason hiddenReason;
private HashMap<CosmeticSlot, Color> colors = new HashMap<>();
public CosmeticUser() {
// Empty
}
public CosmeticUser(UUID uuid) {
this.uniqueId = uuid;
userEmoteManager = new UserEmoteManager(this);
tick();
}
@@ -85,17 +81,6 @@ public class CosmeticUser {
return playerCosmetics.values();
}
public int getArmorstandId() {
return invisibleArmorstand.getEntityId();
}
public Entity getBackpackEntity() {
return this.invisibleArmorstand;
}
public BalloonEntity getBalloonEntity() {
return this.balloonEntity;
}
public void addPlayerCosmetic(Cosmetic cosmetic) {
addPlayerCosmetic(cosmetic, null);
}
@@ -126,13 +111,6 @@ public class CosmeticUser {
spawnBalloon(balloonType);
}
}
public void toggleCosmetic(Cosmetic cosmetic) {
if (hasCosmeticInSlot(cosmetic.getSlot())) {
removeCosmeticSlot(cosmetic.getSlot());
return;
}
addPlayerCosmetic(cosmetic);
}
public void removeCosmetics() {
// Small optimization could be made, but Concurrent modification prevents us from both getting and removing
@@ -155,6 +133,9 @@ public class CosmeticUser {
}
if (slot == CosmeticSlot.BALLOON) {
despawnBalloon();
}
if (slot == CosmeticSlot.EMOTE) {
}
colors.remove(slot);
playerCosmetics.remove(slot);
@@ -170,6 +151,10 @@ public class CosmeticUser {
return playerCosmetics.containsKey(slot);
}
public Set<CosmeticSlot> getSlotsWithCosmetics() {
return Set.copyOf(playerCosmetics.keySet());
}
public void updateCosmetic(CosmeticSlot slot) {
if (getCosmetic(slot) == null) {
return;
@@ -191,6 +176,7 @@ public class CosmeticUser {
public ItemStack getUserCosmeticItem(Cosmetic cosmetic) {
ItemStack item = null;
if (hideCosmetics) {
if (cosmetic instanceof CosmeticBackpackType || cosmetic instanceof CosmeticBalloonType) return new ItemStack(Material.AIR);
return getPlayer().getInventory().getItem(InventoryUtils.getEquipmentSlot(cosmetic.getSlot()));
}
if (cosmetic instanceof CosmeticArmorType || cosmetic instanceof CosmeticMainhandType || cosmetic instanceof CosmeticBackpackType) {
@@ -209,9 +195,14 @@ public class CosmeticUser {
}
if (item.hasItemMeta()) {
ItemMeta itemMeta = item.getItemMeta();
if (itemMeta instanceof LeatherArmorMeta) {
if (colors.containsKey(cosmetic.getSlot())) {
((LeatherArmorMeta) itemMeta).setColor(colors.get(cosmetic.getSlot()));
if (colors.containsKey(cosmetic.getSlot())) {
Color color = colors.get(cosmetic.getSlot());
if (itemMeta instanceof LeatherArmorMeta leatherMeta) {
leatherMeta.setColor(color);
} else if (itemMeta instanceof PotionMeta potionMeta) {
potionMeta.setColor(color);
} else if (itemMeta instanceof MapMeta mapMeta) {
mapMeta.setColor(color);
}
}
item.setItemMeta(itemMeta);
@@ -219,8 +210,32 @@ public class CosmeticUser {
return item;
}
public UserBackpackManager getUserBackpackManager() {
return userBackpackManager;
}
public UserBalloonManager getBalloonManager() {
return this.userBalloonManager;
}
public UserWardrobeManager getWardrobeManager() {
return userWardrobeManager;
}
public UserEmoteManager getUserEmoteManager() {
return userEmoteManager;
}
public void enterWardrobe() {
if (!WardrobeSettings.inDistanceOfStatic(getPlayer().getLocation())) {
enterWardrobe(false);
}
public void enterWardrobe(boolean ignoreDistance) {
enterWardrobe(ignoreDistance, WardrobeSettings.getLeaveLocation(), WardrobeSettings.getViewerLocation(), WardrobeSettings.getWardrobeLocation());
}
public void enterWardrobe(boolean ignoreDistance, Location exitLocation, Location viewingLocation, Location npcLocation) {
if (!WardrobeSettings.inDistanceOfStatic(getPlayer().getLocation()) && !ignoreDistance) {
MessagesUtil.sendMessage(getPlayer(), "not-near-wardrobe");
return;
}
@@ -230,25 +245,21 @@ public class CosmeticUser {
return;
}
if (wardrobe == null) {
wardrobe = new Wardrobe(this);
wardrobe.start();
if (userWardrobeManager == null) {
userWardrobeManager = new UserWardrobeManager(this, exitLocation, viewingLocation, npcLocation);
userWardrobeManager.start();
}
}
public Wardrobe getWardrobe() {
return wardrobe;
}
public void leaveWardrobe() {
PlayerWardrobeLeaveEvent event = new PlayerWardrobeLeaveEvent(this);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
if (!getWardrobe().getWardrobeStatus().equals(Wardrobe.WardrobeStatus.RUNNING)) return;
if (!getWardrobeManager().getWardrobeStatus().equals(UserWardrobeManager.WardrobeStatus.RUNNING)) return;
getWardrobe().setWardrobeStatus(Wardrobe.WardrobeStatus.STOPPING);
getWardrobeManager().setWardrobeStatus(UserWardrobeManager.WardrobeStatus.STOPPING);
if (WardrobeSettings.isEnabledTransition()) {
MessagesUtil.sendTitle(
@@ -259,16 +270,14 @@ public class CosmeticUser {
WardrobeSettings.getTransitionFadeOut()
);
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
wardrobe.end();
wardrobe = null;
userWardrobeManager.end();
userWardrobeManager = null;
}, WardrobeSettings.getTransitionDelay());
} else {
}
}
public boolean isInWardrobe() {
if (wardrobe == null) return false;
if (userWardrobeManager == null) return false;
return true;
}
@@ -281,45 +290,43 @@ public class CosmeticUser {
}
public void spawnBackpack(CosmeticBackpackType cosmeticBackpackType) {
MessagesUtil.sendDebugMessages("spawnBackpack Bukkit - Start");
Player player = Bukkit.getPlayer(getUniqueId());
if (this.userBackpackManager != null) return;
this.userBackpackManager = new UserBackpackManager(this, cosmeticBackpackType.getBackpackType());
userBackpackManager.spawnBackpack(cosmeticBackpackType);
}
if (this.invisibleArmorstand != null) return;
public void despawnBackpack() {
if (userBackpackManager == null) return;
userBackpackManager.despawnBackpack();
userBackpackManager = null;
}
this.invisibleArmorstand = (ArmorStand) NMSHandlers.getHandler().spawnBackpack(this, cosmeticBackpackType);
MessagesUtil.sendDebugMessages("spawnBackpack Bukkit - Finish");
public boolean isBackpackSpawned() {
if (this.userBackpackManager == null) return false;
return true;
}
public void spawnBalloon(CosmeticBalloonType cosmeticBalloonType) {
Player player = Bukkit.getPlayer(getUniqueId());
if (this.balloonEntity != null) return;
if (this.userBalloonManager != null) return;
this.balloonEntity = NMSHandlers.getHandler().spawnBalloon(this, cosmeticBalloonType);
this.userBalloonManager = NMSHandlers.getHandler().spawnBalloon(this, cosmeticBalloonType);
List<Player> viewer = PlayerUtils.getNearbyPlayers(player);
viewer.add(player);
PacketManager.sendLeashPacket(getBalloonEntity().getPufferfishBalloonId(), player.getEntityId(), viewer);
PacketManager.sendLeashPacket(getBalloonManager().getPufferfishBalloonId(), player.getEntityId(), viewer);
}
public void despawnBalloon() {
if (this.balloonEntity == null) return;
if (this.userBalloonManager == null) return;
List<Player> sentTo = PlayerUtils.getNearbyPlayers(getPlayer().getLocation());
PacketManager.sendEntityDestroyPacket(balloonEntity.getPufferfishBalloonId(), sentTo);
PacketManager.sendEntityDestroyPacket(userBalloonManager.getPufferfishBalloonId(), sentTo);
this.balloonEntity.remove();
this.balloonEntity = null;
}
public void despawnBackpack() {
Player player = Bukkit.getPlayer(getUniqueId());
if (invisibleArmorstand == null) return;
invisibleArmorstand.setHealth(0);
invisibleArmorstand.remove();
this.invisibleArmorstand = null;
this.userBalloonManager.remove();
this.userBalloonManager = null;
}
public void respawnBackpack() {
@@ -382,40 +389,23 @@ public class CosmeticUser {
}
}
public void hideBackpack() {
if (hideBackpack == true) return;
if (hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
invisibleArmorstand.getEquipment().clear();
hideBackpack = true;
}
}
public void showBackpack() {
if (hideBackpack == false) return;
if (hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
CosmeticBackpackType cosmeticBackpackType = (CosmeticBackpackType) getCosmetic(CosmeticSlot.BACKPACK);
ItemStack item = getUserCosmeticItem(cosmeticBackpackType);
invisibleArmorstand.getEquipment().setHelmet(item);
hideBackpack = false;
}
}
public void hideCosmetics() {
public void hideCosmetics(HiddenReason reason) {
if (hideCosmetics == true) return;
PlayerCosmeticHideEvent event = new PlayerCosmeticHideEvent(this);
PlayerCosmeticHideEvent event = new PlayerCosmeticHideEvent(this, reason);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
hideCosmetics = true;
hiddenReason = reason;
if (hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
getBalloonEntity().removePlayerFromModel(getPlayer());
getBalloonManager().removePlayerFromModel(getPlayer());
List<Player> viewer = PlayerUtils.getNearbyPlayers(getPlayer());
PacketManager.sendLeashPacket(getBalloonEntity().getPufferfishBalloonId(), -1, viewer);
PacketManager.sendLeashPacket(getBalloonManager().getPufferfishBalloonId(), -1, viewer);
}
if (hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
invisibleArmorstand.getEquipment().clear();
userBackpackManager.clearItems();
}
updateCosmetic();
MessagesUtil.sendDebugMessages("HideCosmetics");
@@ -429,17 +419,19 @@ public class CosmeticUser {
if (event.isCancelled()) {
return;
}
hideCosmetics = false;
hiddenReason = HiddenReason.NONE;
if (hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
CosmeticBalloonType balloonType = (CosmeticBalloonType) getCosmetic(CosmeticSlot.BALLOON);
getBalloonEntity().addPlayerToModel(getPlayer(), balloonType.getModelName());
getBalloonManager().addPlayerToModel(this, balloonType);
List<Player> viewer = PlayerUtils.getNearbyPlayers(getPlayer());
PacketManager.sendLeashPacket(getBalloonEntity().getPufferfishBalloonId(), getPlayer().getEntityId(), viewer);
PacketManager.sendLeashPacket(getBalloonManager().getPufferfishBalloonId(), getPlayer().getEntityId(), viewer);
}
if (hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
CosmeticBackpackType cosmeticBackpackType = (CosmeticBackpackType) getCosmetic(CosmeticSlot.BACKPACK);
ItemStack item = getUserCosmeticItem(cosmeticBackpackType);
invisibleArmorstand.getEquipment().setHelmet(item);
userBackpackManager.setItem(item);
}
updateCosmetic();
MessagesUtil.sendDebugMessages("ShowCosmetics");
@@ -448,4 +440,18 @@ public class CosmeticUser {
public boolean getHidden() {
return this.hideCosmetics;
}
public HiddenReason getHiddenReason() {
return hiddenReason;
}
public enum HiddenReason {
NONE,
WORLDGUARD,
PLUGIN,
POTION,
ACTION,
COMMAND,
EMOTE
}
}

View File

@@ -0,0 +1,149 @@
package com.hibiscusmc.hmccosmetics.user.manager;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType;
import com.hibiscusmc.hmccosmetics.nms.NMSHandlers;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.ticxo.modelengine.api.ModelEngineAPI;
import com.ticxo.modelengine.api.model.ActiveModel;
import com.ticxo.modelengine.api.model.ModeledEntity;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.ArmorStand;
import org.bukkit.inventory.ItemStack;
import java.util.logging.Level;
public class UserBackpackManager {
private boolean hideBackpack;
private ArmorStand invisibleArmorStand;
private AreaEffectCloud particleCloud;
private final CosmeticUser user;
private BackpackType backpackType;
public UserBackpackManager(CosmeticUser user, BackpackType backpackType) {
this.user = user;
hideBackpack = false;
this.backpackType = backpackType;
}
public int getFirstArmorStandId() {
return invisibleArmorStand.getEntityId();
}
public ArmorStand getArmorStand() {
return invisibleArmorStand;
}
public void spawnBackpack(CosmeticBackpackType cosmeticBackpackType) {
MessagesUtil.sendDebugMessages("spawnBackpack Bukkit - Start");
if (getBackpackType().equals(BackpackType.NORMAL)) {
spawnNormalBackpack(cosmeticBackpackType);
}
if (getBackpackType().equals(BackpackType.FIRST_PERSON)) {
spawnFirstPersonBackpack(cosmeticBackpackType);
}
}
private void spawnNormalBackpack(CosmeticBackpackType cosmeticBackpackType) {
if (this.invisibleArmorStand != null) return;
this.invisibleArmorStand = (ArmorStand) NMSHandlers.getHandler().spawnBackpack(user, cosmeticBackpackType);
if (cosmeticBackpackType.getModelName() != null && HMCCosmeticsPlugin.hasModelEngine()) {
if (ModelEngineAPI.api.getModelRegistry().getBlueprint(cosmeticBackpackType.getModelName()) == null) {
MessagesUtil.sendDebugMessages("Invalid Model Engine Blueprint " + cosmeticBackpackType.getModelName(), Level.SEVERE);
return;
}
ModeledEntity modeledEntity = ModelEngineAPI.getOrCreateModeledEntity(invisibleArmorStand);
ActiveModel model = ModelEngineAPI.createActiveModel(ModelEngineAPI.getBlueprint(cosmeticBackpackType.getModelName()));
model.setCanHurt(false);
modeledEntity.addModel(model, false);
}
MessagesUtil.sendDebugMessages("spawnBackpack Bukkit - Finish");
}
public void spawnFirstPersonBackpack(CosmeticBackpackType cosmeticBackpackType) {
if (this.invisibleArmorStand != null) return;
this.invisibleArmorStand = (ArmorStand) NMSHandlers.getHandler().spawnBackpack(user, cosmeticBackpackType);
this.particleCloud = (AreaEffectCloud) NMSHandlers.getHandler().spawnHMCParticleCloud(user.getPlayer().getLocation());
if (cosmeticBackpackType.getModelName() != null && HMCCosmeticsPlugin.hasModelEngine()) {
if (ModelEngineAPI.api.getModelRegistry().getBlueprint(cosmeticBackpackType.getModelName()) == null) {
MessagesUtil.sendDebugMessages("Invalid Model Engine Blueprint " + cosmeticBackpackType.getModelName(), Level.SEVERE);
return;
}
ModeledEntity modeledEntity = ModelEngineAPI.getOrCreateModeledEntity(invisibleArmorStand);
ActiveModel model = ModelEngineAPI.createActiveModel(ModelEngineAPI.getBlueprint(cosmeticBackpackType.getModelName()));
model.setCanHurt(false);
modeledEntity.addModel(model, false);
}
MessagesUtil.sendDebugMessages("spawnBackpack Bukkit - Finish");
}
public void despawnBackpack() {
if (invisibleArmorStand != null) {
invisibleArmorStand.setHealth(0);
invisibleArmorStand.remove();
this.invisibleArmorStand = null;
}
if (particleCloud != null) {
particleCloud.remove();
this.particleCloud = null;
}
}
public void hideBackpack() {
if (user.getHidden()) return;
getArmorStand().getEquipment().clear();
hideBackpack = true;
}
public void showBackpack() {
if (!hideBackpack) return;
CosmeticBackpackType cosmeticBackpackType = (CosmeticBackpackType) user.getCosmetic(CosmeticSlot.BACKPACK);
ItemStack item = user.getUserCosmeticItem(cosmeticBackpackType);
getArmorStand().getEquipment().setHelmet(item);
hideBackpack = false;
}
public void setVisibility(boolean shown) {
hideBackpack = shown;
}
public BackpackType getBackpackType() {
return backpackType;
}
public int getAreaEffectEntityId() {
return particleCloud.getEntityId();
}
public void teleportEffectEntity(Location location) {
particleCloud.teleport(location);
}
public void setItem(ItemStack item) {
getArmorStand().getEquipment().setHelmet(item);
}
public void clearItems() {
ItemStack item = new ItemStack(Material.AIR);
getArmorStand().getEquipment().setHelmet(item);
}
public enum BackpackType {
NORMAL,
FIRST_PERSON // First person not yet implemented
}
}

View File

@@ -0,0 +1,164 @@
package com.hibiscusmc.hmccosmetics.user.manager;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBalloonType;
import com.hibiscusmc.hmccosmetics.nms.NMSHandlers;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.ticxo.modelengine.api.ModelEngineAPI;
import com.ticxo.modelengine.api.model.ActiveModel;
import com.ticxo.modelengine.api.model.ModeledEntity;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
import java.util.logging.Level;
public class UserBalloonManager {
private BalloonType balloonType;
private final int balloonID;
private final UUID uniqueID;
private final ArmorStand modelEntity;
public UserBalloonManager(@NotNull Location location) {
this.uniqueID = UUID.randomUUID();
this.balloonID = NMSHandlers.getHandler().getNextEntityId();
this.modelEntity = NMSHandlers.getHandler().getMEGEntity(location.add(Settings.getBalloonOffset()));
}
public void spawnModel(@NotNull CosmeticBalloonType cosmeticBalloonType, Color color) {
// redo this
if (cosmeticBalloonType.getModelName() != null && HMCCosmeticsPlugin.hasModelEngine()) {
balloonType = BalloonType.MODELENGINE;
} else {
if (cosmeticBalloonType.getItem() != null) {
balloonType = BalloonType.ITEM;
} else {
balloonType = BalloonType.NONE;
}
}
MessagesUtil.sendDebugMessages("balloontype is " + balloonType);
if (balloonType == BalloonType.MODELENGINE) {
String id = cosmeticBalloonType.getModelName();
MessagesUtil.sendDebugMessages("Attempting Spawning for " + id);
if (ModelEngineAPI.api.getModelRegistry().getBlueprint(id) == null) {
MessagesUtil.sendDebugMessages("Invalid Model Engine Blueprint " + id, Level.SEVERE);
return;
}
ModeledEntity modeledEntity = ModelEngineAPI.getOrCreateModeledEntity(modelEntity);
ActiveModel model = ModelEngineAPI.createActiveModel(ModelEngineAPI.getBlueprint(id));
model.setCanHurt(false);
modeledEntity.addModel(model, false);
if (color != null) {
modeledEntity.getModels().forEach((d, singleModel) -> {
if (cosmeticBalloonType.isDyablePart(d)) {
singleModel.getRendererHandler().setColor(color);
singleModel.getRendererHandler().update();
}
});
}
return;
}
if (balloonType == BalloonType.ITEM) {
modelEntity.getEquipment().setHelmet(cosmeticBalloonType.getItem());
}
}
public void remove() {
if (balloonType == BalloonType.MODELENGINE) {
final ModeledEntity entity = ModelEngineAPI.api.getModeledEntity(modelEntity.getUniqueId());
if (entity == null) return;
for (final Player player : entity.getRangeManager().getPlayerInRange()) {
entity.hideFromPlayer(player);
}
entity.destroy();
}
modelEntity.remove();
}
public void addPlayerToModel(final CosmeticUser user, final CosmeticBalloonType cosmeticBalloonType) {
addPlayerToModel(user, cosmeticBalloonType, null);
}
public void addPlayerToModel(final CosmeticUser user, final CosmeticBalloonType cosmeticBalloonType, Color color) {
if (balloonType == BalloonType.MODELENGINE) {
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(modelEntity.getUniqueId());
if (model == null) {
spawnModel(cosmeticBalloonType, color);
MessagesUtil.sendDebugMessages("model is null");
return;
}
//if (model.getRangeManager().getPlayerInRange().contains(player)) return;
model.showToPlayer(user.getPlayer());
MessagesUtil.sendDebugMessages("Show to player");
return;
}
if (balloonType == BalloonType.ITEM) {
modelEntity.getEquipment().setHelmet(user.getUserCosmeticItem(cosmeticBalloonType));
}
}
public void removePlayerFromModel(final Player player) {
if (balloonType == BalloonType.MODELENGINE) {
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(modelEntity.getUniqueId());
if (model == null) return;
model.hideFromPlayer(player);
MessagesUtil.sendDebugMessages("Hidden from player");
return;
}
if (balloonType == BalloonType.ITEM) {
modelEntity.getEquipment().clear();
return;
}
}
public Entity getModelEntity() {
return this.modelEntity;
}
public int getPufferfishBalloonId() {
return balloonID;
}
public UUID getPufferfishBalloonUniqueId() {
return uniqueID;
}
public UUID getModelUnqiueId() {
return getModelEntity().getUniqueId();
}
public int getModelId() {
return getModelEntity().getEntityId();
}
public Location getLocation() {
return this.getModelEntity().getLocation();
}
public void setLocation(Location location) {
this.getModelEntity().teleport(location);
}
public void setVelocity(Vector vector) {
this.getModelEntity().setVelocity(vector);
}
public enum BalloonType {
MODELENGINE,
ITEM,
NONE
}
}

View File

@@ -0,0 +1,42 @@
package com.hibiscusmc.hmccosmetics.user.manager;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticEmoteType;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.jetbrains.annotations.NotNull;
public class UserEmoteManager {
CosmeticUser user;
private UserEmoteModel model;
public UserEmoteManager(CosmeticUser user) {
this.user = user;
}
public void playEmote(@NotNull CosmeticEmoteType cosmeticEmoteType) {
MessagesUtil.sendDebugMessages("playEmote " + cosmeticEmoteType.getAnimationId());
playEmote(cosmeticEmoteType.getAnimationId());
}
public void playEmote(String animationId) {
if (isPlayingEmote()) return;
if (user.isInWardrobe()) return;
try {
model = new UserEmoteModel(user);
model.playAnimation(animationId);
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean isPlayingEmote() {
if (model == null) return false;
return model.isPlayingAnimation();
}
public void stopEmote() {
if (!isPlayingEmote()) return;
model.stopAnimation();
}
}

View File

@@ -0,0 +1,123 @@
package com.hibiscusmc.hmccosmetics.user.manager;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.nms.NMSHandlers;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.ServerUtils;
import com.hibiscusmc.hmccosmetics.util.packets.PacketManager;
import com.ticxo.playeranimator.api.model.player.PlayerModel;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
public class UserEmoteModel extends PlayerModel {
private final CosmeticUser user;
private String emotePlaying;
private final int armorStandId;
private GameMode originalGamemode;
public UserEmoteModel(@NotNull CosmeticUser user) {
super(user.getPlayer());
this.user = user;
armorStandId = NMSHandlers.getHandler().getNextEntityId();
getRangeManager().setRenderDistance(Settings.getViewDistance());
}
@Override
public void playAnimation(@NotNull String id) {
if (id.contains(":")) id = id.split(":", 2)[1]; // A:B -> B -> B.B.B
if (!id.contains(".")) id = id + "." + id + "." + id; // Make into a format that playerAnimator works with. Requires 3 splits.
super.playAnimation(id);
emotePlaying = id;
// Add config option that either allows player to move or forces them into a spot.
Player player = user.getPlayer();
List<Player> viewer = Collections.singletonList(user.getPlayer());
List<Player> outsideViewers = PacketManager.getViewers(player.getLocation());
outsideViewers.remove(player);
PacketManager.equipmentSlotUpdate(player, true, outsideViewers);
Location newLocation = player.getLocation().clone();
newLocation.setPitch(0);
double DISTANCE = Settings.getEmoteDistance();
Location thirdPersonLocation = newLocation.add(newLocation.getDirection().normalize().multiply(DISTANCE));
if (Settings.getCosmeticEmoteBlockCheck() && thirdPersonLocation.getBlock().getType().isOccluding()) {
stopAnimation();
MessagesUtil.sendMessage(player, "emote-blocked");
return;
}
user.getPlayer().setInvisible(true);
user.hideCosmetics(CosmeticUser.HiddenReason.EMOTE);
originalGamemode = player.getGameMode();
PacketManager.sendEntitySpawnPacket(thirdPersonLocation, armorStandId, EntityType.ARMOR_STAND, UUID.randomUUID(), viewer);
PacketManager.sendInvisibilityPacket(armorStandId, viewer);
PacketManager.sendLookPacket(armorStandId, player.getLocation(), viewer);
PacketManager.gamemodeChangePacket(player, 3);
PacketManager.sendCameraPacket(armorStandId, viewer);
MessagesUtil.sendDebugMessages("playAnimation run");
}
@Override
public boolean update() {
if (super.getAnimationProperty() == null) {
stopAnimation();
return false;
}
boolean update = (super.update() && isPlayingAnimation());
if (!update) {
stopAnimation();
}
return update;
}
public void stopAnimation() {
emotePlaying = null;
despawn();
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> {
Player player = user.getPlayer();
if (player == null) return;
List<Player> viewer = Collections.singletonList(player);
List<Player> outsideViewers = PacketManager.getViewers(player.getLocation());
outsideViewers.remove(player);
int entityId = player.getEntityId();
PacketManager.sendCameraPacket(entityId, viewer);
PacketManager.sendEntityDestroyPacket(armorStandId, viewer);
if (this.originalGamemode != null) {
PacketManager.gamemodeChangePacket(player, ServerUtils.convertGamemode(this.originalGamemode));
player.setGameMode(this.originalGamemode);
}
if (user.getPlayer() != null) player.setInvisible(false);
PacketManager.equipmentSlotUpdate(player, false, outsideViewers);
user.showPlayer();
user.showCosmetics();
});
}
public boolean isPlayingAnimation() {
return emotePlaying != null;
}
}

View File

@@ -1,10 +1,12 @@
package com.hibiscusmc.hmccosmetics.user;
package com.hibiscusmc.hmccosmetics.user.manager;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.config.WardrobeSettings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.nms.NMSHandlers;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.ServerUtils;
import com.hibiscusmc.hmccosmetics.util.packets.PacketManager;
@@ -22,49 +24,51 @@ import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
public class Wardrobe {
public class UserWardrobeManager {
private int NPC_ID;
private final int NPC_ID;
private final int ARMORSTAND_ID;
private final UUID WARDROBE_UUID;
private String npcName;
private UUID WARDROBE_UUID;
private int ARMORSTAND_ID;
private GameMode originalGamemode;
private CosmeticUser VIEWER;
private Location viewingLocation;
private Location npcLocation;
private final CosmeticUser user;
private final Location viewingLocation;
private final Location npcLocation;
private Location exitLocation;
private BossBar bossBar;
private boolean active;
private WardrobeStatus wardrobeStatus;
public Wardrobe(CosmeticUser user) {
public UserWardrobeManager(CosmeticUser user, Location exitLocation, Location viewingLocation, Location npcLocation) {
NPC_ID = NMSHandlers.getHandler().getNextEntityId();
ARMORSTAND_ID = NMSHandlers.getHandler().getNextEntityId();
WARDROBE_UUID = UUID.randomUUID();
VIEWER = user;
this.user = user;
this.exitLocation = exitLocation;
this.viewingLocation = viewingLocation;
this.npcLocation = npcLocation;
wardrobeStatus = WardrobeStatus.SETUP;
}
public void start() {
setWardrobeStatus(WardrobeStatus.STARTING);
Player player = VIEWER.getPlayer();
Player player = user.getPlayer();
this.originalGamemode = player.getGameMode();
if (WardrobeSettings.isReturnLastLocation()) {
this.exitLocation = player.getLocation().clone();
} else {
this.exitLocation = WardrobeSettings.getLeaveLocation();
}
viewingLocation = WardrobeSettings.getViewerLocation();
npcLocation = WardrobeSettings.getWardrobeLocation();
VIEWER.hidePlayer();
List<Player> viewer = List.of(player);
user.hidePlayer();
List<Player> viewer = Collections.singletonList(player);
List<Player> outsideViewers = PacketManager.getViewers(viewingLocation);
outsideViewers.remove(player);
@@ -99,17 +103,18 @@ public class Wardrobe {
PacketManager.sendRotationPacket(NPC_ID, npcLocation, true, viewer);
// Misc
if (VIEWER.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
PacketManager.ridingMountPacket(NPC_ID, VIEWER.getBackpackEntity().getEntityId(), viewer);
if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
user.getUserBackpackManager().getArmorStand().teleport(npcLocation.clone().add(0, 2, 0));
PacketManager.ridingMountPacket(NPC_ID, user.getUserBackpackManager().getFirstArmorStandId(), viewer);
}
if (VIEWER.hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
PacketManager.sendLeashPacket(VIEWER.getBalloonEntity().getPufferfishBalloonId(), -1, viewer);
PacketManager.sendLeashPacket(VIEWER.getBalloonEntity().getPufferfishBalloonId(), NPC_ID, viewer); // This needs a possible fix
if (user.hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
PacketManager.sendLeashPacket(user.getBalloonManager().getPufferfishBalloonId(), -1, viewer);
PacketManager.sendLeashPacket(user.getBalloonManager().getPufferfishBalloonId(), NPC_ID, viewer); // This needs a possible fix
//PacketManager.sendLeashPacket(VIEWER.getBalloonEntity().getModelId(), NPC_ID, viewer);
PacketManager.sendTeleportPacket(VIEWER.getBalloonEntity().getPufferfishBalloonId(), npcLocation.clone().add(Settings.getBalloonOffset()), false, viewer);
PacketManager.sendTeleportPacket(VIEWER.getBalloonEntity().getModelId(), npcLocation.clone().add(Settings.getBalloonOffset()), false, viewer);
PacketManager.sendTeleportPacket(user.getBalloonManager().getPufferfishBalloonId(), npcLocation.clone().add(Settings.getBalloonOffset()), false, viewer);
user.getBalloonManager().getModelEntity().teleport(npcLocation.clone().add(Settings.getBalloonOffset()));
}
if (WardrobeSettings.getEnabledBossbar()) {
@@ -130,7 +135,7 @@ public class Wardrobe {
if (WardrobeSettings.isEnabledTransition()) {
MessagesUtil.sendTitle(
VIEWER.getPlayer(),
user.getPlayer(),
WardrobeSettings.getTransitionText(),
WardrobeSettings.getTransitionFadeIn(),
WardrobeSettings.getTransitionStay(),
@@ -145,9 +150,9 @@ public class Wardrobe {
public void end() {
setWardrobeStatus(WardrobeStatus.STOPPING);
Player player = VIEWER.getPlayer();
Player player = user.getPlayer();
List<Player> viewer = List.of(player);
List<Player> viewer = Collections.singletonList(player);
List<Player> outsideViewers = PacketManager.getViewers(viewingLocation);
outsideViewers.remove(player);
@@ -157,7 +162,7 @@ public class Wardrobe {
this.active = false;
// NPC
if (VIEWER.hasCosmeticInSlot(CosmeticSlot.BALLOON)) PacketManager.sendLeashPacket(VIEWER.getBalloonEntity().getModelId(), -1, viewer);
if (user.hasCosmeticInSlot(CosmeticSlot.BALLOON)) PacketManager.sendLeashPacket(user.getBalloonManager().getModelId(), -1, viewer);
PacketManager.sendEntityDestroyPacket(NPC_ID, viewer); // Success
PacketManager.sendRemovePlayerPacket(player, WARDROBE_UUID, viewer); // Success
@@ -170,26 +175,22 @@ public class Wardrobe {
//PacketManager.sendEntityDestroyPacket(player.getEntityId(), viewer); // Success
player.setGameMode(this.originalGamemode);
VIEWER.showPlayer();
user.showPlayer();
if (VIEWER.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
VIEWER.respawnBackpack();
if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
user.respawnBackpack();
//PacketManager.ridingMountPacket(player.getEntityId(), VIEWER.getBackpackEntity().getEntityId(), viewer);
}
if (VIEWER.hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
VIEWER.respawnBalloon();
if (user.hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
user.respawnBalloon();
//PacketManager.sendLeashPacket(VIEWER.getBalloonEntity().getPufferfishBalloonId(), player.getEntityId(), viewer);
}
if (exitLocation == null) {
player.teleport(player.getWorld().getSpawnLocation());
} else {
player.teleport(exitLocation);
}
player.teleport(Objects.requireNonNullElseGet(exitLocation, () -> player.getWorld().getSpawnLocation()));
if (WardrobeSettings.isEquipPumpkin()) {
NMSHandlers.getHandler().equipmentSlotUpdate(VIEWER.getPlayer().getEntityId(), EquipmentSlot.HEAD, player.getInventory().getHelmet(), viewer);
NMSHandlers.getHandler().equipmentSlotUpdate(user.getPlayer().getEntityId(), EquipmentSlot.HEAD, player.getInventory().getHelmet(), viewer);
}
if (WardrobeSettings.getEnabledBossbar()) {
@@ -198,7 +199,14 @@ public class Wardrobe {
target.hideBossBar(bossBar);
}
VIEWER.updateCosmetic();
// For Wardrobe Temp Cosmetics
for (Cosmetic cosmetic : user.getCosmetic()) {
if (cosmetic.requiresPermission()) {
if (!player.hasPermission(cosmetic.getPermission())) user.removeCosmeticSlot(cosmetic.getSlot());
}
}
user.updateCosmetic();
};
run.run();
}
@@ -209,49 +217,50 @@ public class Wardrobe {
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
if (active == false) {
Player player = user.getPlayer();
if (!active || player == null) {
MessagesUtil.sendDebugMessages("Active is false");
this.cancel();
return;
}
MessagesUtil.sendDebugMessages("Update ");
List<Player> viewer = List.of(VIEWER.getPlayer());
List<Player> viewer = Collections.singletonList(player);
List<Player> outsideViewers = PacketManager.getViewers(viewingLocation);
outsideViewers.remove(VIEWER.getPlayer());
outsideViewers.remove(player);
Location location = WardrobeSettings.getWardrobeLocation().clone();
int yaw = data.get();
location.setYaw(yaw);
PacketManager.sendLookPacket(NPC_ID, location, viewer);
VIEWER.hidePlayer();
user.hidePlayer();
int rotationSpeed = WardrobeSettings.getRotationSpeed();
location.setYaw(getNextYaw(yaw - 30, rotationSpeed));
location.setYaw(ServerUtils.getNextYaw(yaw - 30, rotationSpeed));
PacketManager.sendRotationPacket(NPC_ID, location, true, viewer);
int nextyaw = getNextYaw(yaw, rotationSpeed);
int nextyaw = ServerUtils.getNextYaw(yaw, rotationSpeed);
data.set(nextyaw);
for (CosmeticSlot slot : CosmeticSlot.values()) {
PacketManager.equipmentSlotUpdate(NPC_ID, VIEWER, slot, viewer);
PacketManager.equipmentSlotUpdate(NPC_ID, user, slot, viewer);
}
if (VIEWER.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
PacketManager.sendTeleportPacket(VIEWER.getArmorstandId(), location, false, viewer);
PacketManager.ridingMountPacket(NPC_ID, VIEWER.getBackpackEntity().getEntityId(), viewer);
VIEWER.getBackpackEntity().setRotation(nextyaw, 0);
PacketManager.sendEntityDestroyPacket(VIEWER.getArmorstandId(), outsideViewers);
if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
PacketManager.sendTeleportPacket(user.getUserBackpackManager().getFirstArmorStandId(), location, false, viewer);
PacketManager.ridingMountPacket(NPC_ID, user.getUserBackpackManager().getFirstArmorStandId(), viewer);
user.getUserBackpackManager().getArmorStand().setRotation(nextyaw, 0);
PacketManager.sendEntityDestroyPacket(user.getUserBackpackManager().getFirstArmorStandId(), outsideViewers);
}
if (VIEWER.hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
PacketManager.sendTeleportPacket(VIEWER.getBalloonEntity().getPufferfishBalloonId(), WardrobeSettings.getWardrobeLocation().add(Settings.getBalloonOffset()), false, viewer);
VIEWER.getBalloonEntity().getModelEntity().teleport(WardrobeSettings.getWardrobeLocation().add(Settings.getBalloonOffset()));
PacketManager.sendLeashPacket(VIEWER.getBalloonEntity().getPufferfishBalloonId(), -1, outsideViewers);
PacketManager.sendEntityDestroyPacket(VIEWER.getBalloonEntity().getModelId(), outsideViewers);
//PacketManager.sendLeashPacket(VIEWER.getBalloonEntity().getModelId(), NPC_ID, viewer); // Pufferfish goes away for some reason?
if (user.hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
PacketManager.sendTeleportPacket(user.getBalloonManager().getPufferfishBalloonId(), WardrobeSettings.getWardrobeLocation().add(Settings.getBalloonOffset()), false, viewer);
user.getBalloonManager().getModelEntity().teleport(WardrobeSettings.getWardrobeLocation().add(Settings.getBalloonOffset()));
PacketManager.sendLeashPacket(user.getBalloonManager().getPufferfishBalloonId(), -1, outsideViewers);
PacketManager.sendEntityDestroyPacket(user.getBalloonManager().getModelId(), outsideViewers);
PacketManager.sendLeashPacket(user.getBalloonManager().getPufferfishBalloonId(), NPC_ID, viewer); // Pufferfish goes away for some reason?
}
if (WardrobeSettings.isEquipPumpkin()) {
NMSHandlers.getHandler().equipmentSlotUpdate(VIEWER.getPlayer().getEntityId(), EquipmentSlot.HEAD, new ItemStack(Material.CARVED_PUMPKIN), viewer);
NMSHandlers.getHandler().equipmentSlotUpdate(user.getPlayer().getEntityId(), EquipmentSlot.HEAD, new ItemStack(Material.CARVED_PUMPKIN), viewer);
}
}
};
@@ -259,16 +268,7 @@ public class Wardrobe {
runnable.runTaskTimer(HMCCosmeticsPlugin.getInstance(), 0, 2);
}
private static int getNextYaw(final int current, final int rotationSpeed) {
int nextYaw = current + rotationSpeed;
if (nextYaw > 179) {
nextYaw = (current + rotationSpeed) - 358;
return nextYaw;
}
return nextYaw;
}
public int getArmorstandId() {
public int getCameraId() {
return ARMORSTAND_ID;
}

View File

@@ -3,6 +3,8 @@ package com.hibiscusmc.hmccosmetics.util;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import org.bukkit.inventory.EquipmentSlot;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class InventoryUtils {
@@ -58,6 +60,8 @@ public class InventoryUtils {
};
}
@Contract(pure = true)
@Nullable
public static CosmeticSlot BukkitCosmeticSlot(int slot) {
switch (slot) {
case 36 -> {
@@ -81,6 +85,8 @@ public class InventoryUtils {
}
}
@Contract(pure = true)
@Nullable
public static CosmeticSlot NMSCosmeticSlot(int slot) {
switch (slot) {
case 5 -> {
@@ -104,7 +110,9 @@ public class InventoryUtils {
}
}
public static EquipmentSlot getEquipmentSlot(CosmeticSlot slot) {
@Contract(pure = true)
@Nullable
public static EquipmentSlot getEquipmentSlot(@NotNull CosmeticSlot slot) {
switch (slot) {
case HELMET -> {
return EquipmentSlot.HEAD;

View File

@@ -3,7 +3,8 @@ package com.hibiscusmc.hmccosmetics.util;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.config.WardrobeSettings;
import com.hibiscusmc.hmccosmetics.hooks.PAPIHook;
import com.hibiscusmc.hmccosmetics.hooks.Hooks;
import com.hibiscusmc.hmccosmetics.hooks.placeholders.HMCPlaceholderExpansion;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.misc.Adventure;
import me.clip.placeholderapi.PlaceholderAPI;
@@ -14,6 +15,8 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.title.Title;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import java.time.Duration;
@@ -23,9 +26,9 @@ import java.util.logging.Level;
public class MessagesUtil {
private static String prefix;
private static HashMap<String, String> messages = new HashMap<>();
private static final HashMap<String, String> messages = new HashMap<>();
public static void setup(ConfigurationNode config) {
public static void setup(@NotNull ConfigurationNode config) {
prefix = config.node("prefix").getString("");
for (ConfigurationNode node : config.childrenMap().values()) {
if (node.virtual()) continue;
@@ -34,7 +37,7 @@ public class MessagesUtil {
}
}
public static void sendMessage(CosmeticUser user, String key) {
public static void sendMessage(@NotNull CosmeticUser user, String key) {
sendMessage(user.getPlayer(), key);
}
@@ -91,11 +94,12 @@ public class MessagesUtil {
return processString(player, key, null);
}
@Nullable
public static Component processString(Player player, String key, TagResolver placeholders) {
if (!messages.containsKey(key)) return null;
if (messages.get(key) == null) return null;
String message = messages.get(key);
if (PAPIHook.isPAPIEnabled() && player != null) message = PlaceholderAPI.setPlaceholders(player, message);
if (Hooks.isActiveHook("PlaceholderAPI") && player != null) message = PlaceholderAPI.setPlaceholders(player, message);
message = message.replaceAll("%prefix%", prefix);
if (placeholders != null ) {
return Adventure.MINI_MESSAGE.deserialize(message, placeholders);
@@ -103,17 +107,20 @@ public class MessagesUtil {
return Adventure.MINI_MESSAGE.deserialize(message);
}
@NotNull
public static Component processStringNoKey(String message) {
return processStringNoKey(null, message, null);
}
@NotNull
public static Component processStringNoKey(Player player, String message) {
return processStringNoKey(player, message, null);
}
@NotNull
public static Component processStringNoKey(Player player, String message, TagResolver placeholders) {
message = message.replaceAll("%prefix%", prefix);
if (PAPIHook.isPAPIEnabled() && player != null) message = PlaceholderAPI.setPlaceholders(player, message);
if (Hooks.isActiveHook("PlaceholderAPI") && player != null) message = PlaceholderAPI.setPlaceholders(player, message);
if (placeholders != null ) {
return Adventure.MINI_MESSAGE.deserialize(message, placeholders);
}
@@ -122,7 +129,7 @@ public class MessagesUtil {
public static String processStringNoKeyString(Player player, String message) {
message = message.replaceAll("%prefix%", prefix);
if (PAPIHook.isPAPIEnabled() && player != null) message = PlaceholderAPI.setPlaceholders(player, message);
if (Hooks.isActiveHook("PlaceholderAPI") && player != null) message = PlaceholderAPI.setPlaceholders(player, message);
return message;
}

View File

@@ -6,12 +6,15 @@ import com.hibiscusmc.hmccosmetics.config.Settings;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class PlayerUtils {
@Nullable
public static WrappedSignedProperty getSkin(Player player) {
WrappedSignedProperty skinData = WrappedGameProfile.fromPlayer(player).getProperties()
.get("textures").stream().findAny().orElse(null);
@@ -22,11 +25,13 @@ public class PlayerUtils {
return new WrappedSignedProperty("textures", skinData.getValue(), skinData.getSignature());
}
public static List<Player> getNearbyPlayers(Player player) {
@NotNull
public static List<Player> getNearbyPlayers(@NotNull Player player) {
return getNearbyPlayers(player.getLocation());
}
public static List<Player> getNearbyPlayers(Location location) {
@NotNull
public static List<Player> getNearbyPlayers(@NotNull Location location) {
List<Player> players = new ArrayList<>();
int viewDistance = Settings.getViewDistance();
for (Entity entity : location.getWorld().getNearbyEntities(location, viewDistance, viewDistance, viewDistance)) {

View File

@@ -1,8 +1,18 @@
package com.hibiscusmc.hmccosmetics.util;
import com.hibiscusmc.hmccosmetics.nms.NMSHandlers;
import com.owen1212055.particlehelper.api.particle.MultiParticle;
import com.owen1212055.particlehelper.api.particle.Particle;
import com.owen1212055.particlehelper.api.particle.types.*;
import com.owen1212055.particlehelper.api.particle.types.dust.transition.TransitionDustParticle;
import com.owen1212055.particlehelper.api.particle.types.note.MultiNoteParticle;
import org.bukkit.Color;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.jetbrains.annotations.Nullable;
import java.math.BigInteger;
import java.util.Arrays;
public class ServerUtils {
@@ -27,6 +37,16 @@ public class ServerUtils {
}
public static Color hex2Rgb(String colorStr) {
if (colorStr.startsWith("#")) return Color.fromRGB(Integer.valueOf(colorStr.substring(1), 16));
if (colorStr.startsWith("0x")) return Color.fromRGB(Integer.valueOf(colorStr.substring(2), 16));
if (colorStr.contains(",")) {
String[] colorString = colorStr.replace(" ", "").split(",");
for (String color : colorString) if (Integer.valueOf(color) == null) return Color.WHITE;
Color.fromRGB(Integer.valueOf(colorString[0]), Integer.valueOf(colorString[1]), Integer.valueOf(colorString[2]));
}
return Color.WHITE;
/* Old method
try {
return Color.fromRGB(
Integer.valueOf(colorStr.substring(1, 3), 16),
@@ -35,5 +55,95 @@ public class ServerUtils {
} catch (StringIndexOutOfBoundsException e) {
return null;
}
*/
}
// particle amount offsetxyz
// Ex. HEART 10 0.1 0.1 0.1
public static Particle addParticleValues(Particle particle, String[] split) {
var counter = 1;
if (particle instanceof MultiParticle multiParticle) {
multiParticle.setCount(getBigInteger(split[counter]).intValue());
counter++;
multiParticle.setXOffset(getBigInteger(split[counter]).floatValue());
counter++;
multiParticle.setYOffset(getBigInteger(split[counter]).floatValue());
counter++;
multiParticle.setZOffset(getBigInteger(split[counter]).floatValue());
counter++;
if (multiParticle instanceof MultiNoteParticle multiNoteParticle) {
multiNoteParticle.setColorMultplier(getBigInteger(split[counter]).intValue());
counter++;
}
}
if (particle instanceof ColorableParticle colorableParticle && colorFromString(split[counter]) != null) {
colorableParticle.setColor(colorFromString(split[counter]));
counter++;
}
if (particle instanceof TransitionDustParticle transitionDustParticle && colorFromString(split[counter]) != null) {
transitionDustParticle.setFadeColor(colorFromString(split[counter]));
counter++;
}
if (particle instanceof MaterialParticle materialParticle && Material.getMaterial(split[counter]) != null) {
materialParticle.setMaterial(Material.getMaterial(split[counter]));
counter++;
}
if (particle instanceof SpeedModifiableParticle speedModifiableParticle) {
speedModifiableParticle.setSpeed(getBigInteger(split[counter]).floatValue());
counter++;
}
if (particle instanceof DelayableParticle delayableParticle) {
delayableParticle.setDelay(getBigInteger(split[counter]).intValue());
counter++;
}
if (particle instanceof SizeableParticle sizeableParticle) {
sizeableParticle.setSize(getBigInteger(split[counter]).floatValue());
counter++;
}
if (particle instanceof RollableParticle rollableParticle) {
rollableParticle.setRoll(getBigInteger(split[counter]).floatValue());
}
return particle;
}
private static BigInteger getBigInteger(String string) {
try {
return new BigInteger(string);
} catch (Exception e) {
return BigInteger.valueOf(1);
}
}
/**
* Parse a color from a string.
* Formats: #RRGGBB; R,G,B
*
* @param color The string
* @return The color, if the string can't be parsed, null is returned
*/
public static Color colorFromString(@Nullable String color) {
if (color == null) {
return null;
}
try {
var decodedColor = java.awt.Color.decode(color.startsWith("#") ? color : "#" + color);
return Color.fromRGB(decodedColor.getRed(), decodedColor.getGreen(), decodedColor.getBlue());
} catch (NumberFormatException invalidHex) {
try {
var rgbValues = Arrays.stream(color.split(",")).map(Integer::parseInt).toArray(Integer[]::new);
return Color.fromRGB(rgbValues[0], rgbValues[1], rgbValues[2]);
} catch (Exception invalidRgb) {
return null;
}
}
}
public static int getNextYaw(final int current, final int rotationSpeed) {
int nextYaw = current + rotationSpeed;
if (nextYaw > 179) {
nextYaw = (current + rotationSpeed) - 358;
return nextYaw;
}
return nextYaw;
}
}

View File

@@ -6,6 +6,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.jetbrains.annotations.NotNull;
public class ColorBuilder {
@@ -13,7 +14,7 @@ public class ColorBuilder {
return canBeColored(new ItemStack(material));
}
public static boolean canBeColored(final ItemStack itemStack) {
public static boolean canBeColored(final @NotNull ItemStack itemStack) {
final ItemMeta itemMeta = itemStack.getItemMeta();
return (itemMeta instanceof LeatherArmorMeta ||

View File

@@ -8,6 +8,8 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@@ -33,7 +35,7 @@ public class ItemBuilder {
* @param itemStack builder ItemStack
*/
ItemBuilder(final ItemStack itemStack) {
ItemBuilder(final @NotNull ItemStack itemStack) {
this.material = itemStack.getType();
this.itemMeta = itemStack.hasItemMeta() ? itemStack.getItemMeta()
: Bukkit.getItemFactory().getItemMeta(this.material);
@@ -44,6 +46,8 @@ public class ItemBuilder {
* @return
*/
@Contract("_ -> new")
@NotNull
public static ItemBuilder from(final Material material) {
return new ItemBuilder(material);
}
@@ -52,7 +56,8 @@ public class ItemBuilder {
* @param itemStack builder ItemStack
* @return
*/
@Contract("_ -> new")
@NotNull
public static ItemBuilder from(final ItemStack itemStack) {
return new ItemBuilder(itemStack);
}

View File

@@ -6,6 +6,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.NotNull;
public class Keys {
@@ -13,7 +14,7 @@ public class Keys {
public static final NamespacedKey ITEM_KEY = new NamespacedKey(plugin, "cosmetic");
public static final NamespacedKey TOKEN_KEY = new NamespacedKey(plugin, "token-key");
public static void setKey(final ItemStack itemStack) {
public static void setKey(final @NotNull ItemStack itemStack) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
@@ -26,7 +27,7 @@ public class Keys {
}
public static <T, Z> void setKey(
final ItemStack itemStack,
final @NotNull ItemStack itemStack,
final NamespacedKey key,
final PersistentDataType<T, Z> type,
final Z value) {
@@ -41,7 +42,7 @@ public class Keys {
itemStack.setItemMeta(itemMeta);
}
public static boolean hasKey(final ItemStack itemStack) {
public static boolean hasKey(final @NotNull ItemStack itemStack) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
@@ -51,7 +52,7 @@ public class Keys {
return itemMeta.getPersistentDataContainer().has(ITEM_KEY, PersistentDataType.BYTE);
}
public static <T, Z> boolean hasKey(final ItemStack itemStack, final NamespacedKey key, final PersistentDataType<T, Z> type) {
public static <T, Z> boolean hasKey(final @NotNull ItemStack itemStack, final NamespacedKey key, final PersistentDataType<T, Z> type) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
@@ -62,7 +63,7 @@ public class Keys {
}
@Nullable
public static <T, Z> Z getValue(final ItemStack itemStack, final NamespacedKey key, final PersistentDataType<T, Z> type) {
public static <T, Z> Z getValue(final @NotNull ItemStack itemStack, final NamespacedKey key, final PersistentDataType<T, Z> type) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {

View File

@@ -1,6 +1,7 @@
package com.hibiscusmc.hmccosmetics.util.misc;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
public class StringUtils {
@@ -8,15 +9,17 @@ public class StringUtils {
* @param parsed message to be parsed
* @return MiniMessage parsed string
*/
@NotNull
public static Component parse(final String parsed) {
return Adventure.MINI_MESSAGE.deserialize(parsed);
}
@NotNull
public static String parseStringToString(final String parsed) {
return Adventure.SERIALIZER.serialize(Adventure.MINI_MESSAGE.deserialize(parsed));
}
@NotNull
public static String formatArmorItemType(String type) {
type = type.toLowerCase();
final String[] parts = type.split(" ");

View File

@@ -29,7 +29,7 @@ public class Utils {
return original;
}
public static <T> T replaceIf(final @Nullable T original, final T replacement, final Predicate<T> predicate) {
public static <T> T replaceIf(final @Nullable T original, final T replacement, final @NotNull Predicate<T> predicate) {
if (predicate.test(original)) return replacement;
return original;
}

View File

@@ -16,9 +16,13 @@ import com.hibiscusmc.hmccosmetics.util.packets.wrappers.WrapperPlayServerPlayer
import com.hibiscusmc.hmccosmetics.util.packets.wrappers.WrapperPlayServerRelEntityMove;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
@@ -28,11 +32,11 @@ import java.util.UUID;
public class PacketManager extends BasePacket {
public static void sendEntitySpawnPacket(
final Location location,
final @NotNull Location location,
final int entityId,
final EntityType entityType,
final UUID uuid,
final List<Player> sendTo
final @NotNull List<Player> sendTo
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
packet.getModifier().writeDefaults();
@@ -61,7 +65,7 @@ public class PacketManager extends BasePacket {
public static void ridingMountPacket(
int mountId,
int passengerId,
List<Player> sendTo
@NotNull List<Player> sendTo
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.MOUNT);
packet.getIntegers().write(0, mountId);
@@ -71,6 +75,17 @@ public class PacketManager extends BasePacket {
public static void equipmentSlotUpdate(
Player player,
boolean empty,
List<Player> sendTo
) {
for (EquipmentSlot slot : EquipmentSlot.values()) {
ItemStack item = player.getInventory().getItem(slot);
if (empty) item = new ItemStack(Material.AIR);
NMSHandlers.getHandler().equipmentSlotUpdate(player.getEntityId(), slot, item, sendTo);
}
}
public static void equipmentSlotUpdate(
@NotNull Player player,
CosmeticSlot cosmetic,
List<Player> sendTo
) {
@@ -91,13 +106,13 @@ public class PacketManager extends BasePacket {
CosmeticSlot cosmeticSlot,
List<Player> sendTo
) {
if (cosmeticSlot == CosmeticSlot.BACKPACK || cosmeticSlot == CosmeticSlot.BALLOON) return;
if (cosmeticSlot == CosmeticSlot.BACKPACK || cosmeticSlot == CosmeticSlot.BALLOON || cosmeticSlot == CosmeticSlot.EMOTE) return;
NMSHandlers.getHandler().equipmentSlotUpdate(entityId, user, cosmeticSlot, sendTo);
}
public static void armorStandMetaPacket(
Entity entity,
@NotNull Entity entity,
List<Player> sendTo
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
@@ -133,9 +148,9 @@ public class PacketManager extends BasePacket {
}
public static void sendLookPacket(
int entityId,
Location location,
List<Player> sendTo
int entityId,
@NotNull Location location,
@NotNull List<Player> sendTo
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_HEAD_ROTATION);
packet.getIntegers().write(0, entityId);
@@ -152,10 +167,10 @@ public class PacketManager extends BasePacket {
}
public static void sendRotationPacket(
int entityId,
Location location,
boolean onGround,
List<Player> sendTo
int entityId,
@NotNull Location location,
boolean onGround,
@NotNull List<Player> sendTo
) {
float ROTATION_FACTOR = 256.0F / 360.0F;
float yaw = location.getYaw() * ROTATION_FACTOR;
@@ -174,7 +189,7 @@ public class PacketManager extends BasePacket {
int entityId,
int yaw,
boolean onGround,
List<Player> sendTo
@NotNull List<Player> sendTo
) {
float ROTATION_FACTOR = 256.0F / 360.0F;
float yaw2 = yaw * ROTATION_FACTOR;
@@ -211,7 +226,7 @@ public class PacketManager extends BasePacket {
public static void sendRidingPacket(
final int mountId,
final int passengerId,
final List<Player> sendTo
final @NotNull List<Player> sendTo
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.MOUNT);
packet.getIntegers().write(0, mountId);
@@ -226,7 +241,7 @@ public class PacketManager extends BasePacket {
* @param entityId The entity to delete for a player
* @param sendTo The players the packet should be sent to
*/
public static void sendEntityDestroyPacket(final int entityId, List<Player> sendTo) {
public static void sendEntityDestroyPacket(final int entityId, @NotNull List<Player> sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
packet.getModifier().write(0, new IntArrayList(new int[]{entityId}));
for (final Player p : sendTo) sendPacket(p, packet);
@@ -237,7 +252,7 @@ public class PacketManager extends BasePacket {
* @param entityId The Entity ID that camera will go towards
* @param sendTo The players that will be sent this packet
*/
public static void sendCameraPacket(final int entityId, List<Player> sendTo) {
public static void sendCameraPacket(final int entityId, @NotNull List<Player> sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.CAMERA);
packet.getIntegers().write(0, entityId);
for (final Player p : sendTo) sendPacket(p, packet);
@@ -252,10 +267,10 @@ public class PacketManager extends BasePacket {
* @param sendTo Who should it send the packet to?
*/
public static void sendFakePlayerSpawnPacket(
final Location location,
final @NotNull Location location,
final UUID uuid,
final int entityId,
final List<Player> sendTo
final @NotNull List<Player> sendTo
) {
WrapperPlayServerNamedEntitySpawn wrapper = new WrapperPlayServerNamedEntitySpawn();
wrapper.setEntityID(entityId);
@@ -312,7 +327,7 @@ public class PacketManager extends BasePacket {
*/
public static void sendPlayerOverlayPacket(
final int playerId,
final List<Player> sendTo
final @NotNull List<Player> sendTo
) {
/*
0x01 = Is on fire
@@ -384,7 +399,7 @@ public class PacketManager extends BasePacket {
public static void sendLeashPacket(
final int leashedEntity,
final int entityId,
final List<Player> sendTo
final @NotNull List<Player> sendTo
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ATTACH_ENTITY);
packet.getIntegers().write(0, leashedEntity);
@@ -403,9 +418,9 @@ public class PacketManager extends BasePacket {
*/
public static void sendTeleportPacket(
final int entityId,
final Location location,
final @NotNull Location location,
boolean onGround,
final List<Player> sendTo
final @NotNull List<Player> sendTo
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
packet.getIntegers().write(0, entityId);
@@ -430,10 +445,10 @@ public class PacketManager extends BasePacket {
*/
public static void sendMovePacket(
final int entityId,
final Location from,
final Location to,
final @NotNull Location from,
final @NotNull Location to,
final boolean onGround,
List<Player> sendTo
@NotNull List<Player> sendTo
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE);
WrapperPlayServerRelEntityMove wrapper = new WrapperPlayServerRelEntityMove(packet);
@@ -456,6 +471,7 @@ public class PacketManager extends BasePacket {
sendMovePacket(entityId, from, to, onGround, getViewers(to));
}
@NotNull
public static List<Player> getViewers(Location location) {
ArrayList<Player> viewers = new ArrayList();
if (Settings.getViewDistance() <= 0) {

View File

@@ -6,6 +6,7 @@ import com.comphenix.protocol.events.PacketEvent;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
@@ -58,7 +59,7 @@ public class WrapperPlayServerNamedEntitySpawn extends AbstractPacket {
* @param event - the packet event.
* @return The spawned entity.
*/
public Entity getEntity(PacketEvent event) {
public Entity getEntity(@NotNull PacketEvent event) {
return getEntity(event.getPlayer().getWorld());
}
@@ -96,7 +97,7 @@ public class WrapperPlayServerNamedEntitySpawn extends AbstractPacket {
*
* @param position - the new position.
*/
public void setPosition(Vector position) {
public void setPosition(@NotNull Vector position) {
setX(position.getX());
setY(position.getY());
setZ(position.getZ());

View File

@@ -5,6 +5,7 @@ import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
public class WrapperPlayServerRelEntityMove extends AbstractPacket {
public static final PacketType TYPE =
@@ -55,7 +56,7 @@ public class WrapperPlayServerRelEntityMove extends AbstractPacket {
* @param event - the packet event.
* @return The spawned entity.
*/
public Entity getEntity(PacketEvent event) {
public Entity getEntity(@NotNull PacketEvent event) {
return getEntity(event.getPlayer().getWorld());
}

View File

@@ -21,6 +21,10 @@ cosmetic-settings:
# Ticking periods is something that ensures new players near a player get the packets to actually apply to the user.
unapply-on-death: false # If when a player dies, their cosmetics should be unapplied. If this is true, use hmccosmetics.unapplydeath.bypass to bypass
force-permission-join: true # Checks a player permission if they can have a cosmetic when they join the server.
emote-distance: -3 # This shows how far away the camera should be while a player is doing an emote. Negative is behind player.
emote-block-check: true # If the server should check if the block is open (prevents players viewing through blocks)
# view distance in blocks that other players will see the backpack cosmetic
# setting this to lower than the server player view distance should fix the
@@ -32,7 +36,16 @@ cosmetic-settings:
y: 3
z: 0.5
dye-menu:
title: "<white>"
# If you use ItemsAdder, set this to "§f:offset_-8::dye_menu:"
# If you use Oraxen, set this to "<glyph:neg_shift_8><glyph:dye_menu>"
title: "§f"
input-slot: 19
output-slot: 25
hook-settings:
itemsadder:
# This causes the plugin to reload itself after any ItemsAdder change. This keeps the plugin fully up to date with IA, but
# could cause console spam as HMCCosmetics has to reload itself as well.
reload-on-change: false
wardrobe:
# spawn static wardrobe if in this radius of wardrobe-location
static-radius: 10
@@ -48,6 +61,7 @@ wardrobe:
text: "Left-Click to open the menu!"
progress: 1.0 # Goes between 0.0 -> 1.0
overlay: PROGRESS
color: BLUE
transition:
enabled: true
text: "<black>"
@@ -75,4 +89,4 @@ wardrobe:
y: 5
z: 5
yaw: 0
pitch: 0
pitch: 0

View File

@@ -87,9 +87,27 @@ boots:
kite:
slot: BALLOON
permission: "hmccosmetics.kite"
model: kite
model: kite # This is the ModelEngine model it will use. If you do not have ModelEngine installed, it will default to the item.
item:
material: PAPER
model-data: 7
name: "<blue>Kite"
amount: 1
handstand:
slot: EMOTE
animation: handstand
meditate:
slot: EMOTE
animation: meditate
thinking:
slot: EMOTE
animation: thinking
explorer_backpack:
slot: BACKPACK
permission: "hmccosmetics.explorer_backpack"
dyeable: true
item:
material: LEATHER_HORSE_ARMOR
model-data: 3
name: "<white>Explorer's Backpack"
amount: 1

View File

@@ -1,9 +1,9 @@
title: "<white>"
rows: 5
rows: 6
items:
beanie:
slots:
- 1
- 0
item:
material: hmccosmetics:beanie
lore:
@@ -14,7 +14,7 @@ items:
cosmetic: beanie
backpack:
slots:
- 2
- 1
item:
material: hmccosmetics:backpack
lore:
@@ -25,7 +25,7 @@ items:
cosmetic: backpack
future_wings:
slots:
- 3
- 2
item:
material: hmccosmetics:future_wings
lore:
@@ -36,7 +36,7 @@ items:
cosmetic: future_wings
lantern_cosmetic:
slots:
- 4
- 3
item:
material: hmccosmetics:lantern_cosmetic
lore:
@@ -47,7 +47,7 @@ items:
cosmetic: lantern_cosmetic
baseball_hat:
slots:
- 5
- 4
item:
material: hmccosmetics:baseball_hat
lore:
@@ -58,7 +58,7 @@ items:
cosmetic: baseball_hat
frog_hat:
slots:
- 6
- 5
item:
material: hmccosmetics:frog_hat
lore:
@@ -69,7 +69,7 @@ items:
cosmetic: frog_hat
jetpack:
slots:
- 7
- 6
item:
material: hmccosmetics:jetpack
lore:
@@ -80,7 +80,7 @@ items:
cosmetic: jetpack
hammer:
slots:
- 10
- 7
item:
material: hmccosmetics:hammer
lore:
@@ -91,7 +91,7 @@ items:
cosmetic: hammer
chestplate:
slots:
- 11
- 8
item:
material: hmccosmetics:chestplate
lore:
@@ -102,7 +102,7 @@ items:
cosmetic: chestplate
pants:
slots:
- 12
- 9
item:
material: hmccosmetics:pants
lore:
@@ -113,7 +113,7 @@ items:
cosmetic: pants
boots:
slots:
- 13
- 10
item:
material: hmccosmetics:boots
lore:
@@ -124,7 +124,7 @@ items:
cosmetic: boots
kite:
slots:
- 14
- 11
item:
material: hmccosmetics:kite
lore:
@@ -132,4 +132,39 @@ items:
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_kite%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_kite%"
type: cosmetic
cosmetic: kite
cosmetic: kite
handstand:
slots:
- 12
item:
material: PAPER
name: "<blue>Handstand Emote"
type: cosmetic
cosmetic: handstand
meditate:
slots:
- 13
item:
material: PAPER
name: "<blue>Meditate Emote"
type: cosmetic
cosmetic: meditate
thinking:
slots:
- 14
item:
material: PAPER
name: "<blue>Thinking Emote"
type: cosmetic
cosmetic: thinking
explorer_backpack:
slots:
- 15
item:
material: hmccosmetics:explorer_backpack
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_explorer_backpack%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_explorer_backpack%"
type: cosmetic
cosmetic: explorer_backpack

View File

@@ -17,6 +17,9 @@ unequip-cosmetic: "%prefix% <gradient:#6D9DC5:#45CDE9>You have unequipped <cosme
hide-cosmetic: "%prefix% <gradient:#6D9DC5:#45CDE9>Hidden cosmetics"
show-cosmetic: "%prefix% <gradient:#6D9DC5:#45CDE9>Revealed cosmetics!"
emote-blocked: "%prefix% <red>You can not use your emote here!"
emote-none: "%prefix% <red>You have no emote equipped!"
invalid-slot: "%prefix% <red>Invalid cosmetic slot!"
invalid-player: "%prefix% <red>Invalid Player!"
invalid-menu: "%prefix% <red>Invalid Menu!"

BIN
lib/CMI-API9.3.1.5.jar Normal file

Binary file not shown.

BIN
lib/CMILib1.2.4.6.jar Normal file

Binary file not shown.

674
license.md Normal file
View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -4,9 +4,12 @@ pluginManagement {
maven("https://repo.papermc.io/repository/maven-public/")
}
}
rootProject.name = "HMCCosmetics"
include(
"common",
"v1_17_R1",
"v1_18_R2",
"v1_19_R1",
"v1_19_R2"
)

Some files were not shown because too many files have changed in this diff Show More