9
0
mirror of https://github.com/HibiscusMC/HMCCosmetics.git synced 2025-12-22 16:39:21 +00:00

Compare commits

...

172 Commits

Author SHA1 Message Date
LoJoSho
6e94d74990 removed Citizens hook
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-21 11:09:56 -05:00
LoJoSho
5e3edd472c Revert previous commit
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-04 14:44:39 -05:00
LoJoSho
791fe53c48 NMS Test
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-04 14:32:08 -05:00
LoJoSho
c9f7762a26 work on ME 3.0
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-03 21:38:22 -05:00
LoJoSho
1be95c78c2 Moved around code
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-03 20:24:26 -05:00
LoJoSho
2be06e3ad9 Debug Logging for Balloons
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-03 20:24:12 -05:00
LoJoSho
d4bf6f256b Equipment no longer always sends full slots
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-30 12:29:10 -05:00
LoJoSho
5ffe39cdba Remove debug message
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-25 19:39:25 -05:00
LoJoSho
e6c81f8d1e Merge remote-tracking branch 'origin/plib_switch' into plib_switch 2022-09-25 19:36:23 -05:00
LoJoSho
0378b98967 Packet Overhaul, ME 3.0 Work, Teleport to last location config option
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-25 19:36:03 -05:00
lucian929
a26edbfc9c Add new cosmetics 2022-09-24 12:49:57 -04:00
lucian929
19e8a3bf10 Disable first person backpacks temporarily 2022-09-19 10:07:38 -04:00
LoJoSho
b8aefbacdb version bump (1.12.0-BETA-5)
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-10 21:26:15 -05:00
LoJoSho
7a29aa8927 Disabled Model Engine integration
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-10 21:23:51 -05:00
LoJoSho
482aec27f1 Fix for client disconnect as NPC name was >16 characters
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-10 21:22:52 -05:00
LoJoSho
007e5487e6 Added pumpkin option for wardrobe
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-05 20:59:59 -05:00
LoJoSho
e7f077af7a Merge remote-tracking branch 'origin/plib_switch' into plib_switch 2022-09-05 20:26:28 -05:00
LoJoSho
99b1afd15c Changed info packet to be sent earlier 2022-09-05 20:26:10 -05:00
lucian929
3f5acde838 Update libraries
Signed-off-by: lucian929 <lucianfp27091@gmail.com>
2022-09-01 10:49:35 -04:00
LoJoSho
2676505c9a Version Bump (Beta-4) 2022-08-29 19:26:21 -05:00
LoJoSho
f5d1a09d28 Gui Opening + Skins in Wardrobe 2022-08-29 19:24:18 -05:00
LoJoSho
1b9e2ac531 Wardrobe Works! 2022-08-29 18:39:34 -05:00
LoJoSho
b005614881 Bundle of small changes 2022-08-29 14:16:43 -05:00
lucian929
a41fb7df2b Beta-3 2022-08-19 16:23:33 -04:00
LoJoSho
e0fbbc7f76 Fixed issue with armor not showing 2022-08-19 15:21:47 -05:00
LoJoSho
cb09da91fe Removed boolean from packet 2022-08-19 15:21:30 -05:00
LoJoSho
cd7ed29522 remove line 2022-08-19 15:20:29 -05:00
LoJoSho
f5a7c2f9f0 Byte mask apply 2022-08-18 17:47:53 -05:00
LoJoSho
6af8e13dab Removed Debug Messages 2022-08-18 17:36:52 -05:00
LoJoSho
e3f081f1c9 Version Bump (Beta-2) 2022-08-18 17:35:48 -05:00
LoJoSho
c7ba2f179a Update Citizens 2022-08-18 17:35:30 -05:00
LoJoSho
8f012f6c97 Fixed duplicate entity ids causing visual issues 2022-08-18 17:35:18 -05:00
LoJoSho
e95b30131c Bundle of changes 2022-08-18 15:02:21 -05:00
LoJoSho
2dc068a938 Bundle of changes 2022-08-15 17:59:53 -05:00
lucian929
7bdc122cb1 Bump version number (initial beta) 2022-08-15 16:31:09 -04:00
lucian929
a3d57af18d Merge pull request #31 from LoJoSho/lojo_dev
Experimental ProtocolLib Switch
2022-08-15 16:25:20 -04:00
LoJoSho
235c0a9307 Cosmetic Fixes 2022-08-15 15:17:16 -05:00
LoJoSho
4d7e565c23 Latest Commit 2022-08-12 14:34:54 -05:00
LoJoSho
57d3110740 It works! 2022-08-12 09:49:31 -05:00
LoJoSho
61e226b826 Compiling without PacketEvents 2022-08-09 22:16:35 -05:00
LoJoSho
bd7b045c0f Initial ProtocolLib Testing 2022-08-08 13:05:50 -05:00
LoJoSho
1ce28a9f66 Uncommented ProtocolLib 2022-08-08 13:05:04 -05:00
lucian929
70c2b79b6c Bump version number 2022-07-25 18:54:27 -04:00
Boy0000
39d485ddfe remove broadcast (#29) 2022-07-26 00:53:01 +02:00
lucian929
548a6bf4ec Merge pull request #28 from HibiscusMC/1.19_fix
1.19 fix
2022-07-25 18:50:24 -04:00
Boy
fb15919f52 update non-existing packet 2022-07-26 00:45:26 +02:00
lucian929
9a5923bb7d Merge remote-tracking branch 'origin/master' 2022-07-20 18:33:40 -04:00
lucian929
02239396f0 Changes to build.gradle.kts for MEG (temporary fix) 2022-07-20 18:33:20 -04:00
lucian929
942d48adf8 Merge pull request #26 from HibiscusMC/copyjar_task
add copyjar task
2022-07-17 18:06:01 -04:00
Boy
99ae2b765a add copyjar task 2022-07-18 00:04:13 +02:00
lucian929
6b59ba88a5 Bump version number 2022-07-11 13:15:12 -04:00
Fisher2911
4d7dff885a Merge remote-tracking branch 'origin/master' 2022-07-11 13:14:07 -04:00
Fisher2911
f4bc6f1bc3 Fixed particle amounts not working 2022-07-11 13:13:54 -04:00
lucian929
938dfe677d Fix mistake in config 2022-07-08 20:48:08 -04:00
Fisher2911
1c30924410 Merge remote-tracking branch 'origin/master' 2022-07-08 20:26:38 -04:00
lucian929
bd731c8b6b bump version number (1.11.0)! 2022-07-08 20:24:24 -04:00
lucian929
41f4f830d1 Update default configs 2022-07-08 20:22:50 -04:00
Fisher2911
86346583cc Fixed unequipping first person cosmetics 2022-07-08 20:13:43 -04:00
Fisher2911
b13d44536f Fixed rotation for other players 2022-07-08 15:56:46 -04:00
Fisher2911
822422d4a5 First person back hidden mode works 2022-07-08 15:51:51 -04:00
Fisher2911
449fc8a84b Why 2022-07-03 21:10:37 -04:00
Fisher2911
9be234cf11 Why 2022-07-03 21:08:30 -04:00
Fisher2911
08be1d56ac Attempting first person view stuff 2022-07-02 20:21:29 -04:00
lucian929
c6aecaae80 Change dependency info 2022-05-26 15:11:04 -04:00
lucian929
d25336f966 Feature request template (credit Skyslycer) 2022-05-22 10:57:21 -04:00
lucian929
49dfb46cc5 Unshaded packetevents (jar can be downloaded at https://github.com/retrooper/packetevents/actions) 2022-05-13 15:39:47 -04:00
lucian929
4774e2d1d6 build.gradle changes 2022-05-06 19:58:10 -04:00
Fisher2911
31775c5e85 Removed sending packets silently 2022-04-29 21:45:39 -04:00
Fisher2911
59bba0e854 Merge remote-tracking branch 'origin/master' 2022-04-29 21:44:44 -04:00
Fisher2911
74a0d279b0 Added close menu action 2022-04-29 21:44:29 -04:00
lucian929
3d51b77123 Fix look-down-backpack-remove 2022-04-07 00:01:50 -04:00
Fisher2911
fc7b886727 Merge remote-tracking branch 'origin/master' 2022-04-06 23:35:28 -04:00
Fisher2911
4be32d3849 Allow console command for wardrobe 2022-04-06 23:35:19 -04:00
lucian929
e39b56a63e Bump version number 2022-04-05 21:50:57 -04:00
Fisher2911
bc994bfa2f Fixed balloons not being removed in wardrobe 2022-04-05 21:44:03 -04:00
Fisher2911
0ea5c92d86 Fixed issue with not opening wardrobe inventory 2022-04-03 22:27:08 -04:00
Fisher2911
3ed245c95b Improved wardrobe viewing 2022-04-03 21:33:45 -04:00
Fisher2911
7bb4312fee 1.18.2 support, balloon bug fix 2022-04-01 23:04:45 -04:00
Fisher2911
24c06fd12c Fixed files not getting committed 2022-03-29 20:31:43 -04:00
Fisher2911
3a0ff5504e Fixed files not getting committed 2022-03-29 20:28:37 -04:00
Fisher2911
7caeec3fd1 Fixed packet sending 2022-03-29 20:17:28 -04:00
Fisher2911
4e3c0b1c6b Merge remote-tracking branch 'origin/master' 2022-03-22 22:50:57 -04:00
Fisher2911
383ee49d67 Progress so far with switching to PacketEvents 2022-03-22 22:50:32 -04:00
Fisher2911
67e3dbfcf5 Changed to use PacketEvents 2022-03-18 17:14:30 -04:00
lucian929
355920ae8c Update bug-report.yml 2022-03-14 17:52:16 -04:00
lucian929
cd2a8e54e1 Update bug-report.yml 2022-03-14 17:19:03 -04:00
lucian929
a05fde5038 Merge pull request #17 from HibiscusMC/issue-template
Issue template
2022-03-14 17:15:50 -04:00
lucian929
14b0cc6275 Fix YAML syntax error 2022-03-14 17:14:44 -04:00
lucian929
f9ffd91116 New issue template 2022-03-14 17:13:03 -04:00
lucian929
7b063815fc Remove feature template
We handle feature requests on our support discord.
2022-03-14 16:53:38 -04:00
Fisher2911
6653ac6edc Merge remote-tracking branch 'origin/master'
# Conflicts:
#	common/src/main/java/io/github/fisher2911/hmccosmetics/hook/CitizensHook.java
2022-03-12 15:23:54 -05:00
Fisher2911
2beadca574 Removed imports 2022-03-12 15:23:33 -05:00
Fisher2911
844e7c852f Added option to set multiple cosmetics 2022-03-12 13:28:08 -05:00
Fisher2911
6c2363a9fb Allowed sub folders for menus folder 2022-03-12 13:20:10 -05:00
Fisher2911
13212fe26e Fixed ModelEngine bug again 2022-03-12 13:16:09 -05:00
MasterOfTheFish
766eed0387 Fixed Citizens Error 2022-03-11 08:02:36 -05:00
lucian929
a06a5004e1 Bump version number 2022-03-10 21:39:21 -05:00
lucian929
8eec822a8c Merge pull request #16 from Acterax/master
Fix too much packets
2022-03-10 10:09:12 -05:00
Tom
56ca9b2a39 Fix too much packets 2022-03-10 16:02:02 +01:00
lucian929
88b24aefbc Bump version number 2022-03-07 20:10:41 -05:00
Fisher2911
e0044c6d15 Fixed balloons 2022-03-07 17:25:03 -05:00
Fisher2911
6c2049a8d8 Fixed ModelEngine error 2022-03-07 15:49:59 -05:00
lucian929
2ffb791ce1 Bump version number 2022-03-07 10:58:04 -05:00
lucian929
6ced156e23 Merge pull request #14 from KaspianDev/patch-1 2022-03-07 10:57:38 -05:00
Kacper Smoliński
8045a63964 Fix errors 2022-03-07 16:53:50 +01:00
Fisher
49681c7c1d Stopped loading of token if no cosmetic is found 2022-03-07 10:01:36 -05:00
Fisher
1e69dcea89 Fixed always having world name be 'world' 2022-03-07 09:51:07 -05:00
Fisher
2b832c33a4 Added removal of armor stand when not wearing backpack 2022-03-07 08:49:24 -05:00
Fisher2911
8cda481a55 Fixed reload issue with tokens 2022-03-07 00:01:47 -05:00
Fisher
6294a26b1d Delete nms/build directory 2022-03-06 18:34:43 -05:00
Fisher
29b26c29ca Delete common/build directory 2022-03-06 18:34:33 -05:00
Fisher
01230dda3f Delete 1.16/build directory 2022-03-06 18:34:11 -05:00
Fisher
181bd722ac Delete 1.18/build directory 2022-03-06 18:34:01 -05:00
Fisher
4deb586813 Delete 1.17/build directory 2022-03-06 18:33:51 -05:00
Fisher
d478736b5b Delete .idea directory 2022-03-06 18:33:26 -05:00
Fisher2911
d961bd2966 Merge branch 'updates'
# Conflicts:
#	.gitignore
#	1.16/build/classes/java/main/io/github/fisher2911/nms/ArmorStandPackets_1_16_R3.class
#	1.16/build/classes/java/main/io/github/fisher2911/nms/DestroyPacket_1_16_R3.class
#	1.16/build/libs/1.16.jar
#	1.16/build/tmp/compileJava/previous-compilation-data.bin
#	1.17/build/libs/1.17.jar
#	1.17/build/tmp/compileJava/previous-compilation-data.bin
#	1.18/build/libs/1.18.jar
#	1.18/build/tmp/compileJava/previous-compilation-data.bin
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/HMCCosmetics.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/api/CosmeticItem.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/api/HMCCosmeticsAPI.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/api/event/CosmeticChangeEvent.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/api/event/CosmeticItemEvent.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/concurrent/Threads.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/config/ActionSerializer.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/config/CosmeticSettings$1.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/config/CosmeticSettings.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/config/DyeGuiSerializer.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/config/GuiSerializer.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/config/ItemSerializer.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/config/Settings.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/config/SoundData.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/config/WardrobeSettings.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/cosmetic/CosmeticManager.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/database/Database.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/database/DatabaseConverter.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/database/DatabaseFactory.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/database/DatabaseType.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/database/dao/ArmorItemDAO.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/database/dao/UserDAO.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/gui/ArmorItem$1.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/gui/ArmorItem$Type.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/gui/ArmorItem.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/gui/ColorItem.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/gui/CosmeticGui.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/gui/CosmeticsMenu.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/gui/DyeSelectorGui.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/hook/Hook.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/hook/HookManager.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/hook/PAPIHook.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/hook/item/ItemHook.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/hook/item/ItemHooks.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/hook/item/ItemsAdderHook.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/hook/item/OraxenHook.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/inventory/PlayerArmor.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/listener/ClickListener.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/listener/CosmeticFixListener.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/listener/JoinListener.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/listener/MoveListener.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/listener/PlayerShiftListener.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/listener/RespawnListener.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/listener/TeleportListener.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/listener/WardrobeClickListener.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/Adventure.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/ErrorMessages.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/Message$Type.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/Message.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/MessageHandler$1.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/MessageHandler.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/Messages$1.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/Messages.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/Permission.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/Placeholder.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/TitleMessage.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/message/Translation.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/packet/PacketManager.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/task/DataTask.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/task/ImmediateTask.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/task/InfiniteTask.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/task/SupplierTask.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/task/SyncedTask.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/task/Task.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/task/TaskChain.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/task/TaskManager.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/user/Equipment.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/user/User.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/user/UserManager$1.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/user/UserManager.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/user/Wardrobe.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/util/Keys.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/util/StringUtils.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/util/Utils.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/util/builder/ColorBuilder.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/util/builder/ItemBuilder.class
#	common/build/classes/java/main/io/github/fisher2911/hmccosmetics/util/builder/SkullBuilder.class
#	common/build/generated/plugin-yml/Bukkit/plugin.yml
#	common/build/resources/main/config.yml
#	common/build/resources/main/menus/main.yml
#	common/build/resources/main/messages.yml
#	common/build/resources/main/plugin.yml
#	common/build/tmp/compileJava/previous-compilation-data.bin
#	nms/build/libs/nms.jar
#	nms/build/tmp/compileJava/previous-compilation-data.bin
2022-03-06 18:32:10 -05:00
lucian929
58ddceb5f1 Fix typo 2022-03-06 17:59:26 -05:00
lucian929
4be4c5fe2a Update help command to add new commands 2022-03-06 17:58:47 -05:00
lucian929
23c1774f37 Bump version number 2022-03-06 17:56:19 -05:00
lucian929
7c911d1247 Updates messages.yml 2022-03-06 17:40:01 -05:00
lucian929
89a32dcd30 Modified some default messages 2022-03-06 17:27:26 -05:00
Fisher2911
badc2f7b87 Fixed invalid token config 2022-03-06 17:16:30 -05:00
Fisher2911
16d516ef18 Removed sout 2022-03-06 17:03:26 -05:00
Fisher2911
1fcbe27d6a Fixed placeholders 2022-03-06 17:02:48 -05:00
Fisher2911
8da9100dd3 Fixed typo 2022-03-06 16:41:22 -05:00
Fisher2911
1888145ee0 Fixed ProtocolLib enum null error on first call 2022-03-06 16:37:48 -05:00
Fisher2911
84864303fc Finished tokens 2022-03-06 16:07:21 -05:00
Fisher2911
960bb97a04 Added tokens 2022-03-06 15:08:30 -05:00
Fisher2911
a55ad14934 Added 2022-03-06 13:45:53 -05:00
Fisher2911
8b345bc56c Fixed balloon movement 2022-03-05 17:45:26 -05:00
lucian929
4e21945bbb Small changes 2022-02-26 12:34:57 -05:00
MasterOfTheFish
b3aa0b942f Fixed teleporting error with player leaving wardrobe 2022-02-26 00:50:15 -05:00
MasterOfTheFish
607d2ea7bd Fixed issue with dye items not running actions 2022-02-26 00:49:10 -05:00
MasterOfTheFish
23bcd56eac BALLOONS?? 2022-02-26 00:23:33 -05:00
MasterOfTheFish
ba7327dd54 Merge remote-tracking branch 'origin/updates' into updates 2022-02-23 19:39:01 -05:00
MasterOfTheFish
35c6b01f34 Start balloon stuff 2022-02-23 19:38:49 -05:00
lucian929
ee86569f22 Bump Version Number
i forgot to last time
2022-02-23 09:41:04 -05:00
MasterOfTheFish
59dbee34ae Fixed placeholders not appearing on items in GUI menu 2022-02-23 08:53:25 -05:00
MasterOfTheFish
d12a5d090f Fixed concurrent error with citizens hook 2022-02-22 17:20:39 -05:00
MasterOfTheFish
5ba03402a0 Fixed double wardrobe message 2022-02-20 23:15:53 -05:00
MasterOfTheFish
b7c80437e2 Fixed double wardrobe message 2022-02-20 23:15:02 -05:00
MasterOfTheFish
e4cba947d3 Fixed citizens entity null error 2022-02-20 22:25:03 -05:00
MasterOfTheFish
e026739b34 Merge remote-tracking branch 'origin/updates' into updates
# Conflicts:
#	common/build.gradle.kts
2022-02-20 12:16:09 -05:00
MasterOfTheFish
440a106534 Bump version number 2022-02-20 12:15:41 -05:00
MasterOfTheFish
068a147e1e Fixed citizens empty cosmetic overriding armor 2022-02-20 12:12:00 -05:00
MasterOfTheFish
f3b780e730 Fixed concurrent error 2022-02-20 12:05:30 -05:00
MasterOfTheFish
8fa606954e Fixed wardrobe leave / join error 2022-02-20 11:51:07 -05:00
lucian929
9d3ca106c9 Bump version number 2022-02-19 22:31:45 -05:00
MasterOfTheFish
98a6528e50 Fixed formatted placeholder 2022-02-19 22:17:17 -05:00
MasterOfTheFish
a3bce9b766 Stopped sending of blank messages 2022-02-19 21:15:50 -05:00
MasterOfTheFish
d10afc3df3 Fixed placeholder cosmetic items 2022-02-19 21:13:50 -05:00
MasterOfTheFish
be7092b422 Fixed remove items not working 2022-02-19 20:10:38 -05:00
MasterOfTheFish
6ccc40798a Fixed item hooks not working 2022-02-19 19:48:27 -05:00
MasterOfTheFish
8503f3cb39 Allow item hook items to override name and lore 2022-02-19 19:42:45 -05:00
MasterOfTheFish
ffd15345d2 Added citizens support 2022-02-19 19:37:38 -05:00
MasterOfTheFish
a42730dc19 change up how user class works 2022-02-19 02:16:02 -05:00
MasterOfTheFish
363c57141c Added remove cosmetic config option 2022-02-18 20:26:12 -05:00
MasterOfTheFish
cc67eff1f7 Added wardrobe spawn delay 2022-02-18 20:16:20 -05:00
MasterOfTheFish
9b7b5ce1ad Removed glowing of selected item 2022-02-18 20:10:04 -05:00
MasterOfTheFish
ed41b71ff3 Allowed setting of other items in cosmetic slots 2022-02-18 20:06:20 -05:00
Fisher2911
54fe2719d1 Excluded snakeyaml dependency 2022-02-17 21:33:34 -05:00
Fisher2911
a7892ce434 Improved GUI 2022-02-17 19:47:03 -05:00
Fisher2911
39583b3685 Fixed wardrobe always active always stuck bug 2022-02-17 17:10:27 -05:00
Fisher2911
eec995a7f3 More placeholders 2022-02-17 17:05:41 -05:00
Fisher2911
c75182d118 Bump version 2022-02-17 00:36:13 -05:00
Fisher2911
268ccff0db Removed debug messages 2022-02-17 00:33:45 -05:00
Fisher2911
deb7806e78 Added skin overlay on wardrobe 2022-02-17 00:02:15 -05:00
Fisher2911
832980f593 Added skin overlay on wardrobe 2022-02-16 23:51:01 -05:00
lucian929
c8ee8c0c7c Remove some files 2022-02-15 12:40:52 -05:00
lucian929
ce3989edca Fix .gitignore (i think) 2022-02-15 12:30:03 -05:00
lucian929
09e252bd48 Update .gitignore 2022-02-15 12:28:13 -05:00
Fisher2911
f58d328bae update 2022-02-14 22:00:42 -05:00
161 changed files with 8435 additions and 2138 deletions

View File

@@ -1,20 +0,0 @@
---
name: Bug Report
about: Create a bug report to help us keep track of all bugs that have to be fixed
title: "[BUG] Bug name"
labels: bug
---
**I have checked...**
- [ ] ...if there are any similar bug reports
- [ ] ...if a bug fix is already planned
**Complete description**
Write your bug description as good as you can.
**Possible solution**
If you have any possible solutions, write them here, if not, leave it blank or put "N/A".
**Error/Server log**
If you have any errors put them in here (from paste.gg or sentry)

62
.github/ISSUE_TEMPLATE/bug-report.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: Bug Report
description: Create a bug report to help us keep track of all bugs that have to be fixed
title: "[BUG] <name for bug>"
labels: [bug]
body:
- type: checkboxes
id: i-have-checked
attributes:
label: I have checked...
options:
- label: "I am using the latest version of HMCCosmetics"
required: true
- label: "I am using the latest version of any dependencies"
required: true
- label: "I have checked if any similar bug reports exist"
required: true
- type: textarea
id: description
attributes:
label: Description
description: A full description of the bug
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: Steps to reproduce
description: Explain how to reproduce this issue step-by-step, in as much detail as possible.
validations:
required: true
- type: textarea
id: hmcc-version
attributes:
label: Plugin Version
description: Run `version HMCCosmetics` in your console and paste the output
validations:
required: true
- type: textarea
id: meg-version
attributes:
label: ModelEngine Version
description: "Run `version ModelEngine` in your console and paste the output. Optional if not using balloons."
validations:
required: false
- type: textarea
id: server-version
attributes:
label: Server Version
description: "Run `version` in your console and paste the output."
validations:
required: true
- type: "dropdown"
id: "type"
attributes:
label: "How breaking is the bug?"
options:
- "Breaking Bug - Plugin unusable"
- "Non-breaking Bug - Plugin still usable, but certain features unavailable"
- "Minor Bug - Plugin completely functional, but features have non-working aspects"
validations:
required: true

View File

@@ -0,0 +1,29 @@
name: Feature Request
description: Create a feature request to help us keep track of all features you want to be added
title: "[FEATURE] <title>"
labels: [feature]
body:
- type: "checkboxes"
id: "i-have-checked"
attributes:
label: "I have checked that..."
options:
- label: "...such a feature does not exist already"
required: true
- label: "...such a feature request has not been submitted already"
required: true
- type: "textarea"
id: "description"
attributes:
label: "Description"
description: "A full description of the feature"
validations:
required: true
- type: "textarea"
id: "config-changes"
attributes:
label: "Config Changes"
description: "The configuration changes your feature should have"
validations:
required: false

View File

@@ -1,19 +0,0 @@
---
name: Feature To-Do
about: Create an issue with this template to keep track of the current development projects.
title: "[FEATURE] Feature name"
labels: enhancement
---
**I have checked...**
- [ ] ...if there are any similar features in other branches
- [ ] ...if there are any similar issues
- [ ] ...if such a feature is already planned
**Complete description**
Write your feature description as good as you can.
**Reason for feature request**
Write your reason for the feature request as good as you can.

9
.gitignore vendored
View File

@@ -1,4 +1,11 @@
# Project exclude paths
/.gradle/
/gradle/
/.idea/
/build/
/build/classes/java/main/
/build/classes/java/main/
/common/build/
/1.16/build/
/1.17/build/
/1.18/build/
/nms/build/

8
.idea/.gitignore generated vendored
View File

@@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@@ -1,36 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="FORMATTER_TAGS_ENABLED" value="true" />
<JavaCodeStyleSettings>
<option name="GENERATE_FINAL_LOCALS" value="true" />
<option name="GENERATE_FINAL_PARAMETERS" value="true" />
<option name="REPLACE_NULL_CHECK" value="false" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999999999" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999999" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="JAVA">
<arrangement>
<groups>
<group>
<type>GETTERS_AND_SETTERS</type>
<order>KEEP</order>
</group>
<group>
<type>OVERRIDDEN_METHODS</type>
<order>KEEP</order>
</group>
<group>
<type>DEPENDENT_METHODS</type>
<order>BREADTH_FIRST</order>
</group>
</groups>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@@ -1,6 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
<option name="PREFERRED_PROJECT_CODE_STYLE" value="GoogleStyle" />
</state>
</component>

8
.idea/compiler.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="16">
<module name="common" target="1.8" />
</bytecodeTargetLevel>
</component>
</project>

7
.idea/discord.xml generated
View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="ASK" />
<option name="description" value="" />
</component>
</project>

7
.idea/encodings.xml generated
View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/src/main/resources" charset="UTF-8" />
</component>
</project>

24
.idea/gradle.xml generated
View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="delegatedBuild" value="true" />
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="openjdk-16" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/1.17" />
<option value="$PROJECT_DIR$/1.18" />
<option value="$PROJECT_DIR$/common" />
<option value="$PROJECT_DIR$/nms" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="HotSwapAgentPluginSettingsProvider">
<option name="agentPath" value="C:\Users\barry\AppData\Roaming\JetBrains\IdeaIC2021.2\plugins\hotswap-agent-intellij-plugin\lib\agent\hotswap-agent-1.4.1.jar" />
</component>
</project>

View File

@@ -1,110 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://repo.mattstudios.me/artifactory/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="maven7" />
<option name="name" value="maven7" />
<option name="url" value="https://oss.sonatype.org/content/repositories/snapshots/" />
</remote-repository>
<remote-repository>
<option name="id" value="paperweightDecompilerRepository" />
<option name="name" value="paperweightDecompilerRepository" />
<option name="url" value="https://files.minecraftforge.net/maven/" />
</remote-repository>
<remote-repository>
<option name="id" value="sonatype" />
<option name="name" value="sonatype" />
<option name="url" value="https://oss.sonatype.org/content/groups/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="paperweightParamMappingsRepository" />
<option name="name" value="paperweightParamMappingsRepository" />
<option name="url" value="https://maven.fabricmc.net/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="maven6" />
<option name="name" value="maven6" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
<remote-repository>
<option name="id" value="maven7" />
<option name="name" value="maven7" />
<option name="url" value="https://repo.jeff-media.de/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven8" />
<option name="name" value="maven8" />
<option name="url" value="https://maven.pkg.github.com/LoneDev6/API-ItemsAdder" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://papermc.io/repo/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven5" />
<option name="name" value="maven5" />
<option name="url" value="https://repo.leonardobishop.com/releases/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven6" />
<option name="name" value="maven6" />
<option name="url" value="https://mvnrepository.com/artifact/com.zaxxer/HikariCP" />
</remote-repository>
<remote-repository>
<option name="id" value="maven8" />
<option name="name" value="maven8" />
<option name="url" value="https://oss.sonatype.org/content/repositories/snapshots" />
</remote-repository>
<remote-repository>
<option name="id" value="maven4" />
<option name="name" value="maven4" />
<option name="url" value="https://repo.extendedclip.com/content/repositories/placeholderapi/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenLocal" />
<option name="name" value="MavenLocal" />
<option name="url" value="file:/$MAVEN_REPOSITORY$/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven11" />
<option name="name" value="maven11" />
<option name="url" value="https://libraries.minecraft.net/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven7" />
<option name="name" value="maven7" />
<option name="url" value="https://repo.dmulloy2.net/repository/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="spigotmc-repo" />
<option name="name" value="spigotmc-repo" />
<option name="url" value="https://hub.spigotmc.org/nexus/content/repositories/snapshots/" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinScriptingSettings">
<option name="suppressDefinitionsCheck" value="true" />
</component>
</project>

15
.idea/misc.xml generated
View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<list size="1">
<item index="0" class="java.lang.String" itemvalue="org.bukkit.event.EventHandler" />
</list>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" project-jdk-name="temurin-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>SPIGOT</platformType>
<platformType>MCP</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
<component name="McpModuleSettings">
<option name="srgType" value="SRG" />
</component>
</module>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>ADVENTURE</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
</module>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>SPIGOT</platformType>
<platformType>MCP</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
<component name="McpModuleSettings">
<option name="srgType" value="SRG" />
</component>
</module>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>ADVENTURE</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
</module>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>ADVENTURE</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
<component name="McpModuleSettings">
<option name="srgType" value="SRG" />
</component>
</module>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>SPIGOT</platformType>
<platformType>MCP</platformType>
<platformType>ADVENTURE</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
<component name="McpModuleSettings">
<option name="srgType" value="SRG" />
</component>
</module>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>ADVENTURE</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
</module>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>SPIGOT</platformType>
<platformType>MCP</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
<component name="McpModuleSettings">
<option name="srgType" value="SRG" />
</component>
</module>

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
</set>
</option>
</component>
</project>

124
.idea/uiDesigner.xml generated
View File

@@ -1,124 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -1,23 +0,0 @@
plugins {
id("java")
}
//group = "io.github.fisher2911"
//version = "1.7.1"
//description = "Intuitive, easy-to-use cosmetics plugin, designed for servers using resource packs.\n"
repositories {
mavenCentral()
maven("https://papermc.io/repo/repository/maven-public/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://jitpack.io")
maven("https://repo.dmulloy2.net/repository/public/")
}
dependencies {
implementation(project(":nms"))
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot:1.17-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:22.0.0")
compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
}

View File

@@ -1,17 +0,0 @@
package io.github.fisher2911.nms;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.IntArrayList;
public class DestroyPacket_1_17_R1 implements DestroyPacket {
@Override
public PacketContainer get(final int entityId) {
final PacketContainer destroyPacket = new PacketContainer(
PacketType.Play.Server.ENTITY_DESTROY);
destroyPacket.getModifier().write(0, new IntArrayList(new int[]{entityId}));
return destroyPacket;
}
}

View File

@@ -1,96 +0,0 @@
package io.github.fisher2911.nms;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.PlayerInfoData;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class PlayerPackets_1_17_R1 implements PlayerPackets {
@Override
public PacketContainer getSpawnPacket(final Location location, UUID uuid, final int entityId) {
final PacketContainer spawnPacket = new PacketContainer(PacketType.Play.Server.NAMED_ENTITY_SPAWN);
spawnPacket.getUUIDs().write(0, uuid);
spawnPacket.getIntegers().write(0, entityId);
spawnPacket.getDoubles().
write(0, location.getX()).
write(1, location.getY()).
write(2, location.getZ());
spawnPacket.getBytes().write(0, (byte)(((location.getYaw() * 256.0F) / 360.0F)));
return spawnPacket;
}
@Override
public PacketContainer getPlayerInfoPacket(final Player player, final UUID uuid) {
final GameProfile profile = this.getCopyProfile(player, uuid);
final PacketContainer playerInfoPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
final StructureModifier<EnumWrappers.PlayerInfoAction> action = playerInfoPacket.getPlayerInfoAction();
final StructureModifier<List<PlayerInfoData>> infoData = playerInfoPacket.getPlayerInfoDataLists();
final List<PlayerInfoData> playerInfoData = new ArrayList<>();
playerInfoData.add(new PlayerInfoData(WrappedGameProfile
.fromHandle(profile),
0,
EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
WrappedChatComponent.fromText(profile.getName())));
action.write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
infoData.write(0, playerInfoData);
return playerInfoPacket;
}
@Override
public PacketContainer getRemovePacket(final Player player, final UUID uuid, final int entityId) {
final PacketContainer playerPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
final StructureModifier<EnumWrappers.PlayerInfoAction> action = playerPacket.getPlayerInfoAction();
final StructureModifier<List<PlayerInfoData>> infoData = playerPacket.getPlayerInfoDataLists();
final List<PlayerInfoData> playerInfoData = new ArrayList<>();
final GameProfile profile = this.getCopyProfile(player, uuid);
playerInfoData.add(new PlayerInfoData(WrappedGameProfile
.fromHandle(profile),
0,
EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
WrappedChatComponent.fromText("")));
action.write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
infoData.write(0, playerInfoData);
return playerPacket;
}
private GameProfile getCopyProfile(final Player player, final UUID uuid) {
final GameProfile playerProfile = ((CraftPlayer) player).getProfile();
final GameProfile profile = new GameProfile(
uuid,
player.getDisplayName()
);
profile.getProperties().removeAll("textures");
Property textureProperty = playerProfile.getProperties().get("textures").iterator().next();
String texture = textureProperty.getValue();
String signature = textureProperty.getSignature();
profile.getProperties().put("textures", new Property("textures", texture, signature));
return profile;
}
}

View File

@@ -1,23 +0,0 @@
plugins {
id("java")
}
//group = "io.github.fisher2911"
//version = "1.7.1"
//description = "Intuitive, easy-to-use cosmetics plugin, designed for servers using resource packs.\n"
repositories {
mavenCentral()
maven("https://papermc.io/repo/repository/maven-public/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://jitpack.io")
maven("https://repo.dmulloy2.net/repository/public/")
}
dependencies {
implementation(project(":nms"))
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot:1.18-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:22.0.0")
compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
}

View File

@@ -1,17 +0,0 @@
package io.github.fisher2911.nms;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import it.unimi.dsi.fastutil.ints.IntArrayList;
public class DestroyPacket_1_18_R1 implements DestroyPacket {
@Override
public PacketContainer get(final int entityId) {
final PacketContainer destroyPacket = new PacketContainer(
PacketType.Play.Server.ENTITY_DESTROY);
destroyPacket.getModifier().write(0, new IntArrayList(new int[]{entityId}));
return destroyPacket;
}
}

View File

@@ -1,97 +0,0 @@
package io.github.fisher2911.nms;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.PlayerInfoData;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class PlayerPackets_1_18_R1 implements PlayerPackets {
@Override
public PacketContainer getSpawnPacket(final Location location, UUID uuid, final int entityId) {
final PacketContainer spawnPacket = new PacketContainer(PacketType.Play.Server.NAMED_ENTITY_SPAWN);
spawnPacket.getUUIDs().write(0, uuid);
spawnPacket.getIntegers().write(0, entityId);
spawnPacket.getDoubles().
write(0, location.getX()).
write(1, location.getY()).
write(2, location.getZ());
spawnPacket.getBytes().write(0, (byte)(((location.getYaw() * 256.0F) / 360.0F)));
return spawnPacket;
}
@Override
public PacketContainer getPlayerInfoPacket(final Player player, final UUID uuid) {
final GameProfile profile = this.getCopyProfile(player, uuid);
final PacketContainer playerInfoPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
final StructureModifier<EnumWrappers.PlayerInfoAction> action = playerInfoPacket.getPlayerInfoAction();
final StructureModifier<List<PlayerInfoData>> infoData = playerInfoPacket.getPlayerInfoDataLists();
final List<PlayerInfoData> playerInfoData = new ArrayList<>();
playerInfoData.add(new PlayerInfoData(WrappedGameProfile
.fromHandle(profile),
0,
EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
WrappedChatComponent.fromText(profile.getName())));
action.write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
infoData.write(0, playerInfoData);
return playerInfoPacket;
}
@Override
public PacketContainer getRemovePacket(final Player player, final UUID uuid, final int entityId) {
final PacketContainer playerPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
final StructureModifier<EnumWrappers.PlayerInfoAction> action = playerPacket.getPlayerInfoAction();
final StructureModifier<List<PlayerInfoData>> infoData = playerPacket.getPlayerInfoDataLists();
final List<PlayerInfoData> playerInfoData = new ArrayList<>();
final GameProfile profile = this.getCopyProfile(player, uuid);
playerInfoData.add(new PlayerInfoData(WrappedGameProfile
.fromHandle(profile),
0,
EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
WrappedChatComponent.fromText("")));
action.write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
infoData.write(0, playerInfoData);
return playerPacket;
}
private GameProfile getCopyProfile(final Player player, final UUID uuid) {
final GameProfile playerProfile = ((CraftPlayer) player).getProfile();
final GameProfile profile = new GameProfile(
uuid,
player.getDisplayName()
);
profile.getProperties().removeAll("textures");
Property textureProperty = playerProfile.getProperties().get("textures").iterator().next();
String texture = textureProperty.getValue();
String signature = textureProperty.getSignature();
profile.getProperties().put("textures", new Property("textures", texture, signature));
return profile;
}
}

View File

@@ -14,7 +14,7 @@ HMCCosmetics is an intuitive, easy-to-use cosmetics plugin, designed for servers
### Requirements
- ProtocolLib
- [packetevents 2.0](https://github.com/retrooper/packetevents)
### Download

View File

@@ -1,112 +1,3 @@
//import net.minecrell.pluginyml.bukkit.BukkitPluginDescription
//
plugins {
id("java")
}
// id("com.github.johnrengelman.shadow") version "7.1.1"
// id("net.minecrell.plugin-yml.bukkit") version "0.5.1"
//}
//
//group = "io.github.fisher2911"
//version = "1.7.1"
//description = "Intuitive, easy-to-use cosmetics plugin, designed for servers using resource packs.\n"
//
//repositories {
// mavenCentral()
// maven("https://papermc.io/repo/repository/maven-public/")
// maven("https://repo.mattstudios.me/artifactory/public/")
// maven("https://jitpack.io")
// maven("https://repo.dmulloy2.net/repository/public/")
// maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
// maven("https://mvnrepository.com/artifact/com.zaxxer/HikariCP")
// maven("https://repo.jeff-media.de/maven2/")
// maven("https://oss.sonatype.org/content/repositories/snapshots")
//}
//
//dependencies {
// compileOnly("com.mojang:authlib:1.5.25")
// compileOnly("org.spigotmc:spigot:1.17-R0.1-SNAPSHOT")
// compileOnly("org.jetbrains:annotations:22.0.0")
// compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
// compileOnly("me.clip:placeholderapi:2.11.1")
// compileOnly("com.github.oraxen:oraxen:-SNAPSHOT")
// compileOnly("com.github.LoneDev6:API-ItemsAdder:2.5.4")
// implementation("net.kyori:adventure-api:4.9.3")
// implementation("net.kyori:adventure-text-minimessage:4.10.0-SNAPSHOT")
// implementation("net.kyori:adventure-platform-bukkit:4.0.1")
// implementation("dev.triumphteam:triumph-gui:3.1.1")
// implementation("me.mattstudios.utils:matt-framework:1.4.6")
// implementation("org.spongepowered:configurate-yaml:4.1.2")
// implementation("org.bstats:bstats-bukkit:2.2.1")
// implementation("com.zaxxer:HikariCP:5.0.0")
// implementation("com.j256.ormlite:ormlite-jdbc:6.1")
// implementation("com.j256.ormlite:ormlite-core:6.1")
//}
//
//tasks {
// build {
// dependsOn(shadowJar)
// }
//
// compileJava {
// options.encoding = Charsets.UTF_8.name()
// options.release.set(16)
// }
//
// shadowJar {
// relocate("dev.triumphteam.gui", "io.github.fisher2911.hmccosmetics.gui")
// relocate("me.mattstudios.mf", "io.github.fisher2911.hmccosmetics.mf")
// relocate("net.kyori.adventure.text.minimessage", "io.github.fisher2911.hmccosmetics.adventure.minimessage")
// relocate("net.kyori.adventure.platform", "io.github.fisher2911.hmccosmetics.adventure.platform")
// relocate("org.spongepowered.configurate", "io.github.fisher2911.hmccosmetics.configurate")
// relocate("org.bstats", "io.github.fisher2911.hmccosmetics.bstats")
// relocate("com.zaxxer.hikaricp", "io.github.fisher2911.hmccosmetics.hikaricp")
// relocate("com.j256.ormlite", "io.github.fisher2911.hmccosmetics.ormlite")
// archiveFileName.set("HMCCosmetics.jar")
// }
//
// javadoc {
// options.encoding = Charsets.UTF_8.name()
// }
//
// processResources {
// filteringCharset = Charsets.UTF_8.name()
// }
//}
//
//java {
// toolchain.languageVersion.set(JavaLanguageVersion.of(16))
//}
//
//bukkit {
// load = BukkitPluginDescription.PluginLoadOrder.STARTUP
// main = "io.github.fisher2911.hmccosmetics.HMCCosmetics"
// apiVersion = "1.17"
// name = "HMCCosmetics"
// authors = listOf("MasterOfTheFish")
// softDepend = listOf("Multiverse", "PlaceholderAPI", "Oraxen", "ItemsAdder")
// depend = listOf("ProtocolLib")
// permissions {
// register("hmccosmetics.cmd.default") {
// default = BukkitPluginDescription.Permission.Default.OP
// description = "Permission to execute the default command."
// }
// register("hmccosmetics.cmd.dye") {
// default = BukkitPluginDescription.Permission.Default.OP
// description = "Permission to dye armor."
// }
// register("hmccosmetics.cmd.reload") {
// default = BukkitPluginDescription.Permission.Default.OP
// description = "Permission to use the reload command."
// }
// register("hmccosmetics.cmd.set") {
// default = BukkitPluginDescription.Permission.Default.OP
// description = "Permission to set other users' cosmetics."
// }
// register("hmccosmetics.cmd.wardrobe") {
// default = BukkitPluginDescription.Permission.Default.OP
// description = "Permission to view the wardrobe"
// }
// }
//}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

View File

@@ -0,0 +1,2 @@
#Wed Feb 02 16:44:24 EST 2022
gradle.version=7.3.3

Binary file not shown.

Binary file not shown.

View File

View File

@@ -7,7 +7,7 @@ plugins {
}
group = "io.github.fisher2911"
version = "1.7.1"
version = "1.12.0-BETA-5"
description = "Intuitive, easy-to-use cosmetics plugin, designed for servers using resource packs.\n"
repositories {
@@ -20,27 +20,40 @@ repositories {
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
maven("https://mvnrepository.com/artifact/com.zaxxer/HikariCP")
maven("https://repo.jeff-media.de/maven2/")
maven("https://repo.citizensnpcs.co")
//maven("https://mvn.lumine.io/repository/maven-public")
maven {
url = uri("https://mvn.lumine.io/repository/maven-public")
metadataSources {
artifact()
}
}
maven("https://jitpack.io/")
}
dependencies {
implementation(project(":1.17"))
implementation(project(":1.18"))
implementation(project(":nms"))
// implementation(project(":1.16"))
// implementation(project(":1.17"))
// implementation(project(":1.18"))
// implementation(project(":nms"))
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot:1.17-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:22.0.0")
compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
compileOnly("org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:23.0.0")
compileOnly("com.comphenix.protocol:ProtocolLib:5.0.0-SNAPSHOT")
compileOnly("me.clip:placeholderapi:2.11.1")
compileOnly("com.github.oraxen:oraxen:-SNAPSHOT")
compileOnly("com.github.LoneDev6:API-ItemsAdder:2.5.4")
implementation("net.kyori:adventure-api:4.9.3")
implementation("net.kyori:adventure-text-minimessage:4.10.0-SNAPSHOT")
implementation("net.kyori:adventure-platform-bukkit:4.0.1")
implementation("dev.triumphteam:triumph-gui:3.1.1")
compileOnly("net.citizensnpcs:citizens-main:2.0.30-SNAPSHOT")
compileOnly("com.ticxo.modelengine:api:R3.0.0")
//compileOnly("com.github.retrooper.packetevents:spigot:2.0-SNAPSHOT")
implementation("net.kyori:adventure-api:4.11.0")
implementation ("net.kyori:adventure-text-minimessage:4.11.0")
implementation("net.kyori:adventure-platform-bukkit:4.1.2")
implementation("dev.triumphteam:triumph-gui:3.1.3")
implementation("me.mattstudios.utils:matt-framework:1.4.6")
implementation("org.spongepowered:configurate-yaml:4.1.2")
implementation("org.bstats:bstats-bukkit:2.2.1")
implementation("com.zaxxer:HikariCP:5.0.0")
implementation("org.bstats:bstats-bukkit:3.0.0")
implementation("com.zaxxer:HikariCP:5.0.1")
implementation("com.j256.ormlite:ormlite-jdbc:6.1")
implementation("com.j256.ormlite:ormlite-core:6.1")
}
@@ -58,13 +71,21 @@ tasks {
shadowJar {
relocate("dev.triumphteam.gui", "io.github.fisher2911.hmccosmetics.gui")
relocate("me.mattstudios.mf", "io.github.fisher2911.hmccosmetics.mf")
relocate("net.kyori.adventure.text.minimessage", "io.github.fisher2911.hmccosmetics.adventure.minimessage")
relocate("net.kyori.adventure.platform", "io.github.fisher2911.hmccosmetics.adventure.platform")
relocate("net.kyori.adventure", "io.github.fisher2911.hmccosmetics.adventure")
relocate("org.spongepowered.configurate", "io.github.fisher2911.hmccosmetics.configurate")
relocate("org.bstats", "io.github.fisher2911.hmccosmetics.bstats")
relocate("com.zaxxer.hikaricp", "io.github.fisher2911.hmccosmetics.hikaricp")
relocate("com.j256.ormlite", "io.github.fisher2911.hmccosmetics.ormlite")
//relocate("com.github.retrooper.packetevents", "io.github.fisher2911.hmccosmetics.packetevents")
//relocate("io.github.retrooper.packetevents", "io.github.fisher2911.hmccosmetics.packetevents")
archiveFileName.set("HMCCosmetics.jar")
dependencies {
exclude(dependency("org.yaml:snakeyaml"))
}
// todo - remove (Testing only)
//destinationDirectory.set(file("D:\\paper-1.18.1\\plugins"))
}
javadoc {
@@ -75,19 +96,21 @@ tasks {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
filteringCharset = Charsets.UTF_8.name()
}
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(16))
toolchain.languageVersion.set(JavaLanguageVersion.of(16
))
}
bukkit {
load = BukkitPluginDescription.PluginLoadOrder.STARTUP
main = "io.github.fisher2911.hmccosmetics.HMCCosmetics"
apiVersion = "1.17"
apiVersion = "1.16"
name = "HMCCosmetics"
authors = listOf("MasterOfTheFish")
softDepend = listOf("Multiverse", "PlaceholderAPI", "Oraxen", "ItemsAdder")
softDepend = listOf("Multiverse", "PlaceholderAPI", "Oraxen", "ItemsAdder", "Citizens", "ModelEngine")
depend = listOf("ProtocolLib")
permissions {
register("hmccosmetics.cmd.default") {
@@ -118,5 +141,28 @@ bukkit {
default = BukkitPluginDescription.Permission.Default.OP
description = "Permission to open another player's wardrobe"
}
register("hmccosmetics.cmd.token.give") {
default = BukkitPluginDescription.Permission.Default.OP
description = "Permission to give other players tokens"
}
}
}
}
val copyJar: String? by project
val pluginPath = project.findProperty("hibiscusmc_plugin_path")
if(copyJar != "false" && pluginPath != null) {
tasks {
register<Copy>("copyJar") {
from(findByName("reobfJar") ?: findByName("shadowJar") ?: findByName("jar"))
into(pluginPath)
doLast {
println("Copied to plugin directory $pluginPath")
}
}
named<DefaultTask>("build") {
dependsOn("copyJar")
}
}
}

BIN
common/gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -5,11 +5,14 @@ import com.comphenix.protocol.ProtocolManager;
import io.github.fisher2911.hmccosmetics.command.CosmeticsCommand;
import io.github.fisher2911.hmccosmetics.concurrent.Threads;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.config.TokenLoader;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.database.Database;
import io.github.fisher2911.hmccosmetics.database.DatabaseFactory;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.gui.Token;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.item.ItemsAdderHook;
import io.github.fisher2911.hmccosmetics.listener.ClickListener;
@@ -18,51 +21,66 @@ import io.github.fisher2911.hmccosmetics.listener.JoinListener;
import io.github.fisher2911.hmccosmetics.listener.PlayerShiftListener;
import io.github.fisher2911.hmccosmetics.listener.RespawnListener;
import io.github.fisher2911.hmccosmetics.listener.TeleportListener;
import io.github.fisher2911.hmccosmetics.listener.WardrobeListener;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Translation;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import io.github.fisher2911.hmccosmetics.task.TaskManager;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import me.mattstudios.mf.base.CommandManager;
import me.mattstudios.mf.base.CompletionHandler;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
public class HMCCosmetics extends JavaPlugin {
public static final Path PLUGIN_FOLDER = Paths.get("plugins", "HMCCosmetics");
private ProtocolManager protocolManager;
private TaskManager taskManager;
private Settings settings;
private UserManager userManager;
private CosmeticManager cosmeticManager;
private MessageHandler messageHandler;
private CosmeticsMenu cosmeticsMenu;
private TokenLoader tokenLoader;
private CommandManager commandManager;
private Database database;
private BukkitTask saveTask;
private ProtocolManager manager;
/* // commented because PacketEvents is no longer shaded
@Override
public void onLoad() {
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
PacketEvents.getAPI().load();
}
*/
@Override
public void onEnable() {
final int pluginId = 13873;
final Metrics metrics = new Metrics(this, pluginId);
protocolManager = ProtocolLibrary.getProtocolManager();
this.taskManager = new TaskManager(this);
this.taskManager.start();
this.settings = new Settings(this);
this.messageHandler = new MessageHandler(this);
this.userManager = new UserManager(this);
this.cosmeticManager = new CosmeticManager(new HashMap<>());
this.cosmeticManager = new CosmeticManager(new HashMap<>(), new HashMap<>(), new HashMap<>());
this.cosmeticsMenu = new CosmeticsMenu(this);
this.tokenLoader = new TokenLoader(this);
this.manager = ProtocolLibrary.getProtocolManager();
this.userManager.startTeleportTask();
@@ -72,6 +90,7 @@ public class HMCCosmetics extends JavaPlugin {
exception.printStackTrace();
}
PacketManager.setupPackets();
this.registerCommands();
this.registerListeners();
@@ -93,13 +112,14 @@ public class HMCCosmetics extends JavaPlugin {
@Override
public void onDisable() {
//PacketEvents.getAPI().terminate();
this.saveTask.cancel();
this.database.saveAll();
this.messageHandler.close();
this.userManager.cancelTeleportTask();
this.userManager.removeAll();
Threads.getInstance().onDisable();
this.database.close();
this.taskManager.end();
}
private void registerListeners() {
@@ -109,7 +129,8 @@ public class HMCCosmetics extends JavaPlugin {
new TeleportListener(this),
new RespawnListener(this),
new CosmeticFixListener(this),
new PlayerShiftListener(this)
new PlayerShiftListener(this),
new WardrobeListener(this)
).
forEach(
listener -> this.getServer().getPluginManager()
@@ -119,24 +140,59 @@ public class HMCCosmetics extends JavaPlugin {
private void registerCommands() {
this.commandManager = new CommandManager(this, true);
this.commandManager.getMessageHandler().register(
"cmd.no.console", player ->
final HookManager hookManager = HookManager.getInstance();
final me.mattstudios.mf.base.MessageHandler messageHandler = this.commandManager.getMessageHandler();
messageHandler.register("cmd.no.console", player ->
this.messageHandler.sendMessage(
player,
Messages.MUST_BE_PLAYER
)
);
this.commandManager.getCompletionHandler().register("#types",
messageHandler.register("cmd.no.permission", player ->
this.messageHandler.sendMessage(
player,
Messages.NO_PERMISSION
)
);
messageHandler.register("cmd.no.exists", player ->
this.messageHandler.sendMessage(
player,
Messages.HELP_COMMAND
));
messageHandler.register("cmd.wrong.usage", player ->
this.messageHandler.sendMessage(
player,
Messages.HELP_COMMAND
));
final CompletionHandler completionHandler = this.commandManager.getCompletionHandler();
completionHandler.register("#types",
resolver ->
Arrays.stream(ArmorItem.Type.
values()).
map(ArmorItem.Type::toString).
collect(Collectors.toList())
);
this.commandManager.getCompletionHandler().register("#ids",
completionHandler.register("#ids",
resolver ->
this.cosmeticManager.getAll().stream().map(ArmorItem::getId)
this.cosmeticManager.getAllArmorItems().stream().map(ArmorItem::getId)
.collect(Collectors.toList()));
completionHandler.register("#tokens",
resolver ->
this.cosmeticManager.getAllTokens().stream().map(Token::getId)
.collect(Collectors.toList()));
completionHandler.register("#menus",
resolver -> new ArrayList<>(this.cosmeticsMenu.getMenus())
);
completionHandler.register("#npc-args",
resolver -> List.of(CosmeticsCommand.NPC_REMOVE, CosmeticsCommand.NPC_APPLY));
completionHandler.register("#npcs", resolver -> {
final List<String> ids = new ArrayList<>();
if (!hookManager.isEnabled(CitizensHook.class)) return ids;
for (final int id : hookManager.getCitizensHook().getAllNPCS()) {
ids.add(String.valueOf(id));
}
return ids;
});
this.commandManager.register(new CosmeticsCommand(this));
}
@@ -146,6 +202,7 @@ public class HMCCosmetics extends JavaPlugin {
this.settings.load();
this.messageHandler.load();
this.cosmeticsMenu.load();
this.tokenLoader.load();
Translation.getInstance().load();
this.database.load();
}, 1);
@@ -157,10 +214,15 @@ public class HMCCosmetics extends JavaPlugin {
this.settings.load();
this.messageHandler.load();
this.cosmeticsMenu.reload();
this.tokenLoader.load();
Translation.getInstance().load();
});
}
public TaskManager getTaskManager() {
return taskManager;
}
public Settings getSettings() {
return settings;
}
@@ -181,13 +243,12 @@ public class HMCCosmetics extends JavaPlugin {
return cosmeticsMenu;
}
public ProtocolManager getProtocolManager() {
return protocolManager;
}
public Database getDatabase() {
return database;
}
public ProtocolManager getProtocolManager() {
return manager;
}
}

View File

@@ -1,7 +1,6 @@
package io.github.fisher2911.hmccosmetics.api;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import java.util.ArrayList;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
@@ -25,9 +24,17 @@ public class CosmeticItem {
* @param rgb from Bukkit's {@link Color#asRGB()}
*/
public CosmeticItem(final ItemStack itemStack, final String id, final ArmorItem.Type type,
final boolean dyeable, final int rgb) {
this.armorItem = new ArmorItem(itemStack, id, new ArrayList<>(), "", type, dyeable, rgb);
public CosmeticItem(
final ItemStack itemStack,
final String name,
final String id,
final ItemStack locked,
final ItemStack applied,
final String permission,
final ArmorItem.Type type,
final boolean dyeable,
final int rgb) {
this.armorItem = new ArmorItem(itemStack, name, id, locked, applied, permission, type, dyeable, rgb);
}
/**
@@ -38,9 +45,18 @@ public class CosmeticItem {
* @param rgb from Bukkit's {@link Color#asRGB()}
*/
public CosmeticItem(final Material material, final String id, final ArmorItem.Type type,
final boolean dyeable, final int rgb) {
this.armorItem = new ArmorItem(material, id, new ArrayList<>(), "", type, dyeable, rgb);
public CosmeticItem(
final Material material,
final String name,
final String id,
final Material locked,
final Material applied,
final String permission,
final ArmorItem.Type type,
final boolean dyeable,
final int rgb
) {
this.armorItem = new ArmorItem(material, name, id, new ItemStack(locked), new ItemStack(applied), permission, type, dyeable, rgb);
}
/**
@@ -49,8 +65,8 @@ public class CosmeticItem {
* @param type the cosmetic item type
*/
public CosmeticItem(final ItemStack itemStack, final String id, final ArmorItem.Type type) {
this(itemStack, id, type, false, -1);
public CosmeticItem(final ItemStack itemStack, final String name, final String id, final ItemStack locked, final ItemStack applied, final ArmorItem.Type type) {
this(itemStack, name, id, locked, applied, "", type, false, -1);
}
/**
@@ -59,12 +75,12 @@ public class CosmeticItem {
* @param type the cosmetic item type
*/
public CosmeticItem(final Material material, final String id, final ArmorItem.Type type) {
this(material, id, type, false, -1);
public CosmeticItem(final Material material, final Material locked, final Material applied, final String name, final String id, final ArmorItem.Type type) {
this(material, name, id, locked, applied, "", type, false, -1);
}
public ItemStack getColored() {
return this.armorItem.getColored();
public ItemStack getItemStack(final ArmorItem.Status status) {
return this.armorItem.getItemStack(status);
}
public ItemStack getItemStack() {

View File

@@ -4,9 +4,10 @@ import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.UUID;
import org.jetbrains.annotations.Nullable;
public class HMCCosmeticsAPI {
@@ -17,8 +18,8 @@ public class HMCCosmeticsAPI {
}
/**
* This will attempt to get the {@link io.github.fisher2911.hmccosmetics.api.CosmeticItem} that
* the user is wearing. It returns an empty {@link io.github.fisher2911.hmccosmetics.api.CosmeticItem}
* This will attempt to get the {@link CosmeticItem} that
* the user is wearing. It returns an empty {@link CosmeticItem}
* if the user is not found, or if the user is not wearing a cosmetic
*
* @param uuid the uuid of the user
@@ -45,7 +46,7 @@ public class HMCCosmeticsAPI {
return false;
}
userManager.setItem(userOptional.get(), cosmeticItem.getArmorItem());
userManager.setItem(userOptional.get(), cosmeticItem.getArmorItem(), true);
return true;
}
@@ -60,7 +61,7 @@ public class HMCCosmeticsAPI {
if (armorItem == null) {
return null;
}
return new CosmeticItem(new ArmorItem(armorItem));
return new CosmeticItem(armorItem.copy());
}
/**

View File

@@ -1,24 +1,33 @@
package io.github.fisher2911.hmccosmetics.api.event;
import io.github.fisher2911.hmccosmetics.api.CosmeticItem;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.BaseUser;
/**
* Called when a user changes their equipped cosmetic
*/
public class CosmeticChangeEvent extends CosmeticItemEvent {
private final User user;
private final BaseUser<?> user;
private CosmeticItem removed;
public CosmeticChangeEvent(final CosmeticItem cosmeticItem, final CosmeticItem removed,
final User user) {
public CosmeticChangeEvent(
final CosmeticItem cosmeticItem,
final CosmeticItem removed,
final BaseUser<?> user) {
super(cosmeticItem);
this.removed = removed;
this.user = user;
}
public User getUser() {
public CosmeticChangeEvent(final boolean isAsync, final CosmeticItem cosmeticItem, final CosmeticItem removed, final BaseUser<?> user) {
super(isAsync, cosmeticItem);
this.removed = removed;
this.user = user;
}
public BaseUser<?> getUser() {
return user;
}

View File

@@ -17,6 +17,11 @@ public abstract class CosmeticItemEvent extends Event implements Cancellable {
this.cancelled = false;
}
public CosmeticItemEvent(final boolean isAsync, final CosmeticItem cosmeticItem) {
super(isAsync);
this.cosmeticItem = cosmeticItem;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}

View File

@@ -1,22 +1,24 @@
package io.github.fisher2911.hmccosmetics.command;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.config.WardrobeSettings;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.gui.Token;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.message.Message;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.task.TaskChain;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import io.github.fisher2911.hmccosmetics.util.StringUtils;
import java.util.Map;
import java.util.Optional;
import me.mattstudios.mf.annotations.Command;
import me.mattstudios.mf.annotations.Completion;
import me.mattstudios.mf.annotations.Default;
@@ -24,11 +26,14 @@ import me.mattstudios.mf.annotations.Permission;
import me.mattstudios.mf.annotations.SubCommand;
import me.mattstudios.mf.base.CommandBase;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
@Command("cosmetics")
public class CosmeticsCommand extends CommandBase {
@@ -36,22 +41,35 @@ public class CosmeticsCommand extends CommandBase {
private final UserManager userManager;
private final MessageHandler messageHandler;
private final CosmeticsMenu cosmeticsMenu;
private final CosmeticManager cosmeticManager;
private final Settings settings;
private final CosmeticSettings cosmeticSettings;
public CosmeticsCommand(final HMCCosmetics plugin) {
this.plugin = plugin;
this.userManager = this.plugin.getUserManager();
this.messageHandler = this.plugin.getMessageHandler();
this.cosmeticsMenu = this.plugin.getCosmeticsMenu();
this.cosmeticManager = this.plugin.getCosmeticManager();
this.settings = this.plugin.getSettings();
this.cosmeticSettings = this.settings.getCosmeticSettings();
}
@Default
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DEFAULT_COMMAND)
public void defaultCommand(final Player player) {
this.defaultCommand(player, this.cosmeticSettings.getDefaultMenu());
}
@SubCommand("menu")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DEFAULT_COMMAND)
public void defaultCommand(
final Player player,
@Completion("#menus") @me.mattstudios.mf.annotations.Optional String menu) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
if (menu == null) menu = this.cosmeticSettings.getDefaultMenu();
if (optionalUser.isEmpty()) {
this.cosmeticsMenu.openDefault(player);
this.cosmeticsMenu.openMenu(menu, player);
return;
}
final User user = optionalUser.get();
@@ -59,13 +77,13 @@ public class CosmeticsCommand extends CommandBase {
if (wardrobe.isActive() &&
!this.settings.getWardrobeSettings().inDistanceOfWardrobe(wardrobe.getCurrentLocation(), player.getLocation())) {
wardrobe.setActive(false);
wardrobe.despawnFakePlayer(player);
wardrobe.despawnFakePlayer(player, userManager);
this.messageHandler.sendMessage(
player,
Messages.CLOSED_WARDROBE
);
}
this.cosmeticsMenu.openDefault(player);
this.cosmeticsMenu.openMenu(menu, player);
}
@SubCommand("reload")
@@ -85,8 +103,11 @@ public class CosmeticsCommand extends CommandBase {
@SubCommand("dye")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DYE_COMMAND)
public void dyeArmor(final Player player, @Completion("#types") String typeString,
final @me.mattstudios.mf.annotations.Optional String dyeColor) {
public void dyeArmor(
final Player player,
@Completion("#types") String typeString,
final @me.mattstudios.mf.annotations.Optional String dyeColor
) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
@@ -106,11 +127,9 @@ public class CosmeticsCommand extends CommandBase {
final ArmorItem armorItem = user.getPlayerArmor().getItem(type);
if (dyeColor != null) {
this.setDyeColor(dyeColor, armorItem, player);
}
this.setDyeColor(dyeColor, armorItem, player);
this.userManager.setItem(user, armorItem);
this.userManager.setItem(user, armorItem, true);
this.messageHandler.sendMessage(
player,
@@ -140,7 +159,8 @@ public class CosmeticsCommand extends CommandBase {
final CommandSender sender,
@Completion("#players") final Player player,
@Completion("#ids") final String id,
final @me.mattstudios.mf.annotations.Optional String dyeColor) {
final @me.mattstudios.mf.annotations.Optional String dyeColor
) {
final Optional<User> userOptional = this.userManager.get(player.getUniqueId());
if (userOptional.isEmpty()) {
@@ -168,7 +188,7 @@ public class CosmeticsCommand extends CommandBase {
final Message setMessage = Messages.getSetMessage(armorItem.getType());
final Message setOtherMessage = Messages.getSetOtherMessage(armorItem.getType());
this.userManager.setItem(user, armorItem);
this.userManager.setItem(user, armorItem, true);
this.messageHandler.sendMessage(
player,
setMessage
@@ -183,8 +203,11 @@ public class CosmeticsCommand extends CommandBase {
@SubCommand("remove")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.SET_COSMETIC_COMMAND)
public void removeCommand(final CommandSender sender,
@Completion("#players") final Player player, @Completion("#types") String typeString) {
public void removeCommand(
final CommandSender sender,
@Completion("#players") final Player player,
@Completion("#types") String typeString
) {
final Optional<User> userOptional = this.userManager.get(player.getUniqueId());
if (userOptional.isEmpty()) {
@@ -201,7 +224,7 @@ public class CosmeticsCommand extends CommandBase {
final ArmorItem.Type type = ArmorItem.Type.valueOf(typeString.toUpperCase());
final Message setOtherMessage = Messages.getSetOtherMessage(type);
this.userManager.removeItem(user, type);
this.userManager.removeItem(user, type, true);
this.messageHandler.sendMessage(
sender,
setOtherMessage,
@@ -215,22 +238,35 @@ public class CosmeticsCommand extends CommandBase {
@SubCommand("wardrobe")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.WARDROBE)
public void openWardrobe(Player player, @me.mattstudios.mf.annotations.Optional final Player other) {
public void openWardrobe(
CommandSender sender,
@me.mattstudios.mf.annotations.Optional final Player other
) {
Player player = null;
if (other != null) {
if (!player.hasPermission(io.github.fisher2911.hmccosmetics.message.Permission.OPEN_OTHER_WARDROBE)) {
if (!sender.hasPermission(io.github.fisher2911.hmccosmetics.message.Permission.OPEN_OTHER_WARDROBE)) {
this.messageHandler.sendMessage(
player,
sender,
Messages.NO_PERMISSION
);
return;
}
this.messageHandler.sendMessage(
player,
sender,
Messages.OPENED_OTHER_WARDROBE,
Map.of(Placeholder.PLAYER, other.getName())
);
player = other;
} else if (!(sender instanceof final Player p)) {
this.messageHandler.sendMessage(
sender,
Messages.MUST_BE_PLAYER
);
return;
} else {
player = p;
}
final Optional<User> optionalUser = this.plugin.getUserManager().get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
@@ -268,18 +304,152 @@ public class CosmeticsCommand extends CommandBase {
wardrobe.setCurrentLocation(null);
}
wardrobe.setActive(true);
settings.playOpenSound(player);
final Player finalPlayer = player;
Bukkit.getScheduler().runTaskAsynchronously(
this.plugin,
() -> wardrobe.spawnFakePlayer(finalPlayer)
);
new TaskChain(this.plugin).
chain(() -> wardrobe.spawnFakePlayer(finalPlayer), true).
chain(() -> {
// this.cosmeticsMenu.openDefault(finalPlayer);
this.messageHandler.sendMessage(
finalPlayer,
Messages.OPENED_WARDROBE
);
}).execute();
}
this.cosmeticsMenu.openDefault(player);
public static final String NPC_APPLY = "apply";
public static final String NPC_REMOVE = "remove";
@SubCommand("npc")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.SET_COSMETIC_COMMAND)
public void applyNpc(
final CommandSender sender,
@Completion("#npc-args") final String arg,
@Completion("#npcs") final Integer npcId,
@Completion("#types") final String typeStr,
@me.mattstudios.mf.annotations.Optional @Completion("#ids") final String itemId
) {
final CitizensHook citizensHook = HookManager.getInstance().getCitizensHook();
if (citizensHook == null) {
this.messageHandler.sendMessage(
sender,
Messages.HOOK_NOT_ENABLED,
Map.of(Placeholder.TYPE, "Citizens")
);
return;
}
if (npcId == null) {
this.messageHandler.sendMessage(
sender,
new Message("illegal-npc-id", "<red>" + "Invalid NPC id specified: " + npcId)
);
return;
}
final ArmorItem armorItem = this.plugin.getCosmeticManager().getArmorItem(itemId);
if (armorItem == null) {
this.messageHandler.sendMessage(
sender,
Messages.ITEM_NOT_FOUND
);
return;
}
switch (arg.toLowerCase(Locale.ROOT)) {
case NPC_APPLY -> {
this.setNpcCosmetic(citizensHook, sender, npcId, armorItem);
}
case NPC_REMOVE -> {
try {
final ArmorItem.Type type = ArmorItem.Type.valueOf(typeStr);
this.setNpcCosmetic(citizensHook, sender, npcId, ArmorItem.empty(type, "none"));
} catch (final IllegalArgumentException exception) {
this.messageHandler.sendMessage(
sender,
Messages.INVALID_TYPE,
Map.of(Placeholder.TYPE, typeStr)
);
}
}
}
}
@SubCommand("hide")
public void hide(final Player player) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
if (user.isHidden()) {
user.setHidden(false);
this.messageHandler.sendMessage(
player,
Messages.SHOWN_COSMETICS
);
return;
}
user.setHidden(true);
this.messageHandler.sendMessage(
player,
Messages.OPENED_WARDROBE
Messages.HID_COSMETICS
);
}
@SubCommand("token")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.GIVE_TOKEN)
public void token(
final CommandSender sender,
@Completion("#tokens") final String tokenId,
@Completion("#players") @me.mattstudios.mf.annotations.Optional Player giveTo) {
if (!(sender instanceof Player) && giveTo == null) {
this.messageHandler.sendMessage(
sender,
Messages.MUST_BE_PLAYER
);
return;
}
if (giveTo == null) {
giveTo = ((Player) sender);
}
final Token token = this.cosmeticManager.getToken(tokenId);
if (token == null) {
this.messageHandler.sendMessage(
sender,
Messages.ITEM_NOT_FOUND
);
return;
}
giveTo.getInventory().addItem(token.getItemStack().clone());
final String tokenName = token.getArmorItem().getName();
this.messageHandler.sendMessage(
sender,
Messages.GAVE_TOKEN,
Map.of(Placeholder.ID, tokenName,
Placeholder.PLAYER, giveTo.getDisplayName())
);
this.messageHandler.sendMessage(
giveTo,
Messages.RECEIVED_TOKEN,
Map.of(Placeholder.ID, tokenName)
);
}
private void setNpcCosmetic(final CitizensHook hook, final CommandSender sender, final int npcId, final ArmorItem item) {
final boolean isSet = hook.setNpcCosmetic(npcId, item);
if (!isSet) {
this.messageHandler.sendMessage(
sender,
Messages.NPC_NOT_FOUND,
Map.of(Placeholder.ID, String.valueOf(npcId))
);
return;
}
this.messageHandler.sendMessage(
sender,
Messages.SET_NPC_COSMETIC,
Map.of(Placeholder.TYPE, item.getType().toString(),
Placeholder.ITEM, item.getId(),
Placeholder.ID, String.valueOf(npcId))
);
}

View File

@@ -1,14 +1,21 @@
package io.github.fisher2911.hmccosmetics.config;
import com.comphenix.protocol.wrappers.EnumWrappers;
import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.message.Message;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import io.github.fisher2911.hmccosmetics.util.Utils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
@@ -16,22 +23,30 @@ import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class ActionSerializer implements TypeSerializer<GuiAction<InventoryClickEvent>> {
public class ActionSerializer implements TypeSerializer<List<CosmeticGuiAction>> {
public static final ActionSerializer INSTANCE = new ActionSerializer();
private static final HMCCosmetics plugin;
private static final String OPEN_MENU = "open-menu";
private static final String CLOSE_MENU = "close-menu";
private static final String SET_ITEMS = "set-items";
private static final String REMOVE_COSMETICS = "remove-cosmetics";
private static final String SET_COSMETICS = "set-cosmetics";
private static final String SEND_MESSAGE = "send-message";
private static final String SEND_MESSAGES = "send-messages";
private static final String SEND_COMMAND = "send-command";
private static final String SEND_COMMANDS = "send-commands";
private static final String SOUND = "sound";
private static final String SOUND_NAME = "name";
private static final String SOUND_VOLUME = "volume";
private static final String SOUND_PITCH = "pitch";
private static final String SOUND_CATEGORY = "category";
static {
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
@@ -51,71 +66,227 @@ public class ActionSerializer implements TypeSerializer<GuiAction<InventoryClick
}
@Override
public GuiAction<InventoryClickEvent> deserialize(final Type type, final ConfigurationNode source) {
public List<CosmeticGuiAction> deserialize(final Type type, final ConfigurationNode source) {
return this.deserialize(type, new ArrayList<>(), source, CosmeticGuiAction.When.ALL);
}
private List<CosmeticGuiAction> deserialize(
final Type type,
final List<CosmeticGuiAction> consumers,
final ConfigurationNode source,
final CosmeticGuiAction.When when) {
final var children = source.childrenMap();
final List<Consumer<InventoryClickEvent>> consumers = new ArrayList<>();
for (final var entry : children.entrySet()) {
final String clickType = entry.getKey().toString();
if (clickType == null) continue;
consumers.add(this.parseAction(entry.getValue(), clickType.toUpperCase(Locale.ROOT)));
try {
final CosmeticGuiAction.When nextWhen = CosmeticGuiAction.When.valueOf(clickType.toUpperCase());
this.deserialize(type, consumers, entry.getValue(), nextWhen);
} catch (final IllegalArgumentException exception) {
consumers.add(this.parseAction(entry.getValue(), clickType.toUpperCase(Locale.ROOT), when));
}
}
return event -> {
for (final Consumer<InventoryClickEvent> consumer : consumers) {
consumer.accept(event);
return consumers;
}
private CosmeticGuiAction parseAction(
final ConfigurationNode node,
final String clickType,
final CosmeticGuiAction.When when
) {
final ConfigurationNode openMenuNode = node.node(OPEN_MENU);
final ConfigurationNode setItemsNode = node.node(SET_ITEMS);
final ConfigurationNode removeItemsNode = node.node(REMOVE_COSMETICS);
final ConfigurationNode setCosmeticsNode = node.node(SET_COSMETICS);
final ConfigurationNode soundNode = node.node(SOUND);
final boolean closeMenu = node.node(CLOSE_MENU).getBoolean(false);
final String openMenu = openMenuNode.getString();
final List<ArmorItem.Type> removeCosmeticTypes = this.loadRemoveTypes(removeItemsNode);
final int totalRemoveCosmetics = removeCosmeticTypes.size();
final List<String> setCosmetics = this.loadSetCosmetics(setCosmeticsNode);
final int totalSetCosmetics = setCosmetics.size();
final ClickType click = Utils.stringToEnum(clickType, ClickType.class, ClickType.UNKNOWN);
final Map<Integer, GuiItem> setItems = this.loadSetItems(setItemsNode);
final Consumer<Player> messageConsumer = this.loadMessages(node, plugin);
final SoundData soundData = this.loadSoundData(soundNode);
return new CosmeticGuiAction(
when,
event -> {
if (click != ClickType.UNKNOWN && event.getClick() != click) return;
if (!(event.getWhoClicked() instanceof final Player player)) return;
if (soundData != null) {
soundData.play(player);
}
if (openMenu != null) plugin.getCosmeticsMenu().openMenu(openMenu, event.getWhoClicked());
messageConsumer.accept(player);
final UserManager userManager = plugin.getUserManager();
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
final CosmeticManager cosmeticManager = plugin.getCosmeticManager();
int index = 0;
for (final String id : setCosmetics) {
index++;
final boolean sendPacket = index == totalSetCosmetics ;
final ArmorItem armorItem = cosmeticManager.getArmorItem(id);
if (armorItem == null) continue;
userManager.setItem(user, armorItem, sendPacket);
}
index = 0;
for (final ArmorItem.Type type : removeCosmeticTypes) {
index++;
final boolean sendPacket = index == totalSetCosmetics ;
userManager.removeItem(user, type, sendPacket);
}
final CosmeticGui gui = user.getOpenGui();
if (gui != null) {
for (final var entry : setItems.entrySet()) {
final GuiItem item = entry.getValue();
gui.updateItem(entry.getKey(), item, user, player);
}
}
if (closeMenu) player.closeInventory();
}
);
}
private Map<Integer, GuiItem> loadSetItems(final ConfigurationNode node) {
if (node.virtual()) return Collections.emptyMap();
final Map<Integer, GuiItem> setItems = new HashMap<>();
try {
for (final var entry : node.childrenMap().entrySet()) {
if (!(entry.getKey() instanceof final Integer slot)) continue;
final var key = entry.getValue();
final GuiItem guiItem = ArmorItemSerializer.INSTANCE.deserialize(GuiItem.class, key);
if (guiItem == null) continue;
setItems.put(slot, guiItem);
}
} catch (final SerializationException exception) {
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().severe(
"Error loading set-items"
);
return Collections.emptyMap();
}
return setItems;
}
private static final String CONSOLE = "console";
private static final String PLAYER = "player";
private Consumer<Player> loadMessages(final ConfigurationNode source, final HMCCosmetics plugin) {
final ConfigurationNode messageNode = source.node(SEND_MESSAGE);
final ConfigurationNode messagesNode = source.node(SEND_MESSAGES);
final ConfigurationNode commandNode = source.node(SEND_COMMAND);
final ConfigurationNode commandsNode = source.node(SEND_COMMANDS);
final List<String> messages = new ArrayList<>();
final List<String> commands = new ArrayList<>();
final String message = messageNode.getString();
if (message != null) messages.add(message);
final String command = commandNode.getString();
if (command != null) commands.add(command);
for (final var node : messagesNode.childrenList()) {
final String listMessage = node.getString();
if (listMessage == null) continue;
messages.add(listMessage);
}
for (final var node : commandsNode.childrenList()) {
final String commandMessage = node.getString();
if (commandMessage == null) continue;
commands.add(commandMessage);
}
return player -> {
final String playerName = player.getName();
final Map<String, String> placeholders = Map.of(Placeholder.PLAYER, playerName);
final MessageHandler messageHandler = plugin.getMessageHandler();
for (final String sendMessage : messages) {
messageHandler.sendMessage(
player,
new Message("", sendMessage),
placeholders
);
}
for (final String sendCommand : commands) {
final String[] parts = sendCommand.split(":");
if (parts.length < 2) {
Bukkit.dispatchCommand(
Bukkit.getConsoleSender(),
sendCommand.replace(Placeholder.PLAYER, playerName)
);
continue;
}
final String sender = parts[0];
final String commandToSend = parts[1];
if (sender.equalsIgnoreCase(CONSOLE)) {
Bukkit.dispatchCommand(
Bukkit.getConsoleSender(),
commandToSend.replace(Placeholder.PLAYER, playerName)
);
continue;
}
player.chat("/" + commandToSend.replace(Placeholder.PLAYER, playerName));
}
};
}
private Consumer<InventoryClickEvent> parseAction(final ConfigurationNode node, final String clickType) {
final ConfigurationNode openMenuNode = node.node(OPEN_MENU);
final ConfigurationNode sendMessageNode = node.node(SEND_MESSAGE);
final ConfigurationNode soundNode = node.node(SOUND);
final ConfigurationNode soundNameNode = soundNode.node(SOUND_NAME);
final ConfigurationNode volumeNode = soundNode.node(SOUND_VOLUME);
final ConfigurationNode pitchNode = soundNode.node(SOUND_PITCH);
final ConfigurationNode categoryNode = soundNode.node(SOUND_CATEGORY);
final String openMenu = openMenuNode.getString();
final String sendMessage = sendMessageNode.getString();
final SoundData soundData;
final String soundName = soundNameNode.getString();
final String category = categoryNode.getString();
final int volume = volumeNode.getInt();
final int pitch = pitchNode.getInt();
if (soundName == null || category == null) {
soundData = null;
} else {
soundData = new SoundData(
soundName,
EnumWrappers.SoundCategory.valueOf(category),
volume,
pitch
);
private List<ArmorItem.Type> loadRemoveTypes(final ConfigurationNode node) {
try {
final List<String> typeStrings = node.getList(String.class);
if (typeStrings == null) return new ArrayList<>();
return typeStrings.stream().map(
string -> {
try {
return ArmorItem.Type.valueOf(string.toUpperCase(Locale.ROOT));
} catch (final IllegalArgumentException exception) {
plugin.getLogger().severe(string + " is not a valid cosmetic type.");
}
return null;
}
).
filter(type -> type != null).
collect(Collectors.toList());
} catch (final SerializationException exception) {
exception.printStackTrace();
}
return new ArrayList<>();
}
final ClickType click = Utils.stringToEnum(clickType, ClickType.class, ClickType.UNKNOWN);
private SoundData loadSoundData(final ConfigurationNode node) {
try {
return SoundSerializer.INSTANCE.deserialize(SoundData.class, node);
} catch (final ConfigurateException exception) {
return null;
}
}
return event -> {
if (click != ClickType.UNKNOWN && event.getClick() != click) return;
if (!(event.getWhoClicked() instanceof final Player player)) return;
if (soundData != null) {
soundData.play(player);
}
if (sendMessage != null) plugin.getMessageHandler().sendMessage(
player,
new Message("", sendMessage)
);
if (openMenu != null) plugin.getCosmeticsMenu().openMenu(openMenu, event.getWhoClicked());
};
private List<String> loadSetCosmetics(final ConfigurationNode node) {
try {
return node.getList(String.class);
} catch (final ConfigurateException exception) {
return new ArrayList<>();
}
}
@Override
public void serialize(final Type type, @Nullable final GuiAction<InventoryClickEvent> obj, final ConfigurationNode node) throws SerializationException {
public void serialize(final Type type, @Nullable final List<CosmeticGuiAction> obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -0,0 +1,150 @@
package io.github.fisher2911.hmccosmetics.config;
import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.BalloonItem;
import io.github.fisher2911.hmccosmetics.gui.WrappedGuiItem;
import io.github.fisher2911.hmccosmetics.util.StringUtils;
import io.github.fisher2911.hmccosmetics.util.Utils;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
public class ArmorItemSerializer implements TypeSerializer<WrappedGuiItem> {
public static final ArmorItemSerializer INSTANCE = new ArmorItemSerializer();
private ArmorItemSerializer() {
}
private static final String NAME = "name";
private static final String LOCKED_LORE = "locked-lore";
private static final String APPLIED_LORE = "applied-lore";
private static final String LOCKED_ITEM = "locked-item";
private static final String APPLIED_ITEM = "applied-item";
private static final String PERMISSION = "permission";
private static final String TYPE = "type";
private static final String ACTION = "action";
private static final String ID = "id";
private static final String DYEABLE = "dyeable";
private static final String BALLOON_MODEL_ID = "balloon";
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path)
throws SerializationException {
if (!source.hasChild(path)) {
throw new SerializationException(
"Required field " + Arrays.toString(path) + " was not present in node");
}
return source.node(path);
}
@Override
public WrappedGuiItem deserialize(final Type type, final ConfigurationNode source)
throws SerializationException {
final ConfigurationNode nameNode = source.node(NAME);
final ConfigurationNode lockedLoreNode = source.node(LOCKED_LORE);
final ConfigurationNode appliedLoreNode = source.node(APPLIED_LORE);
final ConfigurationNode lockedItemNode = source.node(LOCKED_ITEM);
final ConfigurationNode appliedItemNode = source.node(APPLIED_ITEM);
final ConfigurationNode permissionNode = source.node(PERMISSION);
final ConfigurationNode typeNode = source.node(TYPE);
final ConfigurationNode actionNode = source.node(ACTION);
final ConfigurationNode idNode = source.node(ID);
final ConfigurationNode dyeableNode = source.node(DYEABLE);
final ConfigurationNode balloonModelIdNode = source.node(BALLOON_MODEL_ID);
final ItemStack itemStack = Utils.replaceIfNull(
ItemSerializer.INSTANCE.deserialize(ItemStack.class, source),
new ItemStack(Material.AIR)
);
ItemStack lockedItem = ItemSerializer.INSTANCE.deserialize(ItemStack.class, lockedItemNode);
if (lockedItem == null) {
final List<String> lockedLore = Utils.replaceIfNull(lockedLoreNode.getList(String.class),
new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
lockedItem = ItemBuilder.from(itemStack.clone()).lore(lockedLore).build();
}
ItemStack appliedItem = ItemSerializer.INSTANCE.deserialize(ItemStack.class, appliedItemNode);
if (appliedItem == null) {
final List<String> appliedLore = Utils.replaceIfNull(appliedLoreNode.getList(String.class),
new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
appliedItem = ItemBuilder.from(itemStack.clone()).lore(appliedLore).build();
}
final boolean dyeable = dyeableNode.getBoolean();
final List<CosmeticGuiAction> actions = ActionSerializer.INSTANCE.deserialize(GuiAction.class, actionNode);
try {
final ArmorItem.Type cosmeticType = ArmorItem.Type.valueOf(
Utils.replaceIfNull(
typeNode.getString(), ""
).toUpperCase(Locale.ROOT)
);
final String permission = permissionNode.getString();
if (cosmeticType == ArmorItem.Type.BALLOON) {
return new BalloonItem(
itemStack,
actions,
Utils.replaceIfNull(nameNode.getString(), ""),
Utils.replaceIfNull(idNode.getString(), ""),
lockedItem,
appliedItem,
permission,
cosmeticType,
dyeable,
-1,
balloonModelIdNode.getString()
);
}
return new ArmorItem(
itemStack,
actions,
Utils.replaceIfNull(nameNode.getString(), ""),
Utils.replaceIfNull(idNode.getString(), ""),
lockedItem,
appliedItem,
permission,
cosmeticType,
dyeable,
-1
);
} catch (final IllegalArgumentException exception) {
final GuiItem guiItem = dev.triumphteam.gui.builder.item.ItemBuilder.from(itemStack).asGuiItem();
final GuiAction<InventoryClickEvent> guiAction = event -> {
for (final CosmeticGuiAction action : actions) {
action.execute(event, CosmeticGuiAction.When.ALL);
}
};
guiItem.setAction(guiAction);
return new WrappedGuiItem(guiItem, guiAction);
}
}
@Override
public void serialize(final Type type, @Nullable final WrappedGuiItem obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -0,0 +1,28 @@
package io.github.fisher2911.hmccosmetics.config;
import org.bukkit.event.inventory.InventoryClickEvent;
import java.util.function.Consumer;
public class CosmeticGuiAction {
private final When when;
private final Consumer<InventoryClickEvent> consumer;
public CosmeticGuiAction(final When when, final Consumer<InventoryClickEvent> consumer) {
this.when = when;
this.consumer = consumer;
}
public void execute(final InventoryClickEvent event, final When when) {
if (this.when != When.ALL && this.when != when) return;
consumer.accept(event);
}
public enum When {
EQUIP,
REMOVE,
ALL
}
}

View File

@@ -1,52 +1,147 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.util.Utils;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.util.Vector;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import java.util.Objects;
@ConfigSerializable
public class CosmeticSettings {
private static final transient String COSMETIC_SETTINGS_PATH = "cosmetic-settings";
private static final transient String REQUIRE_EMPTY_HELMET_PATH = "require-empty-helmet";
private static final transient String REQUIRE_EMPTY_OFF_HAND_PATH = "require-empty-off-hand";
private static final transient String LOOK_DOWN_PITCH_PATH = "look-down-backpack-remove";
private static final String DEFAULT_MENU = "default-menu";
private static final String COSMETIC_SETTINGS_PATH = "cosmetic-settings";
private static final String REQUIRE_EMPTY_HELMET_PATH = "require-empty-helmet";
private static final String REQUIRE_EMPTY_OFF_HAND_PATH = "require-empty-off-hand";
private static final String REQUIRE_EMPTY_CHEST_PLATE_PATH = "require-empty-chest-plate";
private static final String REQUIRE_EMPTY_PANTS_PATH = "require-empty-pants";
private static final String REQUIRE_EMPTY_BOOTS_PATH = "require-empty-boots";
private static final String BALLOON_OFFSET = "balloon-offset";
private static final String FIRST_PERSON_BACKPACK_MODE = "first-person-backpack-mode";
private static final transient String LOOK_DOWN_PITCH_PATH = "look-down-backpack-remove";
private static final String VIEW_DISTANCE_PATH = "view-distance";
private static final String PARTICLE_COUNT = "particle-count";
private String defaultMenu;
private boolean requireEmptyHelmet;
private boolean requireEmptyOffHand;
private boolean requireEmptyChestPlate;
private boolean requireEmptyPants;
private boolean requireEmptyBoots;
private int lookDownPitch;
private int viewDistance;
private Vector balloonOffset;
private boolean firstPersonBackpackMode;
private int particleCount;
public void load(final FileConfiguration config) {
this.particleCount = config.getInt(PARTICLE_COUNT, 1);
this.defaultMenu = Utils.replaceIf(config.getString(DEFAULT_MENU), CosmeticsMenu.DEFAULT_MAIN_MENU, null, "");
this.requireEmptyHelmet = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_HELMET_PATH);
this.requireEmptyOffHand = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_OFF_HAND_PATH);
this.requireEmptyChestPlate = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_CHEST_PLATE_PATH);
this.requireEmptyPants = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_PANTS_PATH);
this.requireEmptyBoots = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_BOOTS_PATH);
this.lookDownPitch = config.getInt(COSMETIC_SETTINGS_PATH + "." + LOOK_DOWN_PITCH_PATH);
this.viewDistance = config.getInt(COSMETIC_SETTINGS_PATH + "." + VIEW_DISTANCE_PATH);
this.firstPersonBackpackMode = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + FIRST_PERSON_BACKPACK_MODE, false);
final var balloonSection = config.getConfigurationSection(COSMETIC_SETTINGS_PATH + "." + BALLOON_OFFSET);
if (balloonSection != null) {
this.balloonOffset = loadVector(balloonSection);
}
}
public int getParticleCount() {
return particleCount;
}
private Vector loadVector(final ConfigurationSection section) {
return new Vector(section.getDouble("x"), section.getDouble("y"), section.getDouble("z"));
}
public boolean isRequireEmptyHelmet() {
return requireEmptyHelmet;
}
public boolean isRequireEmptyOffHand() {
return requireEmptyOffHand;
}
public int getLookDownPitch() {
return lookDownPitch;
}
public void setRequireEmptyHelmet(final boolean requireEmptyHelmet) {
this.requireEmptyHelmet = requireEmptyHelmet;
}
public boolean isRequireEmptyOffHand() {
return requireEmptyOffHand;
}
public void setRequireEmptyOffHand(final boolean requireEmptyOffHand) {
this.requireEmptyOffHand = requireEmptyOffHand;
}
public boolean isRequireEmptyChestPlate() {
return requireEmptyChestPlate;
}
public void setRequireEmptyChestPlate(final boolean requireEmptyChestPlate) {
this.requireEmptyChestPlate = requireEmptyChestPlate;
}
public boolean isRequireEmptyPants() {
return requireEmptyPants;
}
public void setRequireEmptyPants(final boolean requireEmptyPants) {
this.requireEmptyPants = requireEmptyPants;
}
public boolean isRequireEmptyBoots() {
return requireEmptyBoots;
}
public void setRequireEmptyBoots(final boolean requireEmptyBoots) {
this.requireEmptyBoots = requireEmptyBoots;
}
public Vector getBalloonOffset() {
return balloonOffset;
}
public int getLookDownPitch() {
return lookDownPitch;
}
public int getViewDistance() {
return viewDistance;
}
public String getDefaultMenu() {
return defaultMenu;
}
public boolean isFirstPersonBackpackMode() {
return firstPersonBackpackMode;
}
public boolean requireEmpty(final EquipmentSlot slot) {
return switch (slot) {
case OFF_HAND -> this.isRequireEmptyOffHand();
case HEAD -> this.isRequireEmptyHelmet();
case CHEST -> this.isRequireEmptyChestPlate();
case LEGS -> this.isRequireEmptyPants();
case FEET -> this.isRequireEmptyBoots();
default -> false;
};
}
public boolean isInViewDistance(final Location location, final Location other) {
if (!Objects.equals(other.getWorld(), location.getWorld())) return false;
return !(other.distanceSquared(location) > this.getViewDistance() * this.getViewDistance());
}
}

View File

@@ -7,17 +7,18 @@ import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.ColorItem;
import io.github.fisher2911.hmccosmetics.gui.DyeSelectorGui;
import io.github.fisher2911.hmccosmetics.message.Adventure;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import io.github.fisher2911.hmccosmetics.gui.WrappedGuiItem;
import org.bukkit.Color;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class DyeGuiSerializer implements TypeSerializer<DyeSelectorGui> {
public static final DyeGuiSerializer INSTANCE = new DyeGuiSerializer();
@@ -67,7 +68,7 @@ public class DyeGuiSerializer implements TypeSerializer<DyeSelectorGui> {
final var node = entry.getValue();
final GuiItem guiItem = ItemSerializer.INSTANCE.deserialize(
final WrappedGuiItem guiItem = ArmorItemSerializer.INSTANCE.deserialize(
GuiItem.class,
node
);
@@ -84,7 +85,8 @@ public class DyeGuiSerializer implements TypeSerializer<DyeSelectorGui> {
final int blue = colorNode.node(BLUE).getInt();
guiItemMap.put(slot,
new ColorItem(guiItem.getItemStack(), Color.fromRGB(red, green, blue)));
new ColorItem(guiItem.getItemStack(), guiItem.getAction(), Color.fromRGB(red, green, blue))
);
}
final BiMap<Integer, ArmorItem.Type> cosmeticSlots = HashBiMap.create();
@@ -116,8 +118,7 @@ public class DyeGuiSerializer implements TypeSerializer<DyeSelectorGui> {
return new DyeSelectorGui(
plugin,
Adventure.SERIALIZER.serialize(
Adventure.MINI_MESSAGE.deserialize(title)),
title,
rowsNode.getInt(),
guiItemMap,
cosmeticSlots,

View File

@@ -3,16 +3,16 @@ package io.github.fisher2911.hmccosmetics.config;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.message.Adventure;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class GuiSerializer implements TypeSerializer<CosmeticGui> {
public static final GuiSerializer INSTANCE = new GuiSerializer();
@@ -49,11 +49,8 @@ public class GuiSerializer implements TypeSerializer<CosmeticGui> {
final Map<Integer, GuiItem> guiItemMap = new HashMap<>();
for (final var entry : childrenMap.entrySet()) {
if (!(entry.getKey() instanceof final Integer slot)) {
continue;
}
final GuiItem guiItem = ItemSerializer.INSTANCE.deserialize(
if (!(entry.getKey() instanceof final Integer slot)) continue;
final GuiItem guiItem = ArmorItemSerializer.INSTANCE.deserialize(
GuiItem.class,
entry.getValue()
);
@@ -68,8 +65,7 @@ public class GuiSerializer implements TypeSerializer<CosmeticGui> {
}
return new CosmeticGui(plugin,
Adventure.SERIALIZER.serialize(
Adventure.MINI_MESSAGE.deserialize(title)),
title,
rowsNode.getInt(),
guiItemMap);
}

View File

@@ -1,9 +1,5 @@
package io.github.fisher2911.hmccosmetics.config;
import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.util.Keys;
import io.github.fisher2911.hmccosmetics.util.StringUtils;
@@ -11,14 +7,6 @@ import io.github.fisher2911.hmccosmetics.util.Utils;
import io.github.fisher2911.hmccosmetics.util.builder.ColorBuilder;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import io.github.fisher2911.hmccosmetics.util.builder.SkullBuilder;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
@@ -26,7 +14,6 @@ import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
import org.bukkit.Registry;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -34,17 +21,22 @@ import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
public class ItemSerializer implements TypeSerializer<GuiItem> {
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class ItemSerializer implements TypeSerializer<ItemStack> {
public static final ItemSerializer INSTANCE = new ItemSerializer();
private static final HMCCosmetics plugin;
private static final String MATERIAL = "material";
private static final String AMOUNT = "amount";
private static final String NAME = "name";
private static final String UNBREAKABLE = "unbreakable";
private static final String GLOWING = "glowing";
private static final String LORE = "lore";
private static final String LOCKED_LORE = "locked-lore";
private static final String MODEL_DATA = "model-data";
private static final String ENCHANTS = "enchants";
private static final String ITEM_FLAGS = "item-flags";
@@ -54,39 +46,19 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
private static final String RED = "red";
private static final String GREEN = "green";
private static final String BLUE = "blue";
private static final String PERMISSION = "permission";
private static final String TYPE = "type";
private static final String ACTION = "action";
private static final String ID = "id";
private static final String DYEABLE = "dyeable";
static {
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
}
private ItemSerializer() {
}
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path)
throws SerializationException {
if (!source.hasChild(path)) {
throw new SerializationException(
"Required field " + Arrays.toString(path) + " was not present in node");
}
return source.node(path);
}
@Override
public GuiItem deserialize(final Type type, final ConfigurationNode source)
public ItemStack deserialize(final Type type, final ConfigurationNode source)
throws SerializationException {
final ConfigurationNode materialNode = this.nonVirtualNode(source, MATERIAL);
final ConfigurationNode materialNode = source.node(MATERIAL);
final ConfigurationNode amountNode = source.node(AMOUNT);
final ConfigurationNode nameNode = source.node(NAME);
final ConfigurationNode unbreakableNode = source.node(UNBREAKABLE);
final ConfigurationNode glowingNode = source.node(GLOWING);
final ConfigurationNode loreNode = source.node(LORE);
final ConfigurationNode lockedLoreNode = source.node(LOCKED_LORE);
final ConfigurationNode modelDataNode = source.node(MODEL_DATA);
final ConfigurationNode enchantsNode = source.node(ENCHANTS);
final ConfigurationNode itemFlagsNode = source.node(ITEM_FLAGS);
@@ -96,11 +68,6 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
final ConfigurationNode redNode = colorNode.node(RED);
final ConfigurationNode greenNode = colorNode.node(GREEN);
final ConfigurationNode blueNode = colorNode.node(BLUE);
final ConfigurationNode permissionNode = source.node(PERMISSION);
final ConfigurationNode typeNode = source.node(TYPE);
final ConfigurationNode actionNode = source.node(ACTION);
final ConfigurationNode idNode = source.node(ID);
final ConfigurationNode dyeableNode = source.node(DYEABLE);
final String materialString = Utils.replaceIfNull(materialNode.getString(), "");
final int amount = amountNode.getInt();
@@ -108,15 +75,15 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
ItemStack itemStack;
try {
itemStack = new ItemStack(Material.valueOf(materialString), amount);
itemStack = new ItemStack(Material.valueOf(materialString.toUpperCase()), amount);
} catch (final IllegalArgumentException exception) {
itemStack = HookManager.getInstance().getItemHooks().getItemStack(materialString);
if (itemStack == null) {
itemStack = new ItemStack(Material.AIR);
return null;
}
}
final String name = StringUtils.parseStringToString(nameNode.getString());
final String name = StringUtils.parseStringToString(Utils.replaceIfNull(nameNode.getString(), ""));
final boolean unbreakable = unbreakableNode.getBoolean();
final boolean glowing = glowingNode.getBoolean();
@@ -125,10 +92,6 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
final List<String> lockedLore = Utils.replaceIfNull(lockedLoreNode.getList(String.class),
new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
final int modelData = modelDataNode.getInt();
final Set<ItemFlag> itemFlags = Utils.replaceIfNull(itemFlagsNode.getList(String.class),
@@ -143,8 +106,6 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
final String texture = textureNode.getString();
final String owner = ownerNode.getString();
final boolean dyeable = dyeableNode.getBoolean();
final Color color;
if (colorNode.virtual()) {
@@ -204,49 +165,24 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
itemBuilder.modelData(modelData);
}
if (!lore.isEmpty()) itemBuilder.lore(lore);
if (!name.isBlank()) itemBuilder.name(name);
itemStack = itemBuilder.
amount(amount).
name(name).
unbreakable(unbreakable).
glow(glowing).
lore(lore).
enchants(enchantments, true).
itemFlags(itemFlags).
build();
final GuiAction<InventoryClickEvent> action = ActionSerializer.INSTANCE.deserialize(GuiAction.class, actionNode);
Keys.setKey(itemStack);
try {
final ArmorItem.Type cosmeticType = ArmorItem.Type.valueOf(
Utils.replaceIfNull(
typeNode.getString(), ""
).toUpperCase(Locale.ROOT)
);
final String permission = permissionNode.getString();
return new ArmorItem(
itemStack,
action,
Utils.replaceIfNull(idNode.getString(), ""),
lockedLore,
permission,
cosmeticType,
dyeable,
-1
);
} catch (final IllegalArgumentException exception) {
final GuiItem guiItem = dev.triumphteam.gui.builder.item.ItemBuilder.from(itemStack).asGuiItem();
guiItem.setAction(action);
return guiItem;
}
return itemStack;
}
@Override
public void serialize(final Type type, @Nullable final GuiItem obj, final ConfigurationNode node) throws SerializationException {
public void serialize(final Type type, @Nullable final ItemStack obj, final ConfigurationNode node) throws SerializationException {
}

View File

@@ -0,0 +1,46 @@
package io.github.fisher2911.hmccosmetics.config;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class LocationSerializer implements TypeSerializer<Location> {
public static final LocationSerializer INSTANCE = new LocationSerializer();
private static final String WORLD = "world";
private static final String X = "x";
private static final String Y = "y";
private static final String Z = "z";
private static final String PITCH = "pitch";
private static final String YAW = "yaw";
private LocationSerializer() {}
@Override
@Nullable
public Location deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
final World world = Bukkit.getWorld(source.node(WORLD).getString());
if (world == null) return null;
return new Location(
world,
source.node(X).getDouble(),
source.node(Y).getDouble(),
source.node(Z).getDouble(),
source.node(YAW).getFloat(),
source.node(PITCH).getFloat()
);
}
@Override
public void serialize(final Type type, @Nullable final Location obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -1,9 +1,7 @@
package io.github.fisher2911.hmccosmetics.config;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.MinecraftKey;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import net.minecraft.server.v1_16_R3.MinecraftKey;
import org.bukkit.entity.Player;
public class SoundData {
@@ -37,16 +35,17 @@ public class SoundData {
}
public void play(final Player player) {
final PacketContainer soundPacket = PacketManager.getSoundPacket(
player,
player.getLocation(),
this.getKey(this.name),
this.volume,
this.pitch,
this.soundCategory
);
PacketManager.sendPacket(player, soundPacket);
// todo - once packetevents updates
// final PacketContainer soundPacket = PacketManager.getSoundPacket(
// player,
// player.getLocation(),
// this.getKey(this.name),
// this.volume,
// this.pitch,
// this.soundCategory
// );
//
// PacketManager.sendPacket(player, soundPacket);
}
private MinecraftKey getKey(final String string) {

View File

@@ -0,0 +1,53 @@
package io.github.fisher2911.hmccosmetics.config;
import com.comphenix.protocol.wrappers.EnumWrappers;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class SoundSerializer implements TypeSerializer<SoundData> {
public static final SoundSerializer INSTANCE = new SoundSerializer();
private SoundSerializer() {}
private static final String SOUND_NAME = "name";
private static final String SOUND_VOLUME = "volume";
private static final String SOUND_PITCH = "pitch";
private static final String SOUND_CATEGORY = "category";
@Override
public SoundData deserialize(final Type type, final ConfigurationNode node) throws SerializationException {
final ConfigurationNode soundNameNode = node.node(SOUND_NAME);
final ConfigurationNode volumeNode = node.node(SOUND_VOLUME);
final ConfigurationNode pitchNode = node.node(SOUND_PITCH);
final ConfigurationNode categoryNode = node.node(SOUND_CATEGORY);
final SoundData soundData;
final String soundName = soundNameNode.getString();
final String category = categoryNode.getString();
final int volume = volumeNode.getInt();
final int pitch = pitchNode.getInt();
if (soundName == null || category == null) {
soundData = null;
} else {
soundData = new SoundData(
soundName,
EnumWrappers.SoundCategory.valueOf(category),
volume,
pitch
);
}
return soundData;
}
@Override
public void serialize(final Type type, @Nullable final SoundData obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -0,0 +1,37 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.gui.TokenGui;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class TokenGuiSerializer implements TypeSerializer<TokenGui> {
public static final TokenGuiSerializer INSTANCE = new TokenGuiSerializer();
private static final String TOKEN_SLOT = "token-slot";
private static final String COSMETIC_SLOT = "cosmetic-slot";
private TokenGuiSerializer() {}
@Override
public TokenGui deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
final CosmeticGui cosmeticGui = GuiSerializer.INSTANCE.deserialize(CosmeticGui.class, source);
final ConfigurationNode tokenSlotNode = source.node(TOKEN_SLOT);
final ConfigurationNode cosmeticSlotNode = source.node(COSMETIC_SLOT);
return new TokenGui(
cosmeticGui,
tokenSlotNode.getInt(),
cosmeticSlotNode.getInt()
);
}
@Override
public void serialize(final Type type, @Nullable final TokenGui obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -0,0 +1,59 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.Token;
import org.bukkit.inventory.ItemStack;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.nio.file.Path;
import java.util.List;
public class TokenLoader {
private static final String FILE_NAME = "tokens.yml";
private static final String TOKEN_PATH = "tokens";
private static final String ID_PATH = "id";
private static final String COMMANDS_PATH = "commands";
private final HMCCosmetics plugin;
private final CosmeticManager cosmeticManager;
public TokenLoader(final HMCCosmetics plugin) {
this.plugin = plugin;
this.cosmeticManager = this.plugin.getCosmeticManager();
}
public void load() {
final Path path = Path.of(this.plugin.getDataFolder().getPath(), FILE_NAME);
final File file = path.toFile();
if (!file.exists()) {
this.plugin.saveResource(FILE_NAME, false);
}
final YamlConfigurationLoader loader = YamlConfigurationLoader.
builder().
defaultOptions(opts -> opts.serializers(build -> build.register(ItemStack.class, ItemSerializer.INSTANCE))).
path(path).
build();
try {
final ConfigurationNode source = loader.load().node(TOKEN_PATH);
for (final var entry : source.childrenMap().entrySet()) {
final var node = entry.getValue();
final String id = node.node(ID_PATH).getString();
final ItemStack itemStack = node.get(ItemStack.class);
final ArmorItem armorItem = this.cosmeticManager.getArmorItem(id);
if (armorItem == null) {
this.plugin.getLogger().severe("Could not find armor item for token: " + id + " with id: " + id);
continue;
}
final List<String> commands = node.node(COMMANDS_PATH).getList(String.class);
this.cosmeticManager.addToken(new Token(itemStack, armorItem, commands));
}
} catch (final ConfigurateException exception) {
this.plugin.getLogger().severe("Error loading tokens!");
}
}
}

View File

@@ -1,31 +1,34 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.checkerframework.checker.units.qual.A;
import org.jetbrains.annotations.Nullable;
import io.github.fisher2911.hmccosmetics.util.Utils;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.nio.file.Path;
public class WardrobeSettings {
private static final String WARDROBE_PATH = "wardrobe";
private static final String DISABLE_ON_DAMAGE_PATH = WARDROBE_PATH + ".disable-on-damage";
private static final String DISPLAY_RADIUS_PATH = WARDROBE_PATH + ".display-radius";
private static final String PORTABLE_PATH = WARDROBE_PATH + ".portable";
private static final String ALWAYS_DISPLAY_PATH = WARDROBE_PATH + ".always-display";
private static final String STATIC_RADIUS_PATH = WARDROBE_PATH + ".static-radius";
private static final String STATIC_LOCATION_PATH = WARDROBE_PATH + ".wardrobe-location";
private static final String WORLD_PATH = "world";
private static final String X_PATH = "x";
private static final String Y_PATH = "y";
private static final String Z_PATH = "z";
private static final String YAW_PATH = "yaw";
private static final String PITCH_PATH = "pitch";
private static final String DISABLE_ON_DAMAGE_PATH = "disable-on-damage";
private static final String DISPLAY_RADIUS_PATH = "display-radius";
private static final String PORTABLE_PATH = "portable";
private static final String ALWAYS_DISPLAY_PATH = "always-display";
private static final String STATIC_RADIUS_PATH = "static-radius";
private static final String ROTATION_SPEED_PATH = "rotation-speed";
private static final String SPAWN_DELAY_PATH = "spawn-delay";
private static final String DESPAWN_DELAY_PATH = "despawn-delay";
private static final String APPLY_COSMETICS_ON_CLOSE = "apply-cosmetics-on-close";
private static final String OPEN_SOUND = "open-sound";
private static final String CLOSE_SOUND = "close-sound";
private static final String STATIC_LOCATION_PATH = "wardrobe-location";
private static final String VIEWER_LOCATION_PATH = "viewer-location";
private static final String LEAVE_LOCATION_PATH = "leave-location";
private static final String EQUIP_PUMPKIN_WARDROBE = "equip-pumpkin";
private static final String RETURN_LAST_LOCATION = "return-last-location";
private final HMCCosmetics plugin;
@@ -34,37 +37,54 @@ public class WardrobeSettings {
private boolean portable;
private boolean alwaysDisplay;
private int staticRadius;
private Location location;
private int rotationSpeed;
private int spawnDelay;
private int despawnDelay;
private boolean applyCosmeticsOnClose;
private boolean equipPumpkin;
private boolean returnLastLocation;
private SoundData openSound;
private SoundData closeSound;
private Location wardrobeLocation;
private Location viewerLocation;
private Location leaveLocation;
public WardrobeSettings(final HMCCosmetics plugin) {
this.plugin = plugin;
}
public void load() {
final FileConfiguration config = this.plugin.getConfig();
this.disableOnDamage = config.getBoolean(DISABLE_ON_DAMAGE_PATH);
this.displayRadius = config.getInt(DISPLAY_RADIUS_PATH);
this.portable = config.getBoolean(PORTABLE_PATH);
this.staticRadius = config.getInt(STATIC_RADIUS_PATH);
this.alwaysDisplay = config.getBoolean(ALWAYS_DISPLAY_PATH);
final ConfigurationSection locationSection = config.getConfigurationSection(STATIC_LOCATION_PATH);
if (locationSection == null) return;
this.location = this.loadLocation(locationSection);
}
@Nullable
private Location loadLocation(final ConfigurationSection section) {
final String worldName = section.getString(WORLD_PATH);
final double x = section.getDouble(X_PATH);
final double y = section.getDouble(Y_PATH);
final double z = section.getDouble(Z_PATH);
final float yaw = (float) section.getDouble(YAW_PATH);
final float pitch = (float) section.getDouble(PITCH_PATH);
if (worldName == null || worldName.isBlank()) return null;
final World world = Bukkit.getWorld(worldName);
if (world == null) return null;
return new Location(world, x, y, z, yaw, pitch);
final File file = Path.of(this.plugin.getDataFolder().getPath(), "config.yml").toFile();
final YamlConfigurationLoader loader = YamlConfigurationLoader.
builder().
path(file.toPath()).
defaultOptions(opts ->
opts.serializers(build -> {
build.register(SoundData.class, SoundSerializer.INSTANCE);
build.register(Location.class, LocationSerializer.INSTANCE);
}))
.build();
try {
final var source = loader.load().node(WARDROBE_PATH);
this.disableOnDamage = source.node(DISABLE_ON_DAMAGE_PATH).getBoolean();
this.displayRadius = source.node(DISPLAY_RADIUS_PATH).getInt();
this.portable = source.node(PORTABLE_PATH).getBoolean();
this.staticRadius = source.node(STATIC_RADIUS_PATH).getInt();
this.alwaysDisplay = source.node(ALWAYS_DISPLAY_PATH).getBoolean();
this.rotationSpeed = source.node(ROTATION_SPEED_PATH).getInt();
this.spawnDelay = source.node(SPAWN_DELAY_PATH).getInt();
this.despawnDelay = source.node(DESPAWN_DELAY_PATH).getInt();
this.applyCosmeticsOnClose = source.node(APPLY_COSMETICS_ON_CLOSE).getBoolean();
this.equipPumpkin = source.node(EQUIP_PUMPKIN_WARDROBE).getBoolean();
this.returnLastLocation = source.node(RETURN_LAST_LOCATION).getBoolean();
this.openSound = source.node(OPEN_SOUND).get(SoundData.class);
this.closeSound = source.node(CLOSE_SOUND).get(SoundData.class);
this.wardrobeLocation = source.node(STATIC_LOCATION_PATH).get(Location.class);
this.viewerLocation = source.node(VIEWER_LOCATION_PATH).get(Location.class);
this.leaveLocation = Utils.replaceIfNull(source.node(LEAVE_LOCATION_PATH).get(Location.class), this.viewerLocation);
} catch (final ConfigurateException exception) {
this.plugin.getLogger().severe("Error loading wardrobe settings");
}
}
public boolean getDisableOnDamage() {
@@ -87,18 +107,60 @@ public class WardrobeSettings {
return staticRadius;
}
public Location getLocation() {
return location.clone();
public int getRotationSpeed() {
return rotationSpeed;
}
public int getSpawnDelay() {
return spawnDelay;
}
public int getDespawnDelay() {
return despawnDelay;
}
public boolean isApplyCosmeticsOnClose() {
return applyCosmeticsOnClose;
}
public boolean isEquipPumpkin() {
return equipPumpkin;
}
public boolean isReturnLastLocation() {
return returnLastLocation;
}
public Location getWardrobeLocation() {
return this.wardrobeLocation.clone();
}
public Location getViewerLocation() {
return viewerLocation;
}
public Location getLeaveLocation() {
return leaveLocation;
}
public void playOpenSound(final Player player) {
if (this.openSound == null) return;
this.openSound.play(player);
}
public void playCloseSound(final Player player) {
if (this.closeSound == null) return;
this.closeSound.play(player);
}
public boolean inDistanceOfWardrobe(final Location wardrobeLocation, final Location playerLocation) {
if (this.displayRadius == -1) return true;
if (!wardrobeLocation.getWorld().equals(playerLocation.getWorld())) return false;
return playerLocation.distanceSquared(wardrobeLocation) <= this.displayRadius * this.displayRadius;
}
public boolean inDistanceOfStatic(final Location location) {
if (this.location == null) return false;
if (this.wardrobeLocation == null) return false;
if (this.staticRadius == -1) return false;
return this.location.distanceSquared(location) <= this.staticRadius * this.staticRadius;
if (!this.wardrobeLocation.getWorld().equals(location.getWorld())) return false;
return this.wardrobeLocation.distanceSquared(location) <= this.staticRadius * this.staticRadius;
}
}

View File

@@ -1,16 +1,34 @@
package io.github.fisher2911.hmccosmetics.cosmetic;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.ArmorItemSerializer;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.Token;
import io.github.fisher2911.hmccosmetics.gui.WrappedGuiItem;
import io.github.fisher2911.hmccosmetics.util.Keys;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
public class CosmeticManager {
private final Map<String, ArmorItem> armorItemMap;
private final Path ITEMS_PATH = Path.of(HMCCosmetics.getPlugin(HMCCosmetics.class).getDataFolder().getPath(), "items.yml");
public CosmeticManager(final Map<String, ArmorItem> armorItemMap) {
private final Map<String, Token> tokenMap;
private final Map<String, ArmorItem> armorItemMap;
private final Map<String, Integer> backpackParticleCounts;
public CosmeticManager(final Map<String, Token> tokenMap, final Map<String, ArmorItem> armorItemMap, final Map<String, Integer> backpackParticleCounts) {
this.tokenMap = tokenMap;
this.armorItemMap = armorItemMap;
this.backpackParticleCounts = backpackParticleCounts;
}
@Nullable
@@ -22,7 +40,7 @@ public class CosmeticManager {
this.armorItemMap.put(armorItem.getId(), armorItem);
}
public Collection<ArmorItem> getAll() {
public Collection<ArmorItem> getAllArmorItems() {
return this.armorItemMap.values();
}
@@ -30,4 +48,82 @@ public class CosmeticManager {
return armorItemMap;
}
@Nullable
public Token getToken(final String id) {
return this.tokenMap.get(id);
}
public void addToken(final Token token) {
this.tokenMap.put(token.getId(), token);
}
public Collection<Token> getAllTokens() {
return this.tokenMap.values();
}
public Map<String, Token> getTokenMap() {
return this.tokenMap;
}
@Nullable
public Token getToken(final ItemStack itemStack) {
final String id = Keys.getValue(itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING);
if (id == null) return null;
return this.tokenMap.get(id);
}
public boolean isToken(final ItemStack itemStack) {
return Keys.hasKey(itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING);
}
public void clearTokens() {
this.tokenMap.clear();
}
public void clearItems() {
this.armorItemMap.clear();
}
public int getBackpackParticleCount(final String id) {
return this.backpackParticleCounts.getOrDefault(id, 0);
}
public int getBackpackParticleCount(final ArmorItem armorItem) {
return this.getBackpackParticleCount(armorItem.getId());
}
private static final String PARTICLE_COUNT = "particle-count";
public void load() {
this.clearItems();
this.backpackParticleCounts.clear();
try {
final File file = ITEMS_PATH.toFile();
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}
final YamlConfigurationLoader loader = YamlConfigurationLoader.
builder().
path(ITEMS_PATH).
defaultOptions(opts ->
opts.serializers(build ->
build.register(WrappedGuiItem.class, ArmorItemSerializer.INSTANCE))
)
.build();
for (var node : loader.load().childrenMap().values()) {
final WrappedGuiItem item = ArmorItemSerializer.INSTANCE.deserialize(WrappedGuiItem.class, node);
if (item instanceof ArmorItem armorItem) {
armorItem.setAction(null);
if (armorItem.getType() == ArmorItem.Type.SELF_BACKPACK) {
final int particleCount = node.node(PARTICLE_COUNT).getInt(5);
this.backpackParticleCounts.put(armorItem.getId(), particleCount);
}
this.armorItemMap.put(armorItem.getId(), armorItem);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -1,4 +1,4 @@
package io.github.fisher2911.hmccosmetics.database.dao;
package io.github.fisher2911.hmccosmetics.dao;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@@ -36,8 +36,7 @@ public class ArmorItemDAO {
}
public static ArmorItemDAO fromArmorItem(final ArmorItem armorItem) {
return new ArmorItemDAO(armorItem.getId(), armorItem.getType().toString(),
armorItem.getDye());
return new ArmorItemDAO(armorItem.getId(), armorItem.getType().toString(), armorItem.getDye());
}
@Nullable
@@ -46,7 +45,7 @@ public class ArmorItemDAO {
if (armorItem == null) {
return null;
}
final ArmorItem copy = new ArmorItem(armorItem);
final ArmorItem copy = armorItem.copy();
copy.setDye(this.rgbDye);
return copy;
}

View File

@@ -0,0 +1,65 @@
package io.github.fisher2911.hmccosmetics.dao;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.user.Backpack;
import io.github.fisher2911.hmccosmetics.user.EntityIds;
import io.github.fisher2911.hmccosmetics.user.NPCUser;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
@DatabaseTable(tableName = "citizen")
public class CitizenDAO {
@DatabaseField(id = true)
private int citizensId;
public CitizenDAO() {
}
public CitizenDAO(final int citizensId) {
this.citizensId = citizensId;
}
public void setCitizensId(final int citizensId) {
this.citizensId = citizensId;
}
@Nullable
public NPCUser toUser(
final CosmeticManager cosmeticManager,
final EntityIds entityIds,
final List<ArmorItemDAO> armorItems,
Backpack backpack
) {
final PlayerArmor playerArmor = PlayerArmor.empty();
for (final ArmorItemDAO armorItemDao : armorItems) {
final ArmorItem armorItem = armorItemDao.toArmorItem(cosmeticManager);
if (armorItem == null) {
continue;
}
playerArmor.setItem(armorItem);
}
return new NPCUser(this.citizensId, playerArmor, backpack, entityIds);
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final CitizenDAO that = (CitizenDAO) o;
return citizensId == that.citizensId;
}
@Override
public int hashCode() {
return Objects.hash(citizensId);
}
}

View File

@@ -1,12 +1,15 @@
package io.github.fisher2911.hmccosmetics.database.dao;
package io.github.fisher2911.hmccosmetics.dao;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.user.Backpack;
import io.github.fisher2911.hmccosmetics.user.EntityIds;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
@@ -29,11 +32,14 @@ public class UserDAO {
this.uuid = uuid;
}
@Nullable
public User toUser(
final CosmeticManager cosmeticManager,
final EntityIds entityIds,
final List<ArmorItemDAO> armorItems,
final Wardrobe wardrobe,
final int armorStandId) {
final Backpack backpack,
final Wardrobe wardrobe
) {
final PlayerArmor playerArmor = PlayerArmor.empty();
for (final ArmorItemDAO armorItemDao : armorItems) {
@@ -44,7 +50,7 @@ public class UserDAO {
playerArmor.setItem(armorItem);
}
return new User(this.uuid, playerArmor, wardrobe, armorStandId);
return new User(this.uuid, playerArmor, backpack, wardrobe, entityIds);
}
@Override

View File

@@ -6,43 +6,35 @@ import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.concurrent.Threads;
import io.github.fisher2911.hmccosmetics.database.dao.ArmorItemDAO;
import io.github.fisher2911.hmccosmetics.database.dao.UserDAO;
import io.github.fisher2911.hmccosmetics.dao.ArmorItemDAO;
import io.github.fisher2911.hmccosmetics.dao.CitizenDAO;
import io.github.fisher2911.hmccosmetics.dao.UserDAO;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.user.Backpack;
import io.github.fisher2911.hmccosmetics.user.EntityIds;
import io.github.fisher2911.hmccosmetics.user.NPCUser;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import org.bukkit.Bukkit;
public class Database {
protected final HMCCosmetics plugin;
final Dao<UserDAO, UUID> userDao;
final Dao<ArmorItemDAO, UUID> armorItemDao;
private final Dao<UserDAO, UUID> userDao;
private final Dao<CitizenDAO, Integer> citizenDao;
private final Dao<ArmorItemDAO, String> armorItemDao;
private final ConnectionSource dataSource;
private final DatabaseType databaseType;
AtomicInteger FAKE_ENTITY_ID = new AtomicInteger(Integer.MAX_VALUE);
String TABLE_NAME = "user";
String PLAYER_UUID_COLUMN = "uuid";
String BACKPACK_COLUMN = "backpack";
String HAT_COLUMN = "hat";
String DYE_COLOR_COLUMN = "dye";
String CREATE_TABLE_STATEMENT =
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
PLAYER_UUID_COLUMN + " CHAR(36), " +
BACKPACK_COLUMN + " CHAR(50), " +
HAT_COLUMN + " CHAR(50), " +
DYE_COLOR_COLUMN + " INT, " +
"UNIQUE (" +
PLAYER_UUID_COLUMN +
"))";
public Database(
final HMCCosmetics plugin,
@@ -51,9 +43,9 @@ public class Database {
this.plugin = plugin;
this.dataSource = dataSource;
this.userDao = DaoManager.createDao(this.dataSource, UserDAO.class);
this.citizenDao = DaoManager.createDao(this.dataSource, CitizenDAO.class);
this.armorItemDao = DaoManager.createDao(this.dataSource, ArmorItemDAO.class);
this.databaseType = databaseType;
}
public void load() {
@@ -64,13 +56,17 @@ public class Database {
try {
TableUtils.createTableIfNotExists(this.dataSource, ArmorItemDAO.class);
TableUtils.createTableIfNotExists(this.dataSource, UserDAO.class);
TableUtils.createTableIfNotExists(this.dataSource, CitizenDAO.class);
} catch (final SQLException exception) {
exception.printStackTrace();
}
}
public void loadUser(final UUID uuid, final Consumer<User> onComplete) {
final int armorStandId = FAKE_ENTITY_ID.getAndDecrement();
public void loadUser(final Entity entity, final Consumer<User> onComplete) {
final UUID uuid = entity.getUniqueId();
final int armorStandId = getNextEntityId();
final int balloonId = getNextEntityId();
final int wardrobeViewerId = getNextEntityId();
final Wardrobe wardrobe = this.createNewWardrobe(uuid);
Threads.getInstance().execute(
() -> {
@@ -81,21 +77,66 @@ public class Database {
user = this.userDao.createIfNotExists(new UserDAO(uuid));
}
final List<ArmorItemDAO> armorItems = this.armorItemDao.queryForEq("uuid",
uuid.toString());
final List<ArmorItemDAO> armorItems = this.armorItemDao.queryForEq("uuid", uuid.toString());
final User actualUser = user.toUser(
this.plugin.getCosmeticManager(),
new EntityIds(
entity.getEntityId(),
armorStandId,
balloonId,
wardrobeViewerId
),
armorItems,
wardrobe,
armorStandId);
new Backpack(this.plugin, armorStandId),
wardrobe
);
Bukkit.getScheduler().runTask(this.plugin,
() -> {
this.plugin.getUserManager().add(
actualUser
);
onComplete.accept(actualUser);
}
() -> onComplete.accept(actualUser)
);
} catch (final SQLException exception) {
exception.printStackTrace();
}
});
onComplete.accept(new User(
uuid,
PlayerArmor.empty(),
new Backpack(this.plugin, armorStandId),
wardrobe,
new EntityIds(entity.getEntityId(), armorStandId, balloonId, wardrobeViewerId)
));
}
public void loadNPCUser(final int id, final Entity entity, final Consumer<NPCUser> onComplete) {
final int armorStandId = getNextEntityId();
final int balloonId = getNextEntityId();
final int wardrobeViewerId = getNextEntityId();
Threads.getInstance().execute(
() -> {
try {
CitizenDAO citizen = this.citizenDao.queryForId(id);
if (citizen == null) {
citizen = this.citizenDao.createIfNotExists(new CitizenDAO(id));
}
final List<ArmorItemDAO> armorItems = this.armorItemDao.queryForEq("uuid", String.valueOf(id));
final NPCUser actualUser = citizen.toUser(
this.plugin.getCosmeticManager(),
new EntityIds(
entity.getEntityId(),
armorStandId,
balloonId,
wardrobeViewerId
),
armorItems,
new Backpack(this.plugin, armorStandId)
);
Bukkit.getScheduler().runTask(this.plugin,
() -> onComplete.accept(actualUser)
);
} catch (final SQLException exception) {
@@ -103,17 +144,21 @@ public class Database {
}
});
final User user = new User(uuid, PlayerArmor.empty(), wardrobe, armorStandId);
this.plugin.getUserManager().add(user);
onComplete.accept(user);
onComplete.accept(new NPCUser(
id,
PlayerArmor.empty(),
new Backpack(this.plugin, armorStandId),
new EntityIds(entity.getEntityId(), armorStandId, balloonId, wardrobeViewerId)
)
);
}
public void saveUser(final User user) {
try {
final UserDAO userDAO = new UserDAO(user.getUuid());
final UserDAO userDAO = new UserDAO(user.getId());
this.userDao.createOrUpdate(userDAO);
final String uuid = user.getUuid().toString();
final String uuid = user.getId().toString();
for (final ArmorItem armorItem : user.getPlayerArmor().getArmorItems()) {
final ArmorItemDAO dao = ArmorItemDAO.fromArmorItem(armorItem);
dao.setUuid(uuid);
@@ -125,6 +170,23 @@ public class Database {
}
}
public void saveNPCUser(final NPCUser user) {
try {
final CitizenDAO citizenDAO = new CitizenDAO(user.getId());
this.citizenDao.createOrUpdate(citizenDAO);
final String id = user.getId().toString();
for (final ArmorItem armorItem : user.getPlayerArmor().getArmorItems()) {
final ArmorItemDAO dao = ArmorItemDAO.fromArmorItem(armorItem);
dao.setUuid(id);
this.armorItemDao.createOrUpdate(dao);
}
} catch (final SQLException exception) {
exception.printStackTrace();
}
}
public void saveAll() {
for (final User user : this.plugin.getUserManager().getAll()) {
this.saveUser(user);
@@ -151,19 +213,30 @@ public class Database {
return userDao;
}
public Dao<ArmorItemDAO, UUID> getArmorItemDao() {
public Dao<ArmorItemDAO, String> getArmorItemDao() {
return armorItemDao;
}
public Wardrobe createNewWardrobe(final UUID ownerUUID) {
final int armorStandId = getNextEntityId();
return new Wardrobe(
this.plugin,
UUID.randomUUID(),
ownerUUID,
PlayerArmor.empty(),
FAKE_ENTITY_ID.getAndDecrement(),
FAKE_ENTITY_ID.getAndDecrement(),
new Backpack(this.plugin, armorStandId),
new EntityIds(
getNextEntityId(),
armorStandId,
getNextEntityId(),
getNextEntityId()
),
false
);
}
public static int getNextEntityId() {
Random random = new Random();
return random.nextInt(999999);
}
}

View File

@@ -3,7 +3,10 @@ package io.github.fisher2911.hmccosmetics.database;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.user.Backpack;
import io.github.fisher2911.hmccosmetics.user.EntityIds;
import io.github.fisher2911.hmccosmetics.user.User;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
@@ -11,9 +14,6 @@ import java.nio.file.Path;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -21,10 +21,6 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import org.bukkit.configuration.file.YamlConfiguration;
import javax.swing.text.DateFormatter;
public class DatabaseConverter {
private static final int CURRENT_VERSION = 2;
@@ -91,11 +87,18 @@ public class DatabaseConverter {
while (results.next()) {
final PlayerArmor playerArmor = PlayerArmor.empty();
final UUID uuid = UUID.fromString(results.getString(1));
final int armorStandId = Database.getNextEntityId();
final User user = new User(
uuid,
playerArmor,
new Backpack(this.plugin, armorStandId),
this.database.createNewWardrobe(uuid),
this.database.FAKE_ENTITY_ID.getAndDecrement()
new EntityIds(
-1,
armorStandId,
Database.getNextEntityId(),
Database.getNextEntityId()
)
);
final String backpackId = results.getString(2);
final String hatId = results.getString(3);

View File

@@ -1,42 +1,47 @@
package io.github.fisher2911.hmccosmetics.gui;
import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.config.CosmeticGuiAction;
import io.github.fisher2911.hmccosmetics.util.builder.ColorBuilder;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ArmorItem extends GuiItem {
import java.util.ArrayList;
import java.util.List;
public class ArmorItem extends WrappedGuiItem {
private final String name;
private final String id;
private final List<String> lockedLore;
private final ItemStack lockedItem;
private final ItemStack appliedItem;
private final String permission;
private final Type type;
private GuiAction<InventoryClickEvent> action;
private List<CosmeticGuiAction> actions;
private boolean dyeable;
private int dye;
public ArmorItem(
@NotNull final ItemStack itemStack,
final GuiAction<InventoryClickEvent> action,
final List<CosmeticGuiAction> actions,
final String name,
final String id,
final List<String> lockedLore,
final ItemStack lockedItem,
final ItemStack appliedItem,
final String permission,
final Type type,
final int dye) {
super(itemStack, action);
super(itemStack, null);
this.name = name;
this.id = id;
this.lockedLore = lockedLore;
this.action = action;
this.lockedItem = lockedItem;
this.appliedItem = appliedItem;
this.actions = actions;
this.permission = permission;
this.type = type;
this.dye = dye;
@@ -44,15 +49,19 @@ public class ArmorItem extends GuiItem {
public ArmorItem(
@NotNull final ItemStack itemStack,
final String name,
final String id,
final List<String> lockedLore,
final ItemStack lockedItem,
final ItemStack appliedItem,
final String permission,
final Type type,
final int dye) {
super(itemStack);
this.id = id;
this.lockedLore = lockedLore;
this.action = null;
this.name = name;
this.lockedItem = lockedItem;
this.appliedItem = appliedItem;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dye = dye;
@@ -60,15 +69,19 @@ public class ArmorItem extends GuiItem {
public ArmorItem(
@NotNull final Material material,
final String name,
final String id,
final List<String> lockedLore,
final ItemStack lockedItem,
final ItemStack appliedItem,
final String permission,
final Type type,
final int dye) {
super(material);
this.id = id;
this.lockedLore = lockedLore;
this.action = null;
this.name = name;
this.lockedItem = lockedItem;
this.appliedItem = appliedItem;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dye = dye;
@@ -76,16 +89,20 @@ public class ArmorItem extends GuiItem {
public ArmorItem(
@NotNull final Material material,
@Nullable final GuiAction<InventoryClickEvent> action,
final List<CosmeticGuiAction> actions,
final String name,
final String id,
final List<String> lockedLore,
final ItemStack lockedItem,
final ItemStack appliedItem,
final String permission,
final Type type,
final int dye) {
super(material, action);
super(material, null);
this.actions = actions;
this.id = id;
this.lockedLore = lockedLore;
this.action = action;
this.name = name;
this.lockedItem = lockedItem;
this.appliedItem = appliedItem;
this.permission = permission;
this.type = type;
this.dye = dye;
@@ -93,17 +110,21 @@ public class ArmorItem extends GuiItem {
public ArmorItem(
@NotNull final ItemStack itemStack,
final GuiAction<InventoryClickEvent> action,
final List<CosmeticGuiAction> actions,
final String name,
final String id,
final List<String> lockedLore,
final ItemStack lockedItem,
final ItemStack appliedItem,
final String permission,
final Type type,
final boolean dyeable,
final int dye) {
super(itemStack, action);
super(itemStack, null);
this.name = name;
this.id = id;
this.lockedLore = lockedLore;
this.action = action;
this.lockedItem = lockedItem;
this.appliedItem = appliedItem;
this.actions = actions;
this.permission = permission;
this.type = type;
this.dyeable = dyeable;
@@ -112,16 +133,20 @@ public class ArmorItem extends GuiItem {
public ArmorItem(
@NotNull final ItemStack itemStack,
final String name,
final String id,
final List<String> lockedLore,
final ItemStack lockedItem,
final ItemStack appliedItem,
final String permission,
final Type type,
final boolean dyeable,
final int dye) {
super(itemStack);
this.name = name;
this.id = id;
this.lockedLore = lockedLore;
this.action = null;
this.lockedItem = lockedItem;
this.appliedItem = appliedItem;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dyeable = dyeable;
@@ -130,16 +155,20 @@ public class ArmorItem extends GuiItem {
public ArmorItem(
@NotNull final Material material,
final String name,
final String id,
final List<String> lockedLore,
final ItemStack lockedItem,
final ItemStack appliedItem,
final String permission,
final Type type,
final boolean dyeable,
final int dye) {
super(material);
this.id = id;
this.lockedLore = lockedLore;
this.action = null;
this.name = name;
this.lockedItem = lockedItem;
this.appliedItem = appliedItem;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dyeable = dyeable;
@@ -149,28 +178,33 @@ public class ArmorItem extends GuiItem {
public ArmorItem(
@NotNull final Material material,
@Nullable final GuiAction<InventoryClickEvent> action,
final String name,
final String id,
final List<String> lockedLore,
final ItemStack lockedItem,
final ItemStack appliedItem,
final String permission,
final Type type,
final boolean dyeable,
final int dye) {
super(material, action);
this.name = name;
this.id = id;
this.lockedLore = lockedLore;
this.action = action;
this.lockedItem = lockedItem;
this.appliedItem = appliedItem;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dyeable = dyeable;
this.dye = dye;
}
public ArmorItem(final ArmorItem armorItem) {
super(armorItem.getItemStack(), armorItem.getAction());
protected ArmorItem(final ArmorItem armorItem) {
super(armorItem.getItemStack().clone(), null);
this.name = armorItem.getName();
this.id = armorItem.getId();
this.lockedLore = new ArrayList<>();
Collections.copy(armorItem.getLockedLore(), this.lockedLore);
this.action = armorItem.getAction();
this.lockedItem = armorItem.getLockedItem().clone();
this.appliedItem = armorItem.getAppliedItem().clone();
this.actions = armorItem.getActions();
this.permission = armorItem.getPermission();
this.type = armorItem.getType();
this.dyeable = armorItem.isDyeable();
@@ -178,10 +212,29 @@ public class ArmorItem extends GuiItem {
}
public static ArmorItem empty(final Type type) {
return empty(type, "");
}
public static ArmorItem empty(final Type type, final String id) {
if (type == Type.BALLOON) {
return new BalloonItem(
new ItemStack(Material.AIR),
id,
id,
new ItemStack(Material.AIR),
new ItemStack(Material.AIR),
"",
type,
-1,
""
);
}
return new ArmorItem(
new ItemStack(Material.AIR),
"",
new ArrayList<>(),
id,
id,
new ItemStack(Material.AIR),
new ItemStack(Material.AIR),
"",
type,
-1
@@ -192,18 +245,21 @@ public class ArmorItem extends GuiItem {
return id;
}
public List<String> getLockedLore() {
return lockedLore;
public ItemStack getLockedItem() {
return lockedItem;
}
public GuiAction<InventoryClickEvent> getAction() {
return this.action;
public ItemStack getAppliedItem() {
return appliedItem;
}
@Override
public void setAction(final GuiAction<InventoryClickEvent> action) {
super.setAction(action);
this.action = action;
public List<CosmeticGuiAction> getActions() {
return actions;
}
public void setActions(final List<CosmeticGuiAction> actions) {
this.actions.clear();
this.actions.addAll(actions);
}
public String getPermission() {
@@ -226,22 +282,12 @@ public class ArmorItem extends GuiItem {
this.dye = dye;
}
public ItemStack getColored() {
return this.color(super.getItemStack());
}
public ItemStack getItemStack(final boolean allowed) {
final ItemStack itemStack;
if (allowed) {
itemStack = super.getItemStack();
} else {
itemStack = ItemBuilder.from(this.getItemStack()).
lore(this.lockedLore).
build();
}
return this.color(itemStack);
public ItemStack getItemStack(final Status status) {
return this.color(switch (status) {
case ALLOWED -> super.getItemStack();
case LOCKED -> this.getLockedItem();
case APPLIED -> this.getAppliedItem();
});
}
private ItemStack color(final ItemStack itemStack) {
@@ -259,15 +305,61 @@ public class ArmorItem extends GuiItem {
}
public ArmorItem copy() {
if (this instanceof final BalloonItem item) {
return new BalloonItem(item);
}
return new ArmorItem(this);
}
public String getName() {
return this.name;
}
public enum Type {
HAT,
BACKPACK,
OFF_HAND
HAT(EquipmentSlot.HEAD),
BACKPACK(null),
SELF_BACKPACK(null),
BALLOON(null),
OFF_HAND(EquipmentSlot.OFF_HAND),
CHEST_PLATE(EquipmentSlot.CHEST),
PANTS(EquipmentSlot.LEGS),
BOOTS(EquipmentSlot.FEET);
private final EquipmentSlot slot;
Type(final EquipmentSlot slot) {
this.slot = slot;
}
public EquipmentSlot getSlot() {
return slot;
}
@Nullable
public static Type fromWrapper(EquipmentSlot slot) {
return switch (slot) {
case HEAD -> Type.HAT;
case CHEST -> Type.CHEST_PLATE;
case LEGS -> Type.PANTS;
case FEET -> Type.BOOTS;
case OFF_HAND -> Type.OFF_HAND;
default -> null;
};
}
@Nullable
public static Type fromEquipmentSlot(final EquipmentSlot slot) {
for (final Type type : values()) {
if (type.getSlot() == slot) return type;
}
return null;
}
}
public enum Status {
ALLOWED,
LOCKED,
APPLIED
}
}

View File

@@ -0,0 +1,84 @@
package io.github.fisher2911.hmccosmetics.gui;
import dev.triumphteam.gui.components.GuiAction;
import io.github.fisher2911.hmccosmetics.config.CosmeticGuiAction;
import org.apache.logging.log4j.util.Strings;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class BalloonItem extends ArmorItem {
private final String modelId;
public BalloonItem(final BalloonItem item) {
this(
item.getItemStack(),
item.getActions(),
item.getName(),
item.getId(),
item.getLockedItem(),
item.getAppliedItem(),
item.getPermission(),
item.getType(),
item.getDye(),
item.getModelId()
);
}
public BalloonItem(final @NotNull ItemStack itemStack, final List<CosmeticGuiAction> actions, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final int dye, final String modelId) {
super(itemStack, actions, name, id, lockedItem, appliedItem, permission, type, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull ItemStack itemStack, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final int dye, final String modelId) {
super(itemStack, name, id, lockedItem, appliedItem, permission, type, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull Material material, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final int dye, final String modelId) {
super(material, name, id, lockedItem, appliedItem, permission, type, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull Material material, final List<CosmeticGuiAction> actions, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final int dye, final String modelId) {
super(material, actions, name, id, lockedItem, appliedItem, permission, type, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull ItemStack itemStack, final List<CosmeticGuiAction> actions, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
super(itemStack, actions, name, id, lockedItem, appliedItem, permission, type, dyeable, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull ItemStack itemStack, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
super(itemStack, name, id, lockedItem, appliedItem, permission, type, dyeable, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull Material material, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
super(material, name, id, lockedItem, appliedItem, permission, type, dyeable, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull Material material, final String name, final @Nullable GuiAction<InventoryClickEvent> action, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
super(material, action, name, id, lockedItem, appliedItem, permission, type, dyeable, dye);
this.modelId = modelId;
}
public BalloonItem(final ArmorItem armorItem, final String modelId) {
super(armorItem);
this.modelId = modelId;
}
public String getModelId() {
if (this.modelId == null) {
return Strings.EMPTY;
}
return this.modelId;
}
}

View File

@@ -9,13 +9,16 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ColorItem extends GuiItem {
public class ColorItem extends WrappedGuiItem {
private final Color color;
public ColorItem(final @NotNull ItemStack itemStack,
final GuiAction<InventoryClickEvent> action,
final Color color) {
public ColorItem(final GuiItem item, final GuiAction<InventoryClickEvent> action, final Color color) {
super(item, action);
this.color = color;
}
public ColorItem(final @NotNull ItemStack itemStack, final @Nullable GuiAction<@NotNull InventoryClickEvent> action, final Color color) {
super(itemStack, action);
this.color = color;
}
@@ -30,8 +33,7 @@ public class ColorItem extends GuiItem {
this.color = color;
}
public ColorItem(final @NotNull Material material,
final @Nullable GuiAction<InventoryClickEvent> action, final Color color) {
public ColorItem(final @NotNull Material material, final @Nullable GuiAction<@NotNull InventoryClickEvent> action, final Color color) {
super(material, action);
this.color = color;
}
@@ -39,5 +41,4 @@ public class ColorItem extends GuiItem {
public Color getColor() {
return color;
}
}

View File

@@ -1,9 +1,9 @@
package io.github.fisher2911.hmccosmetics.gui;
import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.Gui;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.CosmeticGuiAction;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.message.Adventure;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
@@ -11,16 +11,18 @@ import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class CosmeticGui {
private static final float COOL_DOWN = 0.5f;
@@ -45,6 +47,7 @@ public class CosmeticGui {
this.guiItemMap = guiItemMap;
this.itemStackMap = new HashMap<>();
this.guiItemMap.forEach((key, value) -> itemStackMap.put(key, value.getItemStack()));
}
private void setItems(final User user) {
@@ -71,7 +74,7 @@ public class CosmeticGui {
final User user,
final ArmorItem armorItem,
final InventoryClickEvent event,
final GuiAction<InventoryClickEvent> actionIfSet) {
final List<CosmeticGuiAction> actions) {
final long current = System.currentTimeMillis();
if ((current - this.lastClicked) / 1000. < COOL_DOWN) {
@@ -85,15 +88,24 @@ public class CosmeticGui {
final ArmorItem.Type type = armorItem.getType();
final User setUser;
if (user.isWardrobeActive()) {
setUser = user.getWardrobe();
} else {
setUser = user;
}
final ArmorItem setTo = this.plugin.getUserManager().setOrUnset(
user,
setUser,
armorItem,
Messages.getRemovedMessage(type),
Messages.getSetMessage(type)
Messages.getSetMessage(type),
true
);
if (!setTo.isEmpty()) {
actionIfSet.execute(event);
executeActions(event, actions, CosmeticGuiAction.When.EQUIP);
} else {
executeActions(event, actions, CosmeticGuiAction.When.REMOVE);
}
final int slot = event.getSlot();
@@ -107,14 +119,25 @@ public class CosmeticGui {
this.gui.updateItem(slot, guiItem);
}
private void executeActions(
final InventoryClickEvent event,
final List<CosmeticGuiAction> actions,
final CosmeticGuiAction.When when
) {
for (final CosmeticGuiAction action : actions) {
action.execute(event, when);
}
}
public void open(final User user, final Player player) {
final Component component = Adventure.MINI_MESSAGE.deserialize(Placeholder.applyPapiPlaceholders(user.getPlayer(), this.title));
this.gui = Gui.gui().
title(Adventure.MINI_MESSAGE.deserialize(
Placeholder.applyPapiPlaceholders(player, this.title))).
title(component).
rows(this.rows).
create();
this.gui.setDefaultClickAction(event -> event.setCancelled(true));
this.gui.setCloseGuiAction(event -> user.setOpenGui(null));
this.setItems(user);
@@ -124,17 +147,16 @@ public class CosmeticGui {
@Nullable
private GuiItem getGuiItem(final User user, final Player player, final int slot) {
final GuiItem guiItem = this.guiItemMap.get(slot);
if (guiItem == null) {
return null;
}
final ItemStack itemStack = this.itemStackMap.get(slot);
if (itemStack == null) return null;
return this.getGuiItem(user, player, guiItem, itemStack);
}
if (itemStack == null) {
return null;
}
@Nullable
protected GuiItem getGuiItem(final User user, final Player player, final GuiItem guiItem, final ItemStack itemStack) {
if (guiItem instanceof final ArmorItem armorItem) {
final String permission =
armorItem.getPermission() == null ? "" : armorItem.getPermission();
@@ -159,7 +181,7 @@ public class CosmeticGui {
return;
}
this.setUserArmor(player, user, cosmeticItem, event, armorItem.getAction());
this.setUserArmor(player, user, cosmeticItem, event, armorItem.getActions());
}
);
}
@@ -171,8 +193,12 @@ public class CosmeticGui {
return guiItem;
}
protected ItemStack applyPlaceholders(final User user, final Player player,
final ArmorItem armorItem, final boolean hasPermission) {
protected ItemStack applyPlaceholders(
final User user,
final Player player,
final ArmorItem armorItem,
final boolean hasPermission
) {
final Map<String, String> placeholders = new HashMap<>();
final PlayerArmor playerArmor = user.getPlayerArmor();
@@ -194,9 +220,9 @@ public class CosmeticGui {
final ItemStack itemStack;
if (!hasPermission) {
itemStack = armorItem.getItemStack(false);
itemStack = armorItem.getItemStack(ArmorItem.Status.LOCKED);
} else {
itemStack = armorItem.getColored();
itemStack = armorItem.getItemStack(ArmorItem.Status.ALLOWED);
}
return ItemBuilder.from(
@@ -207,6 +233,15 @@ public class CosmeticGui {
build();
}
public void updateItem(final int slot, final GuiItem guiItem, final User user, final Player player) {
final ItemStack itemStack = guiItem.getItemStack().clone();
this.guiItemMap.put(slot, guiItem);
this.itemStackMap.put(slot, itemStack);
final GuiItem setItem = this.getGuiItem(user, player, guiItem, itemStack);
if (setItem == null) return;
this.gui.updateItem(slot, setItem);
}
public CosmeticGui copy() {
return new CosmeticGui(
this.plugin,

View File

@@ -2,9 +2,11 @@ package io.github.fisher2911.hmccosmetics.gui;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.ArmorItemSerializer;
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
import io.github.fisher2911.hmccosmetics.config.DyeGuiSerializer;
import io.github.fisher2911.hmccosmetics.config.GuiSerializer;
import io.github.fisher2911.hmccosmetics.config.ItemSerializer;
import io.github.fisher2911.hmccosmetics.config.TokenGuiSerializer;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
@@ -19,8 +21,10 @@ import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -29,8 +33,10 @@ public class CosmeticsMenu {
public static final String DEFAULT_MAIN_MENU = "main";
public static final String DEFAULT_DYE_MENU = "dye-menu";
public static final String DEFAULT_TOKEN_MENU = "token-menu";
private final HMCCosmetics plugin;
private final CosmeticSettings settings;
private final CosmeticManager cosmeticManager;
private final Map<String, CosmeticGui> guiMap = new HashMap<>();
@@ -39,6 +45,7 @@ public class CosmeticsMenu {
public CosmeticsMenu(final HMCCosmetics plugin) {
this.plugin = plugin;
this.settings = this.plugin.getSettings().getCosmeticSettings();
this.cosmeticManager = this.plugin.getCosmeticManager();
}
@@ -57,18 +64,26 @@ public class CosmeticsMenu {
if (cosmeticGui instanceof final DyeSelectorGui dyeSelectorGui) {
dyeSelectorGui.getGui(user, user.getLastSetItem().getType()).open(humanEntity);
user.setOpenGui(dyeSelectorGui);
return;
}
if (cosmeticGui != null) cosmeticGui.open(user, player);
if (cosmeticGui != null) {
user.setOpenGui(cosmeticGui);
cosmeticGui.open(user, player);
}
}
public Set<String> getMenus() {
return this.guiMap.keySet();
}
public void openDefault(final HumanEntity humanEntity) {
this.openMenu(DEFAULT_MAIN_MENU, humanEntity);
this.openMenu(this.settings.getDefaultMenu(), humanEntity);
}
public void reload() {
for (final ArmorItem armorItem : this.cosmeticManager.getAll()) {
for (final ArmorItem armorItem : this.cosmeticManager.getAllArmorItems()) {
Bukkit.getPluginManager().removePermission(new Permission(armorItem.getPermission()));
}
this.load();
@@ -87,7 +102,7 @@ public class CosmeticsMenu {
final Wardrobe wardrobe = user.getWardrobe();
if (wardrobe.isActive()) user = wardrobe;
final CosmeticGui gui = this.getGui(DEFAULT_DYE_MENU);
final CosmeticGui gui = this.getGui(this.settings.getDefaultMenu());
if (gui instanceof final DyeSelectorGui dyeSelectorGui) {
dyeSelectorGui.getGui(user, type).open(player);
@@ -103,17 +118,20 @@ public class CosmeticsMenu {
private static final String GUI_TYPE = "gui-type";
private static final String DYE_TYPE = "dye";
private static final String TOKEN_TYPE = "token";
public void load() {
this.guiMap.clear();
this.cosmeticManager.clearTokens();
this.cosmeticManager.load();
final File file = Path.of(this.plugin.getDataFolder().getPath(),
"menus").toFile();
if (!Path.of(this.plugin.getDataFolder().getPath(),
"menus",
DEFAULT_MAIN_MENU + ".yml").toFile().exists()) {
this.settings.getDefaultMenu() + ".yml").toFile().exists()) {
this.plugin.saveResource(
new File("menus", DEFAULT_MAIN_MENU + ".yml").getPath(),
new File("menus", this.settings.getDefaultMenu() + ".yml").getPath(),
false
);
}
@@ -127,16 +145,25 @@ public class CosmeticsMenu {
);
}
if (!Path.of(this.plugin.getDataFolder().getPath(),
"menus",
DEFAULT_TOKEN_MENU + ".yml").toFile().exists()) {
this.plugin.saveResource(
new File("menus", DEFAULT_TOKEN_MENU + ".yml").getPath(),
false
);
}
if (!file.exists() ||
!file.isDirectory()) {
this.plugin.getLogger().severe("No directory found");
return;
}
final File[] files = file.listFiles();
final List<File> files = this.getSubFiles(file);
if (files == null) {
this.plugin.getLogger().severe("Files are null");
if (files.isEmpty()) {
this.plugin.getLogger().severe("No GUI files found.");
return;
}
@@ -148,9 +175,10 @@ public class CosmeticsMenu {
path(Path.of(guiFile.getPath())).
defaultOptions(opts ->
opts.serializers(build -> {
build.register(GuiItem.class, ItemSerializer.INSTANCE);
build.register(WrappedGuiItem.class, ArmorItemSerializer.INSTANCE);
build.register(CosmeticGui.class, GuiSerializer.INSTANCE);
build.register(DyeSelectorGui.class, DyeGuiSerializer.INSTANCE);
build.register(TokenGui.class, TokenGuiSerializer.INSTANCE);
}))
.build();
@@ -172,17 +200,24 @@ public class CosmeticsMenu {
continue;
}
if (TOKEN_TYPE.equals(type)) {
this.guiMap.put(id, TokenGuiSerializer.INSTANCE.deserialize(TokenGui.class, source));
this.plugin.getLogger().info("Loaded token gui: " + id);
continue;
}
final CosmeticGui gui = source.get(CosmeticGui.class);
if (gui == null) continue;
for (final GuiItem guiItem : gui.guiItemMap.values()) {
if (guiItem instanceof final ArmorItem item) {
final ArmorItem copy = new ArmorItem(item);
final ArmorItem copy = item.copy();
copy.setAction(null);
this.cosmeticManager.addArmorItem(copy);
final String perm = copy.getPermission();
if (perm.isBlank() || this.registeredPermissions.contains(perm)) continue;
this.registeredPermissions.add(perm);
Bukkit.getPluginManager().addPermission(new Permission(perm));
}
}
@@ -195,4 +230,19 @@ public class CosmeticsMenu {
}
}
private List<File> getSubFiles(final File dir) {
final List<File> files = new ArrayList<>();
if (!dir.isDirectory()) return files;
final File[] arr = dir.listFiles();
if (arr == null) return files;
for (final File file : arr) {
if (file.isDirectory()) {
files.addAll(this.getSubFiles(file));
continue;
}
files.add(file);
}
return files;
}
}

View File

@@ -6,19 +6,18 @@ import dev.triumphteam.gui.guis.Gui;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.message.Adventure;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
public class DyeSelectorGui extends CosmeticGui {
private final BiMap<Integer, ArmorItem.Type> cosmeticsSlots;
@@ -42,9 +41,9 @@ public class DyeSelectorGui extends CosmeticGui {
}
public Gui getGui(final User user, @Nullable final ArmorItem.Type type) {
final Component component = Adventure.MINI_MESSAGE.deserialize(Placeholder.applyPapiPlaceholders(user.getPlayer(), this.title));
this.gui = Gui.gui().
title(Component.text(
Placeholder.applyPapiPlaceholders(user.getPlayer(), this.title))).
title(component).
rows(rows).
create();
@@ -55,20 +54,6 @@ public class DyeSelectorGui extends CosmeticGui {
this.selectedCosmetic = selected == null ? this.selectedCosmetic : selected;
}
for (final var entry : this.cosmeticsSlots.entrySet()) {
gui.setItem(
entry.getKey(),
new GuiItem(
this.applyPlaceholders(
user,
player,
user.getPlayerArmor().getItem(entry.getValue()),
true
)
)
);
}
for (final var entry : this.guiItemMap.entrySet()) {
final GuiItem guiItem = entry.getValue();
@@ -86,6 +71,25 @@ public class DyeSelectorGui extends CosmeticGui {
gui.setItem(entry.getKey(), guiItem);
}
for (final var entry : this.cosmeticsSlots.entrySet()) {
final ArmorItem guiItem = user.getPlayerArmor().getItem(entry.getValue()).copy();
final ItemStack itemStack = guiItem.getItemStack();
if (itemStack == null || guiItem.isEmpty()) continue;
guiItem.setItemStack(
ItemBuilder.from(
this.applyPlaceholders(
user, player, guiItem, true
)
).build()
);
gui.setItem(entry.getKey(), guiItem);
}
final PlayerArmor playerArmor = user.getPlayerArmor();
this.select(this.selectedCosmetic, user, player);
@@ -128,7 +132,14 @@ public class DyeSelectorGui extends CosmeticGui {
armorItem.setDye(colorItem.getColor().asRGB());
this.plugin.getUserManager().setItem(user, armorItem);
if (user.isWardrobeActive()) {
this.plugin.getUserManager().setItem(user.getWardrobe(), armorItem, true);
} else {
this.plugin.getUserManager().setItem(user, armorItem, true);
}
if (colorItem.getAction() != null) {
colorItem.getAction().execute(event);
}
this.updateSelected(user, player);
});
@@ -139,19 +150,33 @@ public class DyeSelectorGui extends CosmeticGui {
final PlayerArmor playerArmor = user.getPlayerArmor();
final ArmorItem previousArmorItem = playerArmor.getItem(this.cosmeticsSlots.get(this.selectedCosmetic));
final ItemStack previous = this.applyPlaceholders(
user,
player,
playerArmor.getItem(this.cosmeticsSlots.get(this.selectedCosmetic)),
previousArmorItem,
true
);
if (previous != null && previous.getType() != Material.AIR) {
if (previous != null && !previousArmorItem.isEmpty()) {
final ItemStack previousItem = dev.triumphteam.gui.builder.item.ItemBuilder.from(
previous
).glow(false).build();
).build();
this.gui.updateItem(this.selectedCosmetic, previousItem);
} else {
final GuiItem guiItem = this.guiItemMap.get(this.selectedCosmetic);
final ItemStack itemStack = this.itemStackMap.get(this.selectedCosmetic);
if (itemStack != null && guiItem != null) {
final GuiItem setItem = this.getGuiItem(
user,
player,
guiItem,
itemStack
);
if (setItem != null) this.gui.updateItem(this.selectedCosmetic, setItem);
}
}
this.selectedCosmetic = slot;
@@ -166,13 +191,16 @@ public class DyeSelectorGui extends CosmeticGui {
return;
}
this.gui.updateItem(this.selectedCosmetic,
final ArmorItem armorItem = user.getPlayerArmor().getItem(type);
if (armorItem.isEmpty()) return;
this.gui.updateItem(
this.selectedCosmetic,
ItemBuilder.from(
this.applyPlaceholders(
user, player, user.getPlayerArmor().getItem(type), true
user, player, armorItem, true
)
).glow(true).build());
).build());
}
@Override

View File

@@ -0,0 +1,37 @@
package io.github.fisher2911.hmccosmetics.gui;
import io.github.fisher2911.hmccosmetics.util.Keys;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import java.util.List;
public class Token {
private final ItemStack itemStack;
private final ArmorItem armorItem;
private final List<String> commands;
public Token(final ItemStack itemStack, final ArmorItem armorItem, final List<String> commands) {
this.itemStack = itemStack;
this.armorItem = armorItem;
this.commands = commands;
Keys.setKey(this.itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING, this.armorItem.getId());
}
public String getId() {
return this.armorItem.getId();
}
public ItemStack getItemStack() {
return itemStack;
}
public ArmorItem getArmorItem() {
return armorItem;
}
public List<String> getCommands() {
return commands;
}
}

View File

@@ -0,0 +1,145 @@
package io.github.fisher2911.hmccosmetics.gui;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
public class TokenGui extends CosmeticGui {
private final int tokenSlot;
private final int cosmeticSlot;
private final CosmeticManager cosmeticManager;
public TokenGui(final CosmeticGui gui, final int tokenSlot, final int cosmeticSlot) {
this(gui.plugin, gui.title, gui.rows, gui.guiItemMap, tokenSlot, cosmeticSlot);
}
public TokenGui(final HMCCosmetics plugin, final String title, final int rows, final Map<Integer, GuiItem> guiItemMap, final int tokenSlot, final int cosmeticSlot) {
super(plugin, title, rows, guiItemMap);
this.tokenSlot = tokenSlot;
this.cosmeticSlot = cosmeticSlot;
this.cosmeticManager = this.plugin.getCosmeticManager();
}
@Override
public void open(final User user, final Player player) {
super.open(user, player);
this.gui.setDragAction(event -> event.setCancelled(true));
this.gui.setDefaultClickAction(event -> {
final int slot = event.getSlot();
final Inventory inventory = event.getClickedInventory();
if (inventory == null) {
event.setCancelled(true);
return;
}
final ClickType clickType = event.getClick();
if (clickType == ClickType.SHIFT_RIGHT || clickType == ClickType.SHIFT_LEFT) {
event.setCancelled(true);
return;
}
if (event.getClickedInventory().equals(event.getView().getBottomInventory())) return;
ItemStack tokenItem = event.getInventory().getItem(this.tokenSlot);
if (slot != tokenSlot && slot != this.cosmeticSlot) {
event.setCancelled(true);
if (tokenItem == null) {
inventory.setItem(this.cosmeticSlot, new ItemStack(Material.AIR));
}
return;
}
final ItemStack inHand = event.getCursor();
Token token;
if (slot == this.tokenSlot) {
if (inHand == null || inHand.getType() == Material.AIR) {
if (tokenItem != null && tokenItem.getAmount() > 1 && clickType == ClickType.RIGHT) return;
inventory.setItem(this.cosmeticSlot, new ItemStack(Material.AIR));
return;
}
token = this.cosmeticManager.getToken(inHand);
if (token == null) {
event.setCancelled(true);
return;
}
final ArmorItem item = token.getArmorItem();
inventory.setItem(this.cosmeticSlot,
this.applyPlaceholders(
user,
player,
item,
true
)
);
return;
}
if (inHand != null && inHand.getType() != Material.AIR) {
event.setCancelled(true);
return;
}
tokenItem = inventory.getItem(this.tokenSlot);
token = this.cosmeticManager.getToken(tokenItem);
if (tokenItem == null || token == null) {
event.setCancelled(true);
return;
}
final ItemStack clicked = event.getCurrentItem();
final ArmorItem armorItem = token.getArmorItem();
if (clicked == null) return;
if (user.hasPermissionToUse(armorItem)) {
this.messageHandler.sendMessage(
player,
Messages.ALREADY_UNLOCKED,
Map.of(Placeholder.ID, armorItem.getName())
);
event.setCancelled(true);
return;
}
tokenItem.setAmount(tokenItem.getAmount() - 1);
inventory.setItem(this.tokenSlot, tokenItem);
clicked.setAmount(0);
for (final String command : token.getCommands()) {
Bukkit.dispatchCommand(
Bukkit.getConsoleSender(),
command.replace(Placeholder.PLAYER, player.getName())
);
}
this.messageHandler.sendMessage(
player,
Messages.TRADED_TOKEN,
Map.of(Placeholder.ID, armorItem.getName())
);
});
this.gui.setCloseGuiAction(event -> {
final Inventory inventory = event.getInventory();
final ItemStack tokens = inventory.getItem(this.tokenSlot);
if (tokens == null) return;
event.getPlayer().getInventory().addItem(tokens);
user.setOpenGui(null);
});
}
@Override
public TokenGui copy() {
return new TokenGui(
this.plugin,
super.title,
super.rows,
new HashMap<>(super.guiItemMap),
this.tokenSlot,
this.cosmeticSlot
);
}
}

View File

@@ -0,0 +1,50 @@
package io.github.fisher2911.hmccosmetics.gui;
import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.GuiItem;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class WrappedGuiItem extends GuiItem {
private GuiAction<InventoryClickEvent> action;
public WrappedGuiItem(final GuiItem item, final GuiAction<InventoryClickEvent> action) {
super(item.getItemStack(), action);
this.action = action;
}
public WrappedGuiItem(final @NotNull ItemStack itemStack, @Nullable final GuiAction<@NotNull InventoryClickEvent> action) {
super(itemStack, action);
this.action = action;
}
public WrappedGuiItem(final @NotNull ItemStack itemStack) {
super(itemStack);
this.action = null;
}
public WrappedGuiItem(final @NotNull Material material) {
super(material);
this.action = null;
}
public WrappedGuiItem(final @NotNull Material material, @Nullable final GuiAction<@NotNull InventoryClickEvent> action) {
super(material, action);
this.action = action;
}
@Nullable
public GuiAction<InventoryClickEvent> getAction() {
return action;
}
@Override
public void setAction(final GuiAction<InventoryClickEvent> action) {
super.setAction(action);
this.action = action;
}
}

View File

@@ -0,0 +1,176 @@
package io.github.fisher2911.hmccosmetics.hook;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.concurrent.Threads;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.database.Database;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.task.InfiniteTask;
import io.github.fisher2911.hmccosmetics.user.NPCUser;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.event.*;
import net.citizensnpcs.api.npc.NPC;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class CitizensHook implements Hook, Listener {
private static final String IDENTIFIER = "citizens";
private final HMCCosmetics plugin;
private final Database database;
private final Map<Integer, NPCUser> npcs = new ConcurrentHashMap<>();
public CitizensHook(final HMCCosmetics plugin) {
this.plugin = plugin;
this.database = this.plugin.getDatabase();
final Settings settings = this.plugin.getSettings();
this.plugin.getTaskManager().submit(
new InfiniteTask(() -> {
for (final NPCUser user : this.npcs.values()) {
if (!user.isValid()) {
continue;
}
user.updateOutsideCosmetics(settings);
}
})
);
}
public List<Integer> getAllNPCS() {
final Iterator<NPC> iterator = CitizensAPI.getNPCRegistry().sorted().iterator();
final List<Integer> ids = new ArrayList<>();
while (iterator.hasNext()) {
ids.add(iterator.next().getId());
}
return ids;
}
public int getCitizensId(final Entity entity) {
final NPC npc = CitizensAPI.getNPCRegistry().getNPC(entity);
if (npc == null) return -1;
return npc.getId();
}
public boolean setNpcCosmetic(final int id, final ArmorItem armorItem) {
final NPC npc = CitizensAPI.getNPCRegistry().getById(id);
if (npc == null) return false;
final NPCUser user = this.npcs.get(npc.getId());
final Entity entity = npc.getEntity();
if (entity == null) return false;
if (user == null) {
Threads.getInstance().execute(() -> {
this.database.loadNPCUser(
npc.getId(),
entity,
npcUser ->
Bukkit.getScheduler().runTask(
this.plugin,
() -> {
this.npcs.put(npc.getId(), npcUser);
this.setNpcCosmetic(npcUser, armorItem);
}
)
);
});
return true;
}
return this.setNpcCosmetic(user, armorItem);
}
public boolean setNpcCosmetic(final NPCUser user, final ArmorItem armorItem) {
if (user == null) return false;
final NPC npc = this.getNPC(user.getId());
if (npc == null) return false;
if (!(npc.getEntity() instanceof final LivingEntity entity)) return false;
user.getPlayerArmor().setItem(armorItem);
final ArmorItem.Type type = armorItem.getType();
if (type != ArmorItem.Type.BACKPACK) {
entity.getEquipment().setItem(
type.getSlot(),
armorItem.getItemStack(ArmorItem.Status.APPLIED)
);
}
return true;
}
@Nullable
public NPC getNPC(final UUID uuid) {
return CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(uuid);
}
@Nullable
public NPC getNPC(final int id) {
return CitizensAPI.getNPCRegistry().getById(id);
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onNpcLoad(final PlayerCreateNPCEvent event) {
this.loadNpc(event.getNPC());
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onNpcLoad(final NPCSpawnEvent event) {
this.loadNpc(event.getNPC());
}
private void loadNpc(final NPC npc) {
if (Bukkit.getPlayer(npc.getUniqueId()) != null) return;
final Entity entity = npc.getEntity();
if (entity == null) return;
Bukkit.getScheduler().runTaskLater(this.plugin,
() -> Threads.getInstance().execute(() -> this.database.loadNPCUser(
npc.getId(),
entity,
user -> Bukkit.getScheduler().runTask(
this.plugin,
() -> {
this.npcs.put(npc.getId(), user);
for (final ArmorItem.Type type : ArmorItem.Type.values()) {
final ArmorItem armorItem = user.getPlayerArmor().getItem(type);
if (armorItem.isEmpty()) continue;
this.setNpcCosmetic(npc.getId(), armorItem);
}
}
)
)),
1);
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onNpcUnload(final NPCDespawnEvent event) {
this.unloadNpc(event.getNPC());
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onNpcUnload(final NPCRemoveEvent event) {
this.unloadNpc(event.getNPC());
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onNpcUnload(final NPCDeathEvent event) {
this.unloadNpc(event.getNPC());
}
private void unloadNpc(final NPC npc) {
final NPCUser user = this.npcs.remove(npc.getId());
if (user == null) return;
user.despawnAttached();
Threads.getInstance().execute(() -> this.database.saveNPCUser(user));
}
@Override
public String getId() {
return IDENTIFIER;
}
}

View File

@@ -10,7 +10,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import io.github.fisher2911.hmccosmetics.hook.item.PAPIExpansion;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginManager;
@@ -27,6 +26,8 @@ public class HookManager {
private final HMCCosmetics plugin;
private final ItemHooks itemHooks;
private final PAPIHook papiHook;
private final CitizensHook citizensHook;
private final ModelEngineHook modelEngineHook;
private final Set<Class<? extends Hook>> registeredHooks;
private final Set<Listener> listeners;
@@ -45,6 +46,7 @@ public class HookManager {
final Map<String, ItemHook> itemHookMap = new HashMap<>();
final OraxenHook oraxenHook = new OraxenHook();
final ItemsAdderHook itemsAdderHook = new ItemsAdderHook();
final CitizensHook citizensHook = new CitizensHook(this.plugin);
if (pluginManager.getPlugin("Oraxen") != null) {
itemHookMap.put(oraxenHook.getIdentifier(), oraxenHook);
}
@@ -52,6 +54,26 @@ public class HookManager {
itemHookMap.put(itemsAdderHook.getIdentifier(), itemsAdderHook);
this.listeners.add(itemsAdderHook);
}
if (pluginManager.getPlugin("Citizens") != null) {
this.citizensHook = null;
/*
this.registerHook(citizensHook.getClass());
this.listeners.add(citizensHook);
this.citizensHook = citizensHook;
this.plugin.getLogger().info("Successfully Hooked into Citizens!");
*/
} else {
this.citizensHook = null;
}
if (pluginManager.getPlugin("ModelEngine") != null) {
this.plugin.getLogger().info("ModelEngine has been detected and has been enabled.");
// 3.0 Model Engine Beta
final ModelEngineHook modelEngineHook = new ModelEngineHook();
this.registerHook(modelEngineHook.getClass());
this.modelEngineHook = modelEngineHook;
} else {
this.modelEngineHook = null;
}
this.itemHooks = new ItemHooks(itemHookMap);
itemHookMap.values().forEach(hook -> this.registerHook(hook.getClass()));
@@ -87,6 +109,16 @@ public class HookManager {
return papiHook;
}
@Nullable
public CitizensHook getCitizensHook() {
return this.citizensHook;
}
@Nullable
public ModelEngineHook getModelEngineHook() {
return modelEngineHook;
}
public ItemHooks getItemHooks() {
return itemHooks;
}

View File

@@ -0,0 +1,14 @@
package io.github.fisher2911.hmccosmetics.hook;
public class ModelEngineHook implements Hook {
public ModelEngineHook() {
}
private static final String ID = "model-engine";
@Override
public String getId() {
return ID;
}
}

View File

@@ -1,9 +1,7 @@
package io.github.fisher2911.hmccosmetics.hook.item;
package io.github.fisher2911.hmccosmetics.hook;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.api.CosmeticItem;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.message.Translation;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
@@ -12,9 +10,6 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class PAPIExpansion extends PlaceholderExpansion {
@@ -67,19 +62,32 @@ public class PAPIExpansion extends PlaceholderExpansion {
}
// %hmccosmetics_current_type%
if (parts[0].equals("current")) {
if (parts[0].startsWith("current")) {
final boolean formatted = parts[0].contains("formatted");
if (parts.length >= 2) {
final String typeStr = getId(parts, 1);
try {
final ArmorItem.Type type = ArmorItem.Type.valueOf(typeStr.toUpperCase());
for (final ArmorItem item : user.getPlayerArmor().getArmorItems()) {
if (item.getType().equals(type)) return item.getId();
if (item.getType().equals(type)) {
if (formatted) {
final String name = item.getName();
if (name.isBlank()) return item.getId().replace("_", "");
return name;
}
return item.getId();
}
}
return Translation.translate(Translation.NONE);
} catch (final IllegalArgumentException exception) {
return null;
}
}
return null;
}
if (parts[0].equals("wardrobe-enabled")) {
return Translation.translate(String.valueOf(user.getWardrobe().isActive()));
}
return null;

View File

@@ -0,0 +1,107 @@
package io.github.fisher2911.hmccosmetics.hook.entity;
import com.ticxo.modelengine.api.ModelEngineAPI;
import com.ticxo.modelengine.api.model.ActiveModel;
import com.ticxo.modelengine.api.model.ModeledEntity;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class BalloonEntity {
private final int balloonID;
private final MEGEntity megEntity;
public BalloonEntity(int balloonID, Location location) {
this.balloonID = balloonID;
this.megEntity = new MEGEntity(UUID.randomUUID(), balloonID, new Vector(0, 0, 0), location, false);
}
public void updateModel() {
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
if (model == null) return;
if (model.getBase() instanceof final MEGEntity e) e.update(this);
}
public void spawnModel(final String id) {
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().info("Attempting Spawning");
if (ModelEngineAPI.api.getModelRegistry().getBlueprint(id) == null) {
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().warning("Invalid Model Engine Blueprint " + id);
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().warning("Possible Blueprints" + ModelEngineAPI.api.getModelRegistry().getAllBlueprintId());
return;
}
final ActiveModel model = ModelEngineAPI.api.createActiveModelImpl(ModelEngineAPI.getBlueprint(id));
ModeledEntity modeledEntity = ModelEngineAPI.api.createModeledEntityImpl(megEntity);
modeledEntity.addModel(model, false);
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().info("Spawned Model");
}
public void remove() {
final ModeledEntity entity = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
if (entity == null) return;
for (final Player player : entity.getRangeManager().getPlayerInRange()) {
entity.hideFromPlayer(player);
}
//ModelEngineAPI.removeModeledEntity(megEntity.getUniqueId());
entity.destroy();
}
public void addPlayerToModel(final Player player, final String id) {
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
if (model == null) {
this.spawnModel(id);
return;
}
if (megEntity.getRangeManager().getPlayerInRange().contains(player)) return;
model.showToPlayer(player);
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().info("Added " + player.getName() + " to " + id);
}
public void removePlayerFromModel(final Player player) {
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
if (model == null) return;
model.hideFromPlayer(player);
}
public int getBalloonID() {
return balloonID;
}
public UUID getUniqueID() {
return megEntity.getUniqueId();
}
public Location getLocation() {
return this.megEntity.getLocation();
}
public boolean isAlive() {
return this.megEntity.isAlive();
}
public void setLocation(Location location) {
this.megEntity.setLocation(location);
}
public void setVelocity(Vector vector) {
this.megEntity.setVelocity(vector);
}
public void setAlive(boolean alive) {
this.megEntity.setAlive(alive);
}
}

View File

@@ -0,0 +1,242 @@
package io.github.fisher2911.hmccosmetics.hook.entity;
import com.ticxo.modelengine.api.entity.BaseEntity;
import com.ticxo.modelengine.api.generator.Hitbox;
import com.ticxo.modelengine.api.model.IModel;
import com.ticxo.modelengine.api.nms.entity.impl.DefaultBodyRotationController;
import com.ticxo.modelengine.api.nms.entity.impl.EmptyRangeManager;
import com.ticxo.modelengine.api.nms.entity.impl.ManualRangeManager;
import com.ticxo.modelengine.api.nms.entity.wrapper.BodyRotationController;
import com.ticxo.modelengine.api.nms.entity.wrapper.LookController;
import com.ticxo.modelengine.api.nms.entity.wrapper.MoveController;
import com.ticxo.modelengine.api.nms.entity.wrapper.RangeManager;
import com.ticxo.modelengine.api.nms.world.IDamageSource;
import com.ticxo.modelengine.api.utils.data.EntityData;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class MEGEntity implements BaseEntity {
private final UUID uuid;
private final int entityId;
private Vector velocity = new Vector(0, 0, 0);
private Location location;
private boolean alive;
private BodyRotationController rotationController;
private List<Entity> passengers;
private RangeManager rangeManager;
protected MEGEntity(final UUID uuid, final int entityId, final Vector velocity, final Location location, final boolean alive) {
this.uuid = uuid;
this.entityId = entityId;
this.velocity = velocity;
this.location = location;
this.alive = alive;
this.rotationController = new DefaultBodyRotationController(this);
this.passengers = new ArrayList<>();
this.rangeManager = new EmptyRangeManager();
this.rangeManager.setRenderDistance(16);
}
protected MEGEntity(final UUID uuid, final int entityId) {
this.uuid = uuid;
this.entityId = entityId;
this.alive = false;
}
public void update(final BalloonEntity entity) {
this.velocity = entity.getLocation().toVector();
this.location = entity.getLocation();
this.alive = entity.isAlive();
}
public void setVelocity(final Vector velocity) {
this.velocity = velocity;
}
public void setLocation(final Location location) {
this.location = location;
}
public void setAlive(final boolean alive) {
this.alive = alive;
}
public boolean isAlive() {
return alive;
}
public EntityData getEntityData() {
return entityData;
}
final EntityData entityData = new EntityData();
@Override
public Object getOriginal() {
return null;
}
@Override
public MoveController wrapMoveControl() {
return null;
}
@Override
public LookController wrapLookControl() {
return null;
}
@Override
public BodyRotationController wrapBodyRotationControl() {
return this.rotationController;
}
@Override
public void wrapNavigation() {
}
@Override
public RangeManager wrapRangeManager(IModel model) {
return new ManualRangeManager(this, model);
}
@Override
public RangeManager getRangeManager() {
if (this.rangeManager == null) {
RangeManager rangeMan = new EmptyRangeManager();
rangeMan.setRenderDistance(16);
return rangeMan;
}
return this.rangeManager;
}
@Override
public boolean onHurt(IDamageSource damageSource, float damage) {
return false;
}
@Override
public void onInteract(Player player, EquipmentSlot hand) {
}
@Override
public void setHitbox(Hitbox hitbox) {
}
@Override
public Hitbox getHitbox() {
return null;
}
@Override
public void setStepHeight(double height) {
}
@Override
public Double getStepHeight() {
return null;
}
@Override
public void setCollidableToLiving(LivingEntity living, boolean isRemove) {
}
@Override
public void broadcastSpawnPacket() {
}
@Override
public void broadcastDespawnPacket() {
}
@Override
public int getEntityId() {
return this.entityId;
}
@Override
public UUID getUniqueId() {
return this.uuid;
}
@Override
public Location getLocation() {
return location;
}
@Override
public World getWorld() {
return this.getWorld();
}
@Override
public boolean isDead() {
return alive;
}
@Override
public boolean isGlowing() {
return false;
}
@Override
public boolean isOnGround() {
return false;
}
@Override
public boolean isMoving() {
return false;
}
@Override
public void setYHeadRot(float rot) {
}
@Override
public float getYHeadRot() {
return 0;
}
@Override
public float getXHeadRot() {
return 0;
}
@Override
public void setYBodyRot(float rot) {
}
@Override
public float getYBodyRot() {
return 0;
}
@Override
public List<Entity> getPassengers() {
return this.passengers;
}
public Vector getVelocity() {
return velocity;
}
}

View File

@@ -1,6 +1,7 @@
package io.github.fisher2911.hmccosmetics.inventory;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashMap;
@@ -33,9 +34,9 @@ public class PlayerArmor {
return this.getItem(ArmorItem.Type.HAT);
}
public ArmorItem getBackpack() {
return this.getItem(ArmorItem.Type.BACKPACK);
}
// public ArmorItem getBackpack() {
// return this.getItem(ArmorItem.Type.BACKPACK);
// }
public ArmorItem getOffHand() {
return this.getItem(ArmorItem.Type.OFF_HAND);
@@ -51,6 +52,9 @@ public class PlayerArmor {
}
public ArmorItem setItem(final ArmorItem armorItem) {
if (armorItem.isEmpty() && armorItem.getType() == ArmorItem.Type.BACKPACK) {
this.armorItems.put(ArmorItem.Type.SELF_BACKPACK, armorItem);
}
return this.armorItems.put(armorItem.getType(), armorItem);
}

View File

@@ -1,53 +1,115 @@
package io.github.fisher2911.hmccosmetics.listener;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.user.Equipment;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import java.util.Optional;
import org.bukkit.Bukkit;
import org.bukkit.entity.HumanEntity;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.inventory.EquipmentSlot;
import java.util.*;
public class ClickListener implements Listener {
private final HMCCosmetics plugin;
private final UserManager userManager;
final Map<EquipmentSlot, Set<Material>> ARMOR_ITEMS = Map.of(
EquipmentSlot.HEAD, EnumSet.of(
Material.LEATHER_HELMET,
Material.CHAINMAIL_HELMET,
Material.IRON_HELMET,
Material.GOLDEN_HELMET,
Material.DIAMOND_HELMET,
Material.NETHERITE_HELMET,
Material.TURTLE_HELMET
),
EquipmentSlot.CHEST, EnumSet.of(
Material.LEATHER_CHESTPLATE,
Material.CHAINMAIL_CHESTPLATE,
Material.IRON_CHESTPLATE,
Material.GOLDEN_CHESTPLATE,
Material.DIAMOND_CHESTPLATE,
Material.NETHERITE_CHESTPLATE,
Material.ELYTRA
),
EquipmentSlot.LEGS, EnumSet.of(
Material.LEATHER_LEGGINGS,
Material.CHAINMAIL_LEGGINGS,
Material.IRON_LEGGINGS,
Material.GOLDEN_LEGGINGS,
Material.DIAMOND_LEGGINGS,
Material.NETHERITE_LEGGINGS
),
EquipmentSlot.FEET, EnumSet.of(
Material.LEATHER_BOOTS,
Material.CHAINMAIL_BOOTS,
Material.IRON_BOOTS,
Material.GOLDEN_BOOTS,
Material.DIAMOND_BOOTS,
Material.NETHERITE_BOOTS
)
);
public ClickListener(final HMCCosmetics plugin) {
this.plugin = plugin;
this.userManager = this.plugin.getUserManager();
}
/*
@EventHandler
public void onCosmeticClick(final InventoryClickEvent event) {
final HumanEntity player = event.getWhoClicked();
if (!(player instanceof Player)) {
return;
public void onArmorSlotClick(final InventoryClickEvent event) {
final int slot = event.getSlot();
if (!(event.getWhoClicked() instanceof Player)) return;
if (slot >= 36 && slot <= 40) {
this.fixInventory(((Player) event.getWhoClicked()).getPlayer());
}
this.fixInventory((Player) player);
}
@EventHandler
public void onCosmeticClick(final InventoryDragEvent event) {
final HumanEntity player = event.getWhoClicked();
if (!(player instanceof Player)) {
return;
}
this.fixInventory((Player) player);
}
@EventHandler
public void onInventoryClose(final InventoryCloseEvent event) {
final HumanEntity player = event.getPlayer();
this.userManager.get(player.getUniqueId()).ifPresent(this::doRunnable);
}
*/
//
// @EventHandler
// public void onBlockClick(final PlayerInteractEvent event) {
// if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
// final Player player = event.getPlayer();
// final Block block = event.getClickedBlock();
// if (block != null && block.getType().isInteractable() && !player.isSneaking()) return;
// final ItemStack clickedWith = event.getItem();
// if (clickedWith == null) return;
// this.checkFix(player, -1, clickedWith);
// }
//
// @EventHandler
// public void onShiftClick(final InventoryClickEvent event) {
// if (event.getClick() != ClickType.SHIFT_LEFT &&
// event.getClick() != ClickType.SHIFT_RIGHT) return;
// if (!(event.getWhoClicked() instanceof final Player player)) return;
// final ItemStack clicked = event.getCurrentItem();
// if (clicked == null) return;
// this.checkFix(player, -1, clicked);
// }
//
// @EventHandler
// public void onCosmeticClick(final InventoryDragEvent event) {
// final HumanEntity player = event.getWhoClicked();
// if (!(player instanceof Player)) {
// return;
// }
//// this.fixInventory((Player) player);
// }
//
// @EventHandler
// public void onInventoryClose(final InventoryCloseEvent event) {
// final HumanEntity player = event.getPlayer();
// this.userManager.get(player.getUniqueId()).ifPresent(this::doRunnable);
// }
//
/*
private void fixInventory(final Player player) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
@@ -59,9 +121,31 @@ public class ClickListener implements Listener {
}
private void doRunnable(final User user) {
Equipment equip = this.userManager.getItemList(user, user.getEquipment(), Collections.emptySet());
Bukkit.getScheduler().runTaskLaterAsynchronously(
this.plugin, () -> this.userManager.updateCosmetics(user),
this.plugin, () -> this.userManager.sendUpdatePacket(user, equip),
1);
}
*/
// private void checkFix(final Player player, final int clickedSlot, final ItemStack itemStack) {
// final EquipmentSlot slot = this.getArmorSlot(itemStack.getType());
// if (slot == null) return;
// final ItemStack wearing = player.getEquipment().getItem(slot);
// if (wearing == null) return;
// if (wearing.getType() == Material.AIR || (clickedSlot >= 39 && clickedSlot <= 40)) {
// this.fixInventory(player);
// }
// }
//
// @Nullable
// private EquipmentSlot getArmorSlot(final Material material) {
// for (final EquipmentSlot slot : EquipmentSlot.values()) {
// final Set<Material> armorItems = ARMOR_ITEMS.get(slot);
// if (armorItems == null) continue;
// if (material == null) continue;
// if (armorItems.contains(material)) return slot;
// }
// return null;
// }
}

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