Compare commits

..

228 Commits
5.7.1 ... 6.4.0

Author SHA1 Message Date
Auxilor
ebc76bba76 Changed display 2021-08-12 16:30:15 +01:00
Auxilor
378218b7da Minor display change 2021-08-12 16:13:59 +01:00
Auxilor
e053514b94 Added mask materials option 2021-08-12 13:56:29 +01:00
Auxilor
341a30e6da Removed unused var 2021-08-12 13:40:19 +01:00
Auxilor
70eb6d4420 Removed logging 2021-08-12 13:40:01 +01:00
Auxilor
aa368909ae Finished GUI 2021-08-12 13:38:14 +01:00
Auxilor
606a54bcf8 Your brain gets smart but your head gets dumb 2021-08-12 13:17:52 +01:00
Auxilor
7f8fb3d87b Didn't make sense not to live for fun 2021-08-12 13:00:31 +01:00
Auxilor
e97d454ff6 Fed to the rules and I hit the ground running 2021-08-12 01:51:47 +01:00
Auxilor
109b9aa3f3 And the changes start coming and they don't stop coming 2021-08-12 01:46:32 +01:00
Auxilor
4a90385b27 The gui changes don't stop 2021-08-12 01:38:20 +01:00
Auxilor
0edd50832c Even more GUI 2021-08-12 01:05:47 +01:00
Auxilor
46415268b7 More GUI 2021-08-12 00:24:35 +01:00
Auxilor
b652dbad2d Added captivator slots 2021-08-11 23:56:09 +01:00
Auxilor
50550d077a Added ? syntax to recipes 2021-08-11 23:07:25 +01:00
Auxilor
60c3b58a33 Updated to 6.3.3 2021-08-10 18:19:46 +01:00
Auxilor
7216d0b09f Fixed component serialization 2021-08-10 18:18:09 +01:00
Auxilor
97eeea8d48 Updated to 6.3.2 2021-08-10 16:18:49 +01:00
Auxilor
82061ee6a3 Added get/set repair cost methods to FastItemStack 2021-08-09 17:30:09 +01:00
Auxilor
f274b9045e Being absolutely sure 2021-08-07 23:17:39 +01:00
Auxilor
2241a5c90f I'm actually going to die 2021-08-07 23:16:59 +01:00
Auxilor
bbc38ae801 Frantic-est fixing 2021-08-07 23:08:12 +01:00
Auxilor
e77346ed62 Even frantic-er fixing 2021-08-07 23:07:06 +01:00
Auxilor
6117abca56 Frantic fixing 2021-08-07 23:00:23 +01:00
Auxilor
2e2a061ebe Updated to 6.3.1 2021-08-07 22:11:08 +01:00
Auxilor
cdc89ac397 Fixed FastItemStack 2021-08-07 22:10:54 +01:00
Auxilor
e758cebe77 Fixed FastItemStack bug 2021-08-07 22:09:50 +01:00
Auxilor
a408e3436a Fixed italic lore 2021-08-07 15:44:16 +01:00
Auxilor
3df977c1bc Fixed FastItemStack#setLore being italicised 2021-08-07 15:10:54 +01:00
Auxilor
136f1841b4 Fixed FastItemStack#setLore being italicised 2021-08-07 15:07:29 +01:00
Auxilor
1086a59a6a Added message about deprecated events 2021-08-07 14:02:52 +01:00
Auxilor
d9147f9918 Changed bStats message 2021-08-07 13:44:21 +01:00
Auxilor
d144df4048 Fixed proxy interface package 2021-08-07 13:33:58 +01:00
Auxilor
061f77e911 Fixed 1.16 proxy package 2021-08-07 13:32:44 +01:00
Auxilor
5cebe2fce8 Moved metric handler 2021-08-07 13:27:12 +01:00
Auxilor
1e712dcae6 Skull.kt now uses lateinit var 2021-08-07 13:24:36 +01:00
Auxilor
09d444da58 Added format cache to yaml configs 2021-08-07 13:18:36 +01:00
Auxilor
09f45c0ab5 Cleaned up FastItemStack 2021-08-07 13:11:09 +01:00
Auxilor
f64d69f084 Switched proxy interfaces to kotlin 2021-08-07 13:02:44 +01:00
Auxilor
86a948738f Moved EcoProxyFactory to kotlin, removing java from eco-backend 2021-08-07 02:29:36 +01:00
Auxilor
8f9c5e7ed8 Moved most 1.16.5 proxies off to kotlin 2021-08-06 23:27:30 +01:00
Auxilor
ae897b7493 Moved most 1.17 proxies to kotlin 2021-08-06 23:22:32 +01:00
Auxilor
f1a7c9d50e Moved FastItemStackUtils to companion object 2021-08-06 23:16:53 +01:00
Auxilor
83ee8fe4cd Fixed 1.17 mapping bug with kotlin 2021-08-06 23:14:25 +01:00
Auxilor
465f885e22 Fixed kotlin bugs 2021-08-06 23:09:47 +01:00
Auxilor
d4141735a9 Moved 1_17_R1 NMSFastItemStack to kotlin for testing reasons 2021-08-06 22:47:26 +01:00
Auxilor
b9b4ce1937 Fixed NumberUtils 2021-08-06 22:31:51 +01:00
Auxilor
56234e6c83 Added tests for NumberUtilsTest 2021-08-06 22:22:18 +01:00
Auxilor
2dda34097e Fixed .gitignore 2021-08-06 22:02:34 +01:00
Auxilor
155a349569 Removed saveAllConfigs on disable 2021-08-06 22:00:04 +01:00
Auxilor
ce231934a3 Fixed DropManager.kt 2021-08-06 21:53:19 +01:00
Auxilor
5cbb7bfe47 Added warnings to servers without bStats 2021-08-06 21:49:12 +01:00
Auxilor
06e0ec0295 Updated bStats 2021-08-06 21:30:29 +01:00
Auxilor
02ed583674 Updated gitignore 2021-08-06 20:21:36 +01:00
Auxilor
8e4cbdd1aa Kotlin cleaning 2021-08-06 20:20:50 +01:00
Auxilor
8828f8e45d Moved EcoConfigHandler to kotlin 2021-08-06 20:05:57 +01:00
Auxilor
d15524ee9e Moved extension loader to kotlin 2021-08-06 19:57:38 +01:00
Auxilor
d45e66d71e Kotlin cleanup 2021-08-06 19:43:48 +01:00
Auxilor
6b1dde7540 Removed lombok from kotlin 2021-08-06 17:40:00 +01:00
Auxilor
abf2964c48 Fixed kotlin class names 2021-08-06 17:37:49 +01:00
Auxilor
db51c4c761 Moved integrations to kotlin 2021-08-06 17:28:21 +01:00
Auxilor
cbb574acec Switched most event listeners to kotlin 2021-08-06 17:25:34 +01:00
Auxilor
93c044ef09 Fixed kotlin errors and warnings 2021-08-06 16:46:48 +01:00
Auxilor
1cc39fe40a Fixed EcoMenuBuilder.kt 2021-08-06 16:45:10 +01:00
Auxilor
edfd561fcd EcoMenu error fix 2021-08-06 16:41:29 +01:00
Auxilor
bd7f22cb02 Fixed kotlin errors 2021-08-06 16:40:47 +01:00
Auxilor
3233bad307 More backend kotlinining 2021-08-06 16:38:12 +01:00
Auxilor
3cefcbe0bb Switched most internals to kotlin 2021-08-06 16:15:29 +01:00
Auxilor
49bce53724 Rename .java to .kt 2021-08-06 16:15:29 +01:00
Auxilor
2b86159b30 Fixed handler 2021-08-06 03:15:50 +01:00
Auxilor
d028511a48 Fixed kotlin being shaded 2021-08-06 03:14:43 +01:00
Auxilor
5ad1ef33b8 Kotlining 2021-08-06 03:10:00 +01:00
Auxilor
634d6194d6 Began kotlin 2021-08-06 03:08:00 +01:00
Auxilor
7f7eb4f45a Fixed trailing spaces 2021-08-05 00:43:18 +01:00
Auxilor
bd90ae996b Fixed deprecation warnings 2021-08-04 17:52:09 +01:00
Auxilor
1bc57dec08 Fixed annotations 2021-08-04 15:22:52 +01:00
Auxilor
ce44d40f0f Reverted BlockUtils 2021-08-04 14:53:16 +01:00
Auxilor
68824fb4d0 Updated gradient regexes 2021-08-04 14:38:18 +01:00
Auxilor
fd96b0d2cf Fixed HAS_VAULT 2021-08-04 14:36:24 +01:00
Auxilor
2669569e81 Removed vault and loadbefore 2021-08-04 14:36:10 +01:00
Auxilor
067f740bcc Improved ArmorEquipEvent javadoc 2021-08-04 14:29:17 +01:00
Auxilor
2ce96ab0b1 Added FastItemStack#unwrap again 2021-08-04 14:27:45 +01:00
Auxilor
027f9be194 Definitely not code smells 2021-08-04 00:25:07 +01:00
Auxilor
a09018d1f0 Added vault and Prerequisite#HAS_VAULT 2021-08-03 23:55:13 +01:00
Auxilor
a1da83173d Deprecated ArmorEquipEvent 2021-08-03 23:43:17 +01:00
Auxilor
8ac30283f8 Deprecated ArmorEquipEvent 2021-08-03 23:42:58 +01:00
Auxilor
6099b5d64d Removed javadoc for private methods 2021-08-03 23:35:53 +01:00
Auxilor
19d2e0788b Added PlaceholderEntry#register 2021-08-03 23:34:39 +01:00
Auxilor
1b223b3736 Added null safety to Customitem 2021-08-03 23:30:31 +01:00
Auxilor
d6d1f01704 FastItemStack refactoring 2021-08-03 20:47:01 +01:00
Auxilor
51231939c0 Added <gradient:#> support 2021-08-03 19:59:21 +01:00
Auxilor
72fb20ecd9 Switched to adventure for legacy / json conversions 2021-08-03 19:57:52 +01:00
Auxilor
58a386922c Removed FastItemStack benchmarks 2021-08-03 19:19:06 +01:00
Auxilor
12824c7f6c FastItemStack cache changes 2021-08-03 19:10:22 +01:00
Auxilor
b5236b8db6 More FastItemStack 2021-08-03 18:54:45 +01:00
Auxilor
3ffbb861d1 More FastItemStack changes 2021-08-03 17:00:49 +01:00
Auxilor
f8fad15f0b More FastItemStack changes 2021-08-03 16:48:13 +01:00
Auxilor
a0e96fca35 Fixed typo 2021-08-03 16:21:19 +01:00
Auxilor
6cf9a53a65 Continued FastItemStack development 2021-08-03 16:20:05 +01:00
Auxilor
a4909453d7 Codestyle 2021-08-01 23:39:04 +01:00
Auxilor
a10666f792 Renamed to EcoFastItemStack 2021-08-01 23:38:42 +01:00
Auxilor
a845cda9ed Fixed mapped jar output issues 2021-08-01 23:18:06 +01:00
Auxilor
ed5f1ccb5e Switched to 1.17 mojang mappings and began FastItemStack 2021-08-01 22:09:18 +01:00
Auxilor
c6e59e1d62 Updated to 6.3.0 2021-08-01 19:16:43 +01:00
Auxilor
ed24b6278e Began FastItemStack shti 2021-08-01 19:16:33 +01:00
Auxilor
3aea7b4077 Fixed CombatLogX codestyle 2021-08-01 17:00:04 +01:00
Auxilor
f53c29cd56 Updated to 6.2.1 2021-07-31 16:59:46 +01:00
Auxilor
6845152a09 Fixed extension classloader bug with unclosed classloaders 2021-07-31 16:59:33 +01:00
Auxilor
7eaf2dc8ed Fixed Javadoc 2021-07-27 19:02:04 +01:00
Auxilor
310485402f Updated to 6.2.0 2021-07-27 19:01:08 +01:00
Auxilor
727dc25083 Added ArmorChangeEvent 2021-07-27 19:00:50 +01:00
Auxilor
364f36d502 Added player option to display, added setters to commands 2021-07-27 18:48:10 +01:00
Auxilor
b6086bc4bd JSON config changes 2021-07-27 18:36:51 +01:00
Auxilor
dd3beaa548 Added dynamic world height check 2021-07-27 18:34:23 +01:00
Auxilor
c36c0c247f Fixed enchant support in crafting recipes 2021-07-26 19:02:11 +01:00
Auxilor
6611a0f82c Fixed missing javadoc 2021-07-26 18:39:18 +01:00
Auxilor
625b981b81 Added support for enchantments in recipes 2021-07-26 18:38:12 +01:00
Auxilor
d8607917a1 Updated to 6.1.0 2021-07-26 18:26:13 +01:00
Auxilor
30d5f54459 Added EcoPlugin#reloadWithTime 2021-07-26 18:25:56 +01:00
Auxilor
a59c05174f Fixed bug with unloaded plugins 2021-07-26 18:21:52 +01:00
Auxilor
cf01abcf87 Added out of world check to blocks 2021-07-26 18:20:13 +01:00
Auxilor
70a4a06d4f Updated to 6.0.6 2021-07-24 01:12:55 +01:00
Auxilor
bbee18fd8a JSON config files now have same deletion behaviour as yaml config files 2021-07-24 01:12:46 +01:00
Auxilor
26ab9a327d Added warnings to invalid extensions 2021-07-23 22:14:14 +01:00
Auxilor
0676f5fa33 Updated to 6.0.5 2021-07-23 22:11:41 +01:00
Auxilor
051b95ad88 Extension loading change 2021-07-23 22:11:32 +01:00
Auxilor
d786014cbc Updated to 6.0.4 2021-07-22 18:40:17 +01:00
Auxilor
b62bb48bb6 Fixed loadable config reloading 2021-07-22 18:39:59 +01:00
Auxilor
b238a10209 Fixed EcoUpdatableYamlConfig not automatically registering itsefl 2021-07-22 18:34:00 +01:00
Auxilor
251049f1f1 Updated to 6.0.3 2021-07-22 16:42:00 +01:00
Auxilor
16d146dba0 Fixed ArrowUtils 2021-07-22 16:41:43 +01:00
Auxilor
214308da10 Updated to 6.0.2 2021-07-21 21:46:12 +01:00
Auxilor
2c12f78aa6 Fixed 'Menu not instance of EcoMenu!' bug 2021-07-21 21:45:59 +01:00
Auxilor
800e83d24b Merge remote-tracking branch 'origin/master' 2021-07-21 20:37:38 +01:00
Auxilor
0a1ee0679c Updated to 6.0.1 2021-07-21 20:37:20 +01:00
Auxilor
898230040a Fixed DropQueue Stack Overflow 2021-07-21 20:37:09 +01:00
Auxilor
6f01577165 Update README.md 2021-07-21 19:07:49 +01:00
Auxilor
1c8c95f292 Update README.md 2021-07-21 19:07:31 +01:00
Auxilor
8cda5be2f0 Renamed 2 configs 2021-07-21 18:47:25 +01:00
Auxilor
850bf5d642 More readme changes 2021-07-21 18:09:48 +01:00
Auxilor
af197db70a More readme changes 2021-07-21 18:08:29 +01:00
Auxilor
c11fedff4e Added dedimc banner to readme 2021-07-21 18:04:03 +01:00
Auxilor
4001af9b8c Optimised Imports 2021-07-21 18:00:25 +01:00
Auxilor
69a8acf39a README change 2021-07-21 17:57:39 +01:00
Auxilor
7247b95cbe Fixed license link 2021-07-21 17:57:39 +01:00
Auxilor
4b5657de91 Changes 2021-07-21 17:57:39 +01:00
Auxilor
11ab52be94 Removed unneeded TridentUtils (added to spigot officially in 1.16.5) 2021-07-21 17:57:39 +01:00
Auxilor
d47757cca4 Backend formatting change 2021-07-21 17:57:39 +01:00
Auxilor
411753859c Removed old packet methods 2021-07-21 17:57:39 +01:00
Auxilor
bb188e5812 Minor Javadoc changes 2021-07-21 17:57:39 +01:00
Auxilor
a1a477e7df Updated to 6.0.0 2021-07-21 17:57:39 +01:00
Auxilor
3144c3a954 Even more Javadoc 2021-07-21 17:57:39 +01:00
Auxilor
75412b98a4 More Javadoc 2021-07-21 17:57:39 +01:00
Auxilor
3f7f1946dc API build.gradle changes 2021-07-21 17:57:39 +01:00
Auxilor
d40fa7983d Added lots of API javadoc 2021-07-21 17:57:39 +01:00
Auxilor
c7a7a8c48a Changed oraxen dependency 2021-07-21 17:57:39 +01:00
Auxilor
cfd5cc4be2 More jitpack changes 2021-07-21 17:57:39 +01:00
Auxilor
c1e36eb2bc jitpack.yml changes 2021-07-21 17:57:39 +01:00
Auxilor
d6d6da520a jitpack.yml changes 2021-07-21 17:57:39 +01:00
Auxilor
b2fd23b13a Test changes 2021-07-21 17:57:39 +01:00
Auxilor
d6e4346e4f jitpack.yml change 2021-07-21 17:57:39 +01:00
Auxilor
b4e5735c51 Automation changes 2021-07-21 17:57:39 +01:00
Auxilor
ba8f861901 Pastegg exclusion 2021-07-21 17:57:39 +01:00
Auxilor
a40415a76f Moved maven artifact to spigot library 2021-07-21 17:57:39 +01:00
Auxilor
d85a7a4503 Updated to 6.0.0-pre1 2021-07-21 17:57:39 +01:00
Auxilor
cab3cb9a9f Added github actions 2021-07-21 17:57:39 +01:00
Auxilor
9fb106c4de Removed more javadoc from internals 2021-07-21 17:57:39 +01:00
Auxilor
cce8e46634 Removed more javadoc from internals 2021-07-21 17:57:39 +01:00
Auxilor
bb595e340c Fixed missing whitespace 2021-07-21 17:57:39 +01:00
Auxilor
b40c3a41c2 Renamed StringUtils.translate to StringUtils.format 2021-07-21 17:57:39 +01:00
Auxilor
226ad14ede Custom items are now actually registered 2021-07-21 17:57:39 +01:00
Auxilor
eadbb489a7 Added more config methods 2021-07-21 17:57:39 +01:00
Auxilor
fb900a18ad Added oraxen support 2021-07-21 17:57:39 +01:00
Auxilor
395a5e1745 Added back EcoPlugin#getProxyFactory 2021-07-21 17:57:39 +01:00
Auxilor
eeffa33918 Removed broken jitpack.yml 2021-07-21 17:57:39 +01:00
Auxilor
617a91c41c More jitpack.yml chagnes 2021-07-21 17:57:39 +01:00
Auxilor
fbfe11d275 More jitpack.yml chagnes 2021-07-21 17:57:39 +01:00
Auxilor
a4e31ff5ca Tweaked jitpack.yml 2021-07-21 17:57:39 +01:00
Auxilor
bf85785451 Added jitpack.yml 2021-07-21 17:57:39 +01:00
Auxilor
d830672795 Added Items#getCustomItems 2021-07-21 17:57:39 +01:00
Auxilor
255bb4b38e Removed bad localization system 2021-07-21 17:57:39 +01:00
Auxilor
d73c665d20 Removed loadUpdatableClasses 2021-07-21 17:57:39 +01:00
Auxilor
39b95c7a34 Changed EcoPlugin#getProxyFactory#getProxy to EcoPlugin#getProxy 2021-07-21 17:57:39 +01:00
Auxilor
bbcbc7f88b Fixed CONTRIBUTING.md 2021-07-21 17:57:39 +01:00
Auxilor
4787d0f389 Fixed CONTRIBUTING.md 2021-07-21 17:57:39 +01:00
Auxilor
641d479c6d Dropped support for 1.16-1.16.4 (1.16.5 is still supported) 2021-07-21 17:57:39 +01:00
Auxilor
a521a9c93a Fixed reflections 2021-07-21 17:57:39 +01:00
Auxilor
51f690c9cb Removed the need to register updatable classes - added reflections 2021-07-21 17:57:39 +01:00
Auxilor
a451732c1e Added suppliers to EnchantedBook, LeatherArmor, and Skull builders 2021-07-21 17:57:39 +01:00
Auxilor
d6d0e4d3b3 Fixed 2 backend issues 2021-07-21 17:57:39 +01:00
Auxilor
e6bdf192ed Removed bad javadoc 2021-07-21 17:57:39 +01:00
Auxilor
eccd4b4a6f Removed the redundant never-used persistent data storage system - it's not needed as 1.14+ has it's own API's 2021-07-21 17:57:39 +01:00
Auxilor
8650e9bb2a Added javadoc to Eco#getHandler 2021-07-21 17:57:39 +01:00
Auxilor
8e5392084d Cleaned up PacketOpenWindowMerchant 2021-07-21 17:57:39 +01:00
Auxilor
5c39a557f2 Added NamespacedKeyUtils#create 2021-07-21 17:57:39 +01:00
Auxilor
75d13fafc1 Applied a thin coat of polish 2021-07-21 17:57:39 +01:00
Auxilor
c674518eb8 Improved ConfigWrapper#getHandle documentation 2021-07-21 17:57:39 +01:00
Auxilor
23e18cd0dd Minor paste changes 2021-07-21 17:57:39 +01:00
Auxilor
2644495bca Proxy Refactoring 2021-07-21 17:57:39 +01:00
Auxilor
130094a16e Changes + Documentation 2021-07-21 17:57:39 +01:00
Auxilor
6c4bb2e6e8 Fixed poorly named methods 2021-07-21 17:57:39 +01:00
Auxilor
c56d5d38c3 EcoPlugin method renames 2021-07-21 17:57:39 +01:00
Auxilor
f0d44ccf02 Fixed gradient strikethrough 2021-07-21 17:57:39 +01:00
Auxilor
83f9c27238 Added use-fast-collated-drops to eco config.yml 2021-07-21 17:57:39 +01:00
Auxilor
083f643ce2 Localization changes 2021-07-21 17:57:39 +01:00
Auxilor
76e808b8b1 Packet changes 2021-07-21 17:57:39 +01:00
Auxilor
beca53ca6a Removed reference to non-existent plugin 2021-07-21 17:57:39 +01:00
Auxilor
028c7c76da Miscellaneous changes 2021-07-21 17:57:39 +01:00
Auxilor
0e02e8f6db Changed getNearbyBlocks decrement size from 2500 to 1024 to allow for a smaller memory overhead 2021-07-21 17:57:39 +01:00
Auxilor
94984d993b Proxy and BlockUtils rework 2021-07-21 17:57:39 +01:00
Auxilor
741208d20c Fixed proxy errors 2021-07-21 17:57:39 +01:00
Auxilor
b92c55d3e7 Proxy changes (hopefully working classloader magic to allow for EcoPlugin#getProxyFactory#getProxy and plugin class loading) 2021-07-21 17:57:39 +01:00
Auxilor
b60fc49fd5 Tweaked PlayerJumpEvent 2021-07-21 17:57:39 +01:00
Auxilor
9fc5b78fa0 The config changes dont end 2021-07-21 17:57:39 +01:00
Auxilor
91ba7cc475 Even more config reworking 2021-07-21 17:57:39 +01:00
Auxilor
45fc05ca49 Refactored GUI 2021-07-21 17:57:39 +01:00
Auxilor
610081dab4 Removed deprecated methods and classes 2021-07-21 17:57:39 +01:00
Auxilor
22c62e45be Updated to eco 6.0.0 and continued config changes 2021-07-21 17:57:39 +01:00
Auxilor
119b5742fb Continued config changes 2021-07-21 17:57:39 +01:00
Auxilor
c143006c4b Minor refactoring 2021-07-21 17:57:39 +01:00
Auxilor
f88c9b7d42 More config changes 2021-07-21 17:57:39 +01:00
Auxilor
775c562705 Added Config#clone and JSONConfig#clone 2021-07-21 17:57:39 +01:00
Auxilor
9b443f25cc Config and GUI changes 2021-07-21 17:57:39 +01:00
Auxilor
ddeaa5c79c Refactoring 2021-07-21 17:57:39 +01:00
Auxilor
78093531f7 Fixed CombatLogX PR codestyle 2021-07-21 17:57:39 +01:00
Auxilor
5ec293e9c9 Refactored internals into core-backend from core-spigot 2021-07-21 17:57:39 +01:00
Auxilor
d846f348ac Continued refactor 2021-07-21 17:57:39 +01:00
Auxilor
30ce422349 Removed com.willfp.eco.internal from API module 2021-07-21 17:57:39 +01:00
341 changed files with 7781 additions and 6468 deletions

38
.github/workflows/publish-release.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: Publish release
on:
release:
types: [published]
jobs:
publish-release:
runs-on: ubuntu-latest
steps:
- name: Checkout latest code
uses: actions/checkout@v2
- name: Set up JDK 16
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: 16
- name: Setup build cache
uses: actions/cache@v2.1.6
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Publish artifact
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# The GITHUB_REF tag comes in the format 'refs/tags/xxx'.
# So if we split on '/' and take the 3rd value, we can get the release name.
run: |
NEW_VERSION=$(echo "${GITHUB_REF}" | cut -d "/" -f3)
echo "New version: ${NEW_VERSION}"
echo "Github username: ${GITHUB_ACTOR}"
./gradlew -Pversion=${NEW_VERSION} publish

1
.gitignore vendored
View File

@@ -14,6 +14,7 @@ bin/
# Gradle
.gradle
**/build/
**/out/
!eco-api/src/**/build/
.gradletasknamecache
!gradle-wrapper.jar

View File

@@ -6,7 +6,7 @@
- Every method and field must have a javadoc attached.
2. Use lombok wherever possible.
- @Getter, @Setter, @ToString, @EqualsAndHashCode, @UtilityClass are the most important.
- @Getter, @Setter, @UtilityClass only.
3. Use JetBrains annotations
- Every parameter should be annotated with @NotNull or @Nullable
@@ -24,4 +24,4 @@
## Other
- All drops **must** be sent through a DropQueue - calls to World#dropItem will get your PR rejected.
- eco is built with java 8. Usage of J9+ will get your PR rejected.
- eco is built with java 16.

166
README.md
View File

@@ -1 +1,165 @@
## eco - Library for spigot plugin development.
<h1 align="center">
<br>
<img src="https://i.imgur.com/p5uR2Qp.png" alt="eco logo" width="256">
<br>
</h1>
<h4 align="center">eco - Simplify spigot development.</h4>
### Plugin Information
- Requires ProtocolLib to be installed: get the latest version [here](https://www.spigotmc.org/resources/protocollib.1997/)
- Supports 1.16.5+
### bStats
<img src="https://bstats.org/signatures/bukkit/eco.svg" width="512">
# Information for development
## Javadoc
The 6.0.0 Javadoc can be found [here](https://javadoc.jitpack.io/com/willfp/eco/6.0.0/javadoc/)
## Plugin Information
eco is a standalone plugin, so you will need to install it on any servers that have plugins which depend on it,
and specify it as a dependency in your plugin.yml:
```yaml
depend:
- eco
```
eco is available from any of these places:
- [GitHub](https://github.com/Auxilor/eco/releases)
- [Spigot](https://www.spigotmc.org/resources/eco.87955/)
- [Polymart](https://polymart.org/resource/eco.773)
- [Build it locally](https://github.com/Auxilor/eco#build-locally).
## Get from JitPack:
Gradle:
```groovy
repositories {
maven { url 'https://jitpack.io' }
}
```
```groovy
dependencies {
compileOnly 'com.willfp:eco:Tag'
}
```
Replace `Tag` with a release tag for eco, eg `6.0.0`.
Maven:
```xml
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
```
```xml
<dependency>
<groupId>com.willfp</groupId>
<artifactId>eco</artifactId>
<version>Tag</version>
<scope>provided</scope>
</dependency>
```
Replace `Tag` with a release tag for eco, eg `6.0.0`.
## Build locally:
Run the following commands in your terminal of choice.
If you're on windows, you will need to have git bash installed.
```
git clone https://github.com/Auxilor/eco
cd eco
./gradlew build
```
# Features
Here's a list of some (not all) of the features of eco:
- Command system with subcommands
- Reworked config system
- JSON Config Support
- Client-Side item display
- World drop system
- Event manager
- PlayerJumpEvent
- ArmorEquipEvent
- EntityDeathByEntityEvent
- NaturalExpGainEvent
- Plugin extensions (com.willfp.eco.internal.Plugins for plugins)
- GUI System
- Integration system for external plugins
- Anticheat support
- AAC
- Matrix
- NCP
- Spartan
- Vulcan
- Antigrief/Combat support
- CombatLogX (V10 + V11)
- FactionsUUID
- GriefPrevention
- Kingdoms
- Lands
- Towny
- WorldGuard
- mcMMO support
- Custom Items support
- Oraxen
- PlaceholderAPI support
- NMS Proxy / Wrapper system built in
- Custom Items system
- Crafting Recipe handler
- Tuples
- Support uploading to / downloading from hastebin
- Packet System (via ProtocolLib)
- Dependency Injection systems
- Prerequisite system
- API additions (via utility classes)
- Get bow from arrow
- Break a block as a player
- Get a vein of blocks
- Create 2D lists
- Create NamespacedKeys safely
- Random number, distribution, roman numerals
- Set skull texture
- Format all strings
- Hex Support
- Gradient Support
- Placeholder Support
- Get a scoreboard team from any color
- Telekinesis (Drops straight to inventory) system
- More vector options
- Update checker
- bStats integration
- Reworked systems for:
- NamespacedKey
- MetadataValue
- Runnables / Scheduling
... and a lot more!
## License
*Click here to read [the entire license](https://github.com/Auxilor/eco/blob/master/LICENSE.md).*
<h1 align="center">
<br>
<a href="https://dedimc.promo/Auxilor" target="_blank">
<img src="https://i.imgur.com/zdDLhFA.png" alt="dedimc banner">
</a>
<br>
</h1>

View File

@@ -7,7 +7,11 @@ plugins {
dependencies {
implementation project(":eco-api")
implementation project(":eco-core").getSubprojects()
implementation project(":eco-core:core-plugin")
implementation project(":eco-core:core-proxy")
implementation project(":eco-core:core-backend")
implementation project(":eco-core:core-nms:v1_16_R3")
implementation project(path: ":eco-core:core-nms:v1_17_R1", configuration: 'mapped')
}
allprojects {
@@ -57,6 +61,10 @@ allprojects {
annotationProcessor 'org.projectlombok:lombok:1.18.20'
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
// Test
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1'
}
tasks.withType(JavaCompile) {
@@ -68,14 +76,14 @@ allprojects {
exclude group: "org.codehaus.plexus", module: "plexus-utils"
exclude group: "com.mojang", module: "brigadier"
exclude group: "org.kitteh", module: "paste-gg-api"
exclude group: "org.kitteh", module: "pastegg"
exclude group: "org.spongepowered", module: "configurate-hocon"
exclude group: "com.darkblade12", module: "particleeffect"
exclude group: "com.github.cryptomorin", module: "XSeries"
}
shadowJar {
relocate('org.bstats.bukkit', 'com.willfp.eco.shaded.bstats')
relocate('org.apache.maven', 'com.willfp.eco.shaded.maven')
relocate('org.bstats', 'com.willfp.eco.shaded.bstats')
}
jar {
@@ -89,6 +97,19 @@ allprojects {
java {
sourceCompatibility = JavaVersion.VERSION_16
targetCompatibility = JavaVersion.VERSION_16
withSourcesJar()
}
test {
useJUnitPlatform()
// Always run tests, even when nothing changed.
dependsOn cleanTest
// Show test results.
testLogging {
events "passed", "skipped", "failed"
}
}
compileJava.options.encoding = 'UTF-8'

View File

@@ -45,7 +45,7 @@
-->
<property name="severity" value="error"/>
<property name="fileExtensions" value="java, properties, xml"/>
<property name="fileExtensions" value="java, properties, xml, kt"/>
<!-- Excludes all 'module-info.java' files -->
<!-- See https://checkstyle.org/config_filefilters.html -->
@@ -66,6 +66,7 @@
<module name="FileLength"/>
<module name="LineLength">
<property name="fileExtensions" value="java"/>
<property name="fileExtensions" value="kt"/>
<property name="max" value="200"/>
</module>

View File

@@ -10,6 +10,8 @@
<suppress files="[\\/]internal[\\/]" checks="JavadocVariable"/>
<suppress files="[\\/]eco[\\/]spigot[\\/]" checks="MissingJavadocMethod"/>
<suppress files="[\\/]eco[\\/]spigot[\\/]" checks="JavadocVariable"/>
<suppress files="[\\/]eco[\\/]proxy[\\/]" checks="MissingJavadocMethod"/>
<suppress files="[\\/]eco[\\/]proxy[\\/]" checks="JavadocVariable"/>
<!-- Modified version of library -->
<suppress files="ArmorEquipEvent.java" checks="JavadocVariable"/>

View File

@@ -6,16 +6,18 @@ group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot:1.17-R0.1-SNAPSHOT'
compileOnly 'org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT'
compileOnly 'org.apache.maven:maven-artifact:3.0.3'
compileOnly 'org.bstats:bstats-bukkit:1.7'
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT'
compileOnly 'me.clip:placeholderapi:2.10.9'
compileOnly 'com.google.code.gson:gson:2.8.7'
compileOnly 'net.kyori:adventure-text-serializer-gson:4.8.1'
compileOnly 'net.kyori:adventure-text-serializer-legacy:4.8.1'
}
java {
withJavadocJar()
}
compileJava.options.encoding = 'UTF-8'
compileJava.dependsOn clean
build.dependsOn publishToMavenLocal
@@ -26,4 +28,15 @@ publishing {
artifactId 'eco'
}
}
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/Auxilor/eco")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
}

View File

@@ -12,6 +12,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collections;
/**
* Wrapper class for ProtocolLib packets.
*/
public abstract class AbstractPacketAdapter extends PacketAdapter {
/**
* The packet type to listen for.
@@ -56,28 +59,6 @@ public abstract class AbstractPacketAdapter extends PacketAdapter {
this(plugin, type, ListenerPriority.NORMAL, postLoad);
}
/**
* The code that should be executed once the packet has been received.
*
* @param packet The packet.
* @param player The player.
*/
public void onReceive(@NotNull final PacketContainer packet,
@NotNull final Player player) {
// Empty rather than abstract as implementations don't need both
}
/**
* THe code that should be executed once the packet has been sent.
*
* @param packet The packet.
* @param player The player.
*/
public void onSend(@NotNull final PacketContainer packet,
@NotNull final Player player) {
// Empty rather than abstract as implementations don't need both
}
/**
* The code that should be executed once the packet has been received.
*
@@ -119,7 +100,6 @@ public abstract class AbstractPacketAdapter extends PacketAdapter {
return;
}
onReceive(event.getPacket(), event.getPlayer());
onReceive(event.getPacket(), event.getPlayer(), event);
}
@@ -138,7 +118,6 @@ public abstract class AbstractPacketAdapter extends PacketAdapter {
return;
}
onSend(event.getPacket(), event.getPlayer());
onSend(event.getPacket(), event.getPlayer(), event);
}

View File

@@ -0,0 +1,40 @@
package com.willfp.eco.core;
import lombok.Getter;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Base class to hold the handler.
*
* @see Handler
*/
@UtilityClass
public class Eco {
/**
* Instance of eco handler.
* <p>
* The handler is, in essence, a way to interface between the eco-api
* frontend module, and the eco-backend implementations.
* <p>
* There shouldn't really be any reason to ever use the handler
* in your own plugins, but if you want to then you can - it's
* just a part of the API like any other.
*/
@Getter
private Handler handler;
/**
* Set the handler.
*
* @param handler The handler.
*/
@ApiStatus.Internal
public void setHandler(@NotNull final Handler handler) {
Validate.isTrue(Eco.handler == null, "Already initialized!");
Eco.handler = handler;
}
}

View File

@@ -1,10 +1,9 @@
package com.willfp.eco.core;
import com.willfp.eco.core.command.AbstractCommand;
import com.willfp.eco.core.command.impl.PluginCommand;
import com.willfp.eco.core.config.ConfigHandler;
import com.willfp.eco.core.config.base.ConfigYml;
import com.willfp.eco.core.config.base.LangYml;
import com.willfp.eco.core.config.updating.ConfigHandler;
import com.willfp.eco.core.display.Display;
import com.willfp.eco.core.display.DisplayModule;
import com.willfp.eco.core.events.EventManager;
@@ -14,23 +13,13 @@ import com.willfp.eco.core.factory.NamespacedKeyFactory;
import com.willfp.eco.core.factory.RunnableFactory;
import com.willfp.eco.core.integrations.IntegrationLoader;
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
import com.willfp.eco.core.proxy.AbstractProxy;
import com.willfp.eco.core.proxy.ProxyFactory;
import com.willfp.eco.core.scheduling.Scheduler;
import com.willfp.eco.internal.Internals;
import com.willfp.eco.internal.UpdateChecker;
import com.willfp.eco.internal.arrows.ArrowDataListener;
import com.willfp.eco.internal.config.updating.EcoConfigHandler;
import com.willfp.eco.internal.events.EcoEventManager;
import com.willfp.eco.internal.extensions.EcoExtensionLoader;
import com.willfp.eco.internal.factory.EcoMetadataValueFactory;
import com.willfp.eco.internal.factory.EcoNamespacedKeyFactory;
import com.willfp.eco.internal.factory.EcoRunnableFactory;
import com.willfp.eco.internal.integrations.PlaceholderIntegrationPAPI;
import com.willfp.eco.internal.logging.EcoLogger;
import com.willfp.eco.internal.scheduling.EcoScheduler;
import com.willfp.eco.core.web.UpdateChecker;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.Listener;
@@ -47,22 +36,23 @@ import java.util.Set;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
/**
* EcoPlugin is the base plugin class for eco-based plugins.
* <p>
* It functions as a replacement for {@link JavaPlugin}.
* <p>
* EcoPlugin is a lot more powerful than {@link JavaPlugin} and
* contains many methods to reduce boilerplate code and reduce
* plugin complexity.
* <p>
* It is recommended to view the source code for this class to
* gain a better understanding of how it works.
* <p>
* <b>IMPORTANT: When reloading a plugin, all runnables / tasks will
* be cancelled.</b>
*/
@SuppressWarnings("unused")
public abstract class EcoPlugin extends JavaPlugin {
/**
* Loaded eco plugins.
*/
public static final List<String> LOADED_ECO_PLUGINS = new ArrayList<>();
/**
* The name of the plugin.
*
* @deprecated Pointless, use getName instead.
*/
@Getter
@Deprecated
private final String pluginName;
/**
* The spigot resource ID of the plugin.
*/
@@ -93,11 +83,6 @@ public abstract class EcoPlugin extends JavaPlugin {
@Getter
private final Set<String> loadedIntegrations = new HashSet<>();
/**
* Set of classes to be processed on config update.
*/
private final List<Class<?>> updatableClasses = new ArrayList<>();
/**
* The internal plugin scheduler.
*/
@@ -177,6 +162,12 @@ public abstract class EcoPlugin extends JavaPlugin {
@Getter
private final boolean supportingExtensions;
/**
* The proxy factory.
*/
@Getter
private final ProxyFactory proxyFactory;
/**
* Create a new plugin without a specified color, proxy support, spigot, or bStats.
*/
@@ -198,7 +189,7 @@ public abstract class EcoPlugin extends JavaPlugin {
* Create a new plugin unlinked to spigot and bStats.
*
* @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b)
* @param color The color of the plugin (used in messages, using standard formatting)
*/
protected EcoPlugin(@NotNull final String proxyPackage,
@NotNull final String color) {
@@ -210,7 +201,7 @@ public abstract class EcoPlugin extends JavaPlugin {
*
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param color The color of the plugin (used in messages, such as &a, &b)
* @param color The color of the plugin (used in messages, using standard formatting)
*/
protected EcoPlugin(final int resourceId,
final int bStatsId,
@@ -223,7 +214,7 @@ public abstract class EcoPlugin extends JavaPlugin {
*
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param color The color of the plugin (used in messages, such as &a, &b)
* @param color The color of the plugin (used in messages, using standard formatting)
* @param supportingExtensions If the plugin supports extensions.
*/
protected EcoPlugin(final int resourceId,
@@ -239,7 +230,7 @@ public abstract class EcoPlugin extends JavaPlugin {
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b)
* @param color The color of the plugin (used in messages, using standard formatting)
*/
protected EcoPlugin(final int resourceId,
final int bStatsId,
@@ -254,7 +245,7 @@ public abstract class EcoPlugin extends JavaPlugin {
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b)
* @param color The color of the plugin (used in messages, using standard formatting)
* @param supportingExtensions If the plugin supports extensions.
*/
protected EcoPlugin(final int resourceId,
@@ -262,68 +253,62 @@ public abstract class EcoPlugin extends JavaPlugin {
@NotNull final String proxyPackage,
@NotNull final String color,
final boolean supportingExtensions) {
this("", resourceId, bStatsId, proxyPackage, color, supportingExtensions);
}
/*
The handler must be initialized before any plugin's constructors
are called, as the constructors call Eco#getHandler().
/**
* Create a new plugin.
*
* @param pluginName The name of the plugin.
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b)
* @deprecated pluginName is redundant.
*/
@Deprecated
@SuppressWarnings("unused")
protected EcoPlugin(@NotNull final String pluginName,
final int resourceId,
final int bStatsId,
@NotNull final String proxyPackage,
@NotNull final String color) {
this(pluginName, resourceId, bStatsId, proxyPackage, color, false);
}
To fix this, EcoSpigotPlugin an abstract class and the 'actual'
plugin class is EcoHandler - that way I can create the handler
before any plugins are loaded while still having a separation between
the plugin class and the handler class (for code clarity).
I don't really like the fact that the handler class *is* the
spigot plugin, but it is what it is.
There is probably a better way of doing it - maybe with
some sort of HandlerCreator interface in order to still have
a standalone handler class, but then there would be an interface
left in the API that doesn't really help anything.
The other alternative would be do use reflection to get a 'createHandler'
method that only exists in EcoSpigotPlugin - but that feels really dirty
and I'd rather only use reflection where necessary.
*/
if (Eco.getHandler() == null && this instanceof Handler) {
/*
This code is only ever called by EcoSpigotPlugin (EcoHandler)
as it's the first plugin to load and it is a handler.
Any other plugins will never call this code as the handler
will have already been initialized.
*/
Eco.setHandler((Handler) this);
}
assert Eco.getHandler() != null;
/**
* Create a new plugin.
*
* @param pluginName The name of the plugin.
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b)
* @param supportingExtensions If the plugin supports extensions.
* @deprecated pluginName is redundant.
*/
@Deprecated
@SuppressWarnings("unused")
protected EcoPlugin(@NotNull final String pluginName,
final int resourceId,
final int bStatsId,
@NotNull final String proxyPackage,
@NotNull final String color,
final boolean supportingExtensions) {
this.pluginName = this.getName();
this.resourceId = resourceId;
this.bStatsId = bStatsId;
this.proxyPackage = proxyPackage;
this.color = color;
this.supportingExtensions = supportingExtensions;
this.scheduler = new EcoScheduler(this);
this.eventManager = new EcoEventManager(this);
this.namespacedKeyFactory = new EcoNamespacedKeyFactory(this);
this.metadataValueFactory = new EcoMetadataValueFactory(this);
this.runnableFactory = new EcoRunnableFactory(this);
this.extensionLoader = new EcoExtensionLoader(this);
this.configHandler = new EcoConfigHandler(this);
this.logger = new EcoLogger(this);
this.scheduler = Eco.getHandler().createScheduler(this);
this.eventManager = Eco.getHandler().createEventManager(this);
this.namespacedKeyFactory = Eco.getHandler().createNamespacedKeyFactory(this);
this.metadataValueFactory = Eco.getHandler().createMetadataValueFactory(this);
this.runnableFactory = Eco.getHandler().createRunnableFactory(this);
this.extensionLoader = Eco.getHandler().createExtensionLoader(this);
this.configHandler = Eco.getHandler().createConfigHandler(this);
this.logger = Eco.getHandler().createLogger(this);
this.proxyFactory = this.proxyPackage.equalsIgnoreCase("") ? null : Eco.getHandler().createProxyFactory(this);
this.langYml = new LangYml(this);
this.configYml = new ConfigYml(this);
LOADED_ECO_PLUGINS.add(this.getName().toLowerCase());
Eco.getHandler().addNewPlugin(this);
}
/**
@@ -336,8 +321,6 @@ public abstract class EcoPlugin extends JavaPlugin {
this.getLogger().info("");
this.getLogger().info("Loading " + this.getColor() + this.getName());
this.getEventManager().registerListener(new ArrowDataListener(this));
if (this.getResourceId() != 0) {
new UpdateChecker(this).getVersion(version -> {
DefaultArtifactVersion currentVersion = new DefaultArtifactVersion(this.getDescription().getVersion());
@@ -353,7 +336,7 @@ public abstract class EcoPlugin extends JavaPlugin {
});
}
DefaultArtifactVersion runningVersion = new DefaultArtifactVersion(Internals.getInstance().getPlugin().getDescription().getVersion());
DefaultArtifactVersion runningVersion = new DefaultArtifactVersion(Eco.getHandler().getEcoPlugin().getDescription().getVersion());
DefaultArtifactVersion requiredVersion = new DefaultArtifactVersion(this.getMinimumEcoVersion());
if (!(runningVersion.compareTo(requiredVersion) > 0 || runningVersion.equals(requiredVersion))) {
this.getLogger().severe("You are running an outdated version of eco!");
@@ -364,17 +347,17 @@ public abstract class EcoPlugin extends JavaPlugin {
}
if (this.getBStatsId() != 0) {
new Metrics(this, this.getBStatsId());
Eco.getHandler().registerBStats(this);
}
Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toSet());
if (enabledPlugins.contains("PlaceholderAPI")) {
this.loadedIntegrations.add("PlaceholderAPI");
PlaceholderManager.addIntegration(new PlaceholderIntegrationPAPI(this));
PlaceholderManager.addIntegration(Eco.getHandler().createPAPIIntegration(this));
}
this.getIntegrationLoaders().forEach((integrationLoader -> {
this.loadIntegrationLoaders().forEach((integrationLoader -> {
if (enabledPlugins.contains(integrationLoader.getPluginName())) {
this.loadedIntegrations.add(integrationLoader.getPluginName());
integrationLoader.load();
@@ -385,23 +368,18 @@ public abstract class EcoPlugin extends JavaPlugin {
Prerequisite.update();
this.getPacketAdapters().forEach(abstractPacketAdapter -> {
this.loadPacketAdapters().forEach(abstractPacketAdapter -> {
if (!abstractPacketAdapter.isPostLoad()) {
abstractPacketAdapter.register();
}
});
updatableClasses.addAll(this.getUpdatableClasses());
this.loadListeners().forEach(listener -> this.getEventManager().registerListener(listener));
this.getListeners().forEach(listener -> this.getEventManager().registerListener(listener));
this.getCommands().forEach(AbstractCommand::register);
this.getPluginCommands().forEach(PluginCommand::register);
this.loadPluginCommands().forEach(PluginCommand::register);
this.getScheduler().runLater(this::afterLoad, 1);
this.updatableClasses.forEach(clazz -> this.getConfigHandler().registerUpdatableClass(clazz));
if (this.isSupportingExtensions()) {
this.getExtensionLoader().loadExtensions();
@@ -413,7 +391,7 @@ public abstract class EcoPlugin extends JavaPlugin {
}
}
this.enable();
this.handleEnable();
this.getLogger().info("");
}
@@ -427,13 +405,15 @@ public abstract class EcoPlugin extends JavaPlugin {
this.getEventManager().unregisterAllListeners();
this.getScheduler().cancelAll();
this.getConfigHandler().saveAllConfigs();
this.disable();
this.handleDisable();
if (this.isSupportingExtensions()) {
this.getExtensionLoader().unloadExtensions();
}
this.getLogger().info("Cleaning up...");
Eco.getHandler().getCleaner().clean(this);
}
/**
@@ -443,7 +423,7 @@ public abstract class EcoPlugin extends JavaPlugin {
public final void onLoad() {
super.onLoad();
this.load();
this.handleLoad();
}
/**
@@ -456,7 +436,7 @@ public abstract class EcoPlugin extends JavaPlugin {
Display.registerDisplayModule(this.getDisplayModule());
}
this.getPacketAdapters().forEach(abstractPacketAdapter -> {
this.loadPacketAdapters().forEach(abstractPacketAdapter -> {
if (abstractPacketAdapter.isPostLoad()) {
abstractPacketAdapter.register();
}
@@ -475,15 +455,15 @@ public abstract class EcoPlugin extends JavaPlugin {
this.getLogger().severe("");
}
this.postLoad();
this.handleAfterLoad();
this.reload();
this.getLogger().info("Loaded " + this.color + this.pluginName);
this.getLogger().info("Loaded " + this.color + this.getName());
}
/**
* Default code to be executed on plugin reload.
* Reload the plugin.
*/
public final void reload() {
this.getConfigHandler().updateConfigs();
@@ -492,7 +472,20 @@ public abstract class EcoPlugin extends JavaPlugin {
this.getConfigHandler().callUpdate(); // Call twice to fix issues
this.getScheduler().cancelAll();
this.onReload();
this.handleReload();
}
/**
* Reload the plugin and return the time taken to reload.
*
* @return The time.
*/
public final long reloadWithTime() {
long startTime = System.currentTimeMillis();
this.reload();
return System.currentTimeMillis() - startTime;
}
/**
@@ -500,7 +493,7 @@ public abstract class EcoPlugin extends JavaPlugin {
* <p>
* Override when needed.
*/
public void enable() {
protected void handleEnable() {
}
@@ -509,7 +502,7 @@ public abstract class EcoPlugin extends JavaPlugin {
* <p>
* Override when needed.
*/
public void disable() {
protected void handleDisable() {
}
@@ -520,7 +513,7 @@ public abstract class EcoPlugin extends JavaPlugin {
* <p>
* Override when needed.
*/
public void load() {
protected void handleLoad() {
}
@@ -529,7 +522,7 @@ public abstract class EcoPlugin extends JavaPlugin {
* <p>
* Override when needed.
*/
public void onReload() {
protected void handleReload() {
}
@@ -538,7 +531,7 @@ public abstract class EcoPlugin extends JavaPlugin {
* <p>
* Override when needed.
*/
public void postLoad() {
protected void handleAfterLoad() {
}
@@ -547,18 +540,7 @@ public abstract class EcoPlugin extends JavaPlugin {
*
* @return A list of integrations.
*/
public List<IntegrationLoader> getIntegrationLoaders() {
return new ArrayList<>();
}
/**
* The commands to be registered.
*
* @return A list of commands.
* @deprecated Use {@link this#getPluginCommands()} instead.
*/
@Deprecated
public List<AbstractCommand> getCommands() {
protected List<IntegrationLoader> loadIntegrationLoaders() {
return new ArrayList<>();
}
@@ -567,7 +549,7 @@ public abstract class EcoPlugin extends JavaPlugin {
*
* @return A list of commands.
*/
public List<PluginCommand> getPluginCommands() {
protected List<PluginCommand> loadPluginCommands() {
return new ArrayList<>();
}
@@ -578,7 +560,7 @@ public abstract class EcoPlugin extends JavaPlugin {
*
* @return A list of packet adapters.
*/
public List<AbstractPacketAdapter> getPacketAdapters() {
protected List<AbstractPacketAdapter> loadPacketAdapters() {
return new ArrayList<>();
}
@@ -587,16 +569,7 @@ public abstract class EcoPlugin extends JavaPlugin {
*
* @return A list of all listeners.
*/
public abstract List<Listener> getListeners();
/**
* All updatable classes.
*
* @return A list of all updatable classes.
*/
public List<Class<?>> getUpdatableClasses() {
return new ArrayList<>();
}
protected abstract List<Listener> loadListeners();
/**
* Create the display module for the plugin.
@@ -618,8 +591,8 @@ public abstract class EcoPlugin extends JavaPlugin {
*
* @return The version.
*/
protected String getMinimumEcoVersion() {
return "5.0.0";
public String getMinimumEcoVersion() {
return "6.0.0";
}
/**
@@ -633,12 +606,25 @@ public abstract class EcoPlugin extends JavaPlugin {
return logger;
}
/**
* Get a proxy.
*
* @param proxyClass The proxy class.
* @param <T> The proxy type.
* @return The proxy.
*/
public final <T extends AbstractProxy> T getProxy(@NotNull final Class<T> proxyClass) {
Validate.notNull(proxyFactory, "Plugin does not support proxy!");
return proxyFactory.getProxy(proxyClass);
}
/**
* Get unwrapped config.
* Does not use eco config system, don't use.
*
* @return The bukkit config.
* @deprecated Use {@link EcoPlugin#getConfigYml()} instead.
* @deprecated Use getConfigYml() instead.
*/
@NotNull
@Override
@@ -646,7 +632,7 @@ public abstract class EcoPlugin extends JavaPlugin {
public final FileConfiguration getConfig() {
this.getLogger().warning("Call to default config method in eco plugin!");
return this.getConfigYml().getHandle();
return this.getConfigYml().getBukkitHandle();
}
/**
@@ -687,4 +673,23 @@ public abstract class EcoPlugin extends JavaPlugin {
super.reloadConfig();
}
/**
* Get an EcoPlugin by name.
*
* @param pluginName The name.
* @return The plugin.
*/
public static EcoPlugin getPlugin(@NotNull final String pluginName) {
return Eco.getHandler().getPluginByName(pluginName);
}
/**
* Get all EcoPlugin names.
*
* @return The set of names.
*/
public static Set<String> getPluginNames() {
return new HashSet<>(Eco.getHandler().getLoadedPlugins());
}
}

View File

@@ -0,0 +1,178 @@
package com.willfp.eco.core;
import com.willfp.eco.core.config.updating.ConfigHandler;
import com.willfp.eco.core.config.wrapper.ConfigFactory;
import com.willfp.eco.core.drops.DropQueueFactory;
import com.willfp.eco.core.events.EventManager;
import com.willfp.eco.core.extensions.ExtensionLoader;
import com.willfp.eco.core.factory.MetadataValueFactory;
import com.willfp.eco.core.factory.NamespacedKeyFactory;
import com.willfp.eco.core.factory.RunnableFactory;
import com.willfp.eco.core.fast.FastItemStack;
import com.willfp.eco.core.gui.GUIFactory;
import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration;
import com.willfp.eco.core.proxy.Cleaner;
import com.willfp.eco.core.proxy.ProxyFactory;
import com.willfp.eco.core.scheduling.Scheduler;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.logging.Logger;
/**
* @see Eco
*/
public interface Handler {
/**
* Create a scheduler.
*
* @param plugin The plugin.
* @return The scheduler.
*/
Scheduler createScheduler(@NotNull EcoPlugin plugin);
/**
* Create an event manager.
*
* @param plugin The plugin.
* @return The event manager.
*/
EventManager createEventManager(@NotNull EcoPlugin plugin);
/**
* Create a NamespacedKey factory.
*
* @param plugin The plugin.
* @return The factory.
*/
NamespacedKeyFactory createNamespacedKeyFactory(@NotNull EcoPlugin plugin);
/**
* Create a MetadataValue factory.
*
* @param plugin The plugin.
* @return The factory.
*/
MetadataValueFactory createMetadataValueFactory(@NotNull EcoPlugin plugin);
/**
* Create a Runnable factory.
*
* @param plugin The plugin.
* @return The factory.
*/
RunnableFactory createRunnableFactory(@NotNull EcoPlugin plugin);
/**
* Create an ExtensionLoader.
*
* @param plugin The plugin.
* @return The factory.
*/
ExtensionLoader createExtensionLoader(@NotNull EcoPlugin plugin);
/**
* Create a config handler.
*
* @param plugin The plugin.
* @return The handler.
*/
ConfigHandler createConfigHandler(@NotNull EcoPlugin plugin);
/**
* Create a logger.
*
* @param plugin The plugin.
* @return The logger.
*/
Logger createLogger(@NotNull EcoPlugin plugin);
/**
* Create a PAPI integration.
*
* @param plugin The plugin.
* @return The integration.
*/
PlaceholderIntegration createPAPIIntegration(@NotNull EcoPlugin plugin);
/**
* Create a proxy factory.
*
* @param plugin The plugin.
* @return The factory.
*/
ProxyFactory createProxyFactory(@NotNull EcoPlugin plugin);
/**
* Get eco Spigot plugin.
*
* @return The plugin.
*/
EcoPlugin getEcoPlugin();
/**
* Get config factory.
*
* @return The factory.
*/
ConfigFactory getConfigFactory();
/**
* Get drop queue factory.
*
* @return The factory.
*/
DropQueueFactory getDropQueueFactory();
/**
* Get GUI factory.
*
* @return The factory.
*/
GUIFactory getGUIFactory();
/**
* Get cleaner.
*
* @return The cleaner.
*/
Cleaner getCleaner();
/**
* Add new plugin.
*
* @param plugin The plugin.
*/
void addNewPlugin(@NotNull EcoPlugin plugin);
/**
* Get plugin by name.
*
* @param name The name.
* @return The plugin.
*/
EcoPlugin getPluginByName(@NotNull String name);
/**
* Get all loaded eco plugins.
*
* @return A list of plugin names in lowercase.
*/
List<String> getLoadedPlugins();
/**
* Create a FastItemStack.
*
* @param itemStack The base ItemStack.
* @return The FastItemStack.
*/
FastItemStack createFastItemStack(@NotNull ItemStack itemStack);
/**
* Register bStats metrics.
*
* @param plugin The plugin.
*/
void registerBStats(@NotNull EcoPlugin plugin);
}

View File

@@ -4,6 +4,11 @@ import lombok.AccessLevel;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
/**
* Quick DI class to manage passing eco plugins.
*
* @param <T> The eco plugin type.
*/
public abstract class PluginDependent<T extends EcoPlugin> {
/**
* The {@link EcoPlugin} that is stored.

View File

@@ -10,6 +10,12 @@ import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
/**
* A prerequisite is a requirement for something.
* <p>
* For example, you can require the server to have paper or be a specific version,
* or have some other dependency.
*/
public class Prerequisite {
/**
* All existing prerequisites are registered on creation.
@@ -25,12 +31,11 @@ public class Prerequisite {
);
/**
* Requires the server to be running 1.17.
* Requires the server to be running an implementation of paper.
*/
@Deprecated
public static final Prerequisite v1_17 = new Prerequisite(
() -> ProxyConstants.NMS_VERSION.contains("17"),
"Requires server to be running 1.17+"
public static final Prerequisite HAS_VAULT = new Prerequisite(
() -> ClassUtils.exists("net.milkbowl.vault.economy.Economy"),
"Requires server to have vault"
);
/**

View File

@@ -1,156 +0,0 @@
package com.willfp.eco.core.command;
import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.EcoPlugin;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
public abstract class AbstractCommand extends PluginDependent<EcoPlugin> implements CommandExecutor {
/**
* The name of the command
* <p>
* i.e. the name used on execution, for example /enchantinfo would have the name enchantinfo.
*/
private final String name;
/**
* The permission required to execute the command.
* <p>
* Written out as a string for flexibility with subclasses.
*/
private final String permission;
/**
* Should the command only be allowed to be executed by players?
* <p>
* In other worlds, only allowed to be executed by console.
*/
private final boolean playersOnly;
/**
* Create a new command.
* <p>
* The command will not be registered until {@link this#register()} is called.
* <p>
* The name cannot be the same as an existing command as this will conflict.
*
* @param plugin The owning {@link EcoPlugin}.
* @param name The name used in execution.
* @param permission The permission required to execute the command.
* @param playersOnly If only players should be able to execute this command.
*/
protected AbstractCommand(@NotNull final EcoPlugin plugin,
@NotNull final String name,
@NotNull final String permission,
final boolean playersOnly) {
super(plugin);
this.name = name;
this.permission = permission;
this.playersOnly = playersOnly;
}
/**
* Get the {@link AbstractTabCompleter} associated with this command.
* <p>
* Implementations of {@link AbstractCommand} do not have to override this method:
* null represents no associated tab-completer.
*
* @return The associated {@link AbstractTabCompleter}, or null if none associated.
*/
public @Nullable AbstractTabCompleter getTab() {
return null;
}
/**
* Get the name of the permission required to execute this command.
*
* @return The name of the permission.
*/
public String getPermission() {
return this.permission;
}
/**
* Get the name of the command used in execution.
*
* @return The command name.
*/
public String getName() {
return this.name;
}
/**
* Internal implementation used to clean up boilerplate.
* Used for parity with {@link CommandExecutor#onCommand(CommandSender, Command, String, String[])}.
* <p>
* Calls {@link this#onExecute(CommandSender, List)}.
*
* @param sender The executor of the command.
* @param command The bukkit command.
* @param label The name of the executed command.
* @param args The arguments of the command (anything after the physical command name)
* @return If the command was processed by the linked {@link EcoPlugin}
*/
@Override
public final boolean onCommand(@NotNull final CommandSender sender,
@NotNull final Command command,
@NotNull final String label,
@NotNull final String[] args) {
if (!command.getName().equalsIgnoreCase(name)) {
return false;
}
if (playersOnly && !(sender instanceof Player)) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("not-player"));
return true;
}
if (!sender.hasPermission(permission) && sender instanceof Player) {
sender.sendMessage(this.getPlugin().getLangYml().getNoPermission());
return true;
}
onExecute(sender, Arrays.asList(args));
return true;
}
/**
* Registers the command with the server,
* <p>
* Requires the command name to exist, defined in plugin.yml.
*/
public final void register() {
PluginCommand command = Bukkit.getPluginCommand(name);
assert command != null;
command.setExecutor(this);
AbstractTabCompleter tabCompleter = this.getTab();
if (tabCompleter != null) {
command.setTabCompleter(tabCompleter);
}
}
/**
* The code for the execution of the command (The actual functionality).
* <p>
* Unlike {@link this#onCommand(CommandSender, Command, String, String[])},
* this does not return a value as the command <b>will</b> have been processed.
*
* @param sender The sender of the command
* @param args The arguments of the command
*/
protected abstract void onExecute(CommandSender sender,
List<String> args);
}

View File

@@ -1,66 +0,0 @@
package com.willfp.eco.core.command;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
@Deprecated
public abstract class AbstractTabCompleter implements TabCompleter {
/**
* The {@link AbstractCommand} that is tab-completed.
*/
private final AbstractCommand command;
/**
* Create a tab-completer for a specified {@link AbstractCommand}.
*
* @param command The command to tab-complete.
*/
protected AbstractTabCompleter(@NotNull final AbstractCommand command) {
this.command = command;
}
/**
* Internal implementation used to clean up boilerplate.
* Used for parity with {@link TabCompleter#onTabComplete(CommandSender, Command, String, String[])}.
* <p>
* Calls {@link this#onTab(CommandSender, List)}.
*
* @param sender The executor of the command.
* @param command The bukkit command.
* @param label The name of the executed command.
* @param args The arguments of the command (anything after the physical command name).
* @return The list of tab-completions.
*/
@Override
public @Nullable List<String> onTabComplete(@NotNull final CommandSender sender,
@NotNull final Command command,
@NotNull final String label,
@NotNull final String[] args) {
if (!command.getName().equalsIgnoreCase(this.command.getName())) {
return null;
}
if (!sender.hasPermission(this.command.getPermission())) {
return null;
}
return onTab(sender, Arrays.asList(args));
}
/**
* The code for the tab-completion of the command (The actual functionality).
* <p>
*
* @param sender The sender of the command.
* @param args The arguments of the command.
* @return The list of tab-completions.
*/
public abstract List<String> onTab(@NotNull CommandSender sender,
@NotNull List<String> args);
}

View File

@@ -2,6 +2,9 @@ package com.willfp.eco.core.command;
import org.jetbrains.annotations.NotNull;
/**
* Interface for all command implementations.
*/
public interface CommandBase {
/**
* Get command name.
@@ -39,10 +42,24 @@ public interface CommandBase {
*/
CommandHandler getHandler();
/**
* Set the handler.
*
* @param handler The handler.
*/
void setHandler(@NotNull CommandHandler handler);
/**
* Get the tab completer.
*
* @return The tab completer.
*/
TabCompleteHandler getTabCompleter();
/**
* Set the tab completer.
*
* @param handler The handler.
*/
void setTabCompleter(@NotNull TabCompleteHandler handler);
}

View File

@@ -1,10 +1,17 @@
package com.willfp.eco.core.command;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* A command handler handles the actual code for a command.
* <p>
* The replacement for {@link org.bukkit.command.CommandExecutor#onCommand(CommandSender, Command, String, String[])}
* @see CommandBase
*/
@FunctionalInterface
public interface CommandHandler {
/**

View File

@@ -1,10 +1,17 @@
package com.willfp.eco.core.command;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* A Tab Complete handler handles the actual tab-completion code.
* <p>
* The replacement for {@link org.bukkit.command.TabCompleter#onTabComplete(CommandSender, Command, String, String[])}
* @see CommandBase
*/
@FunctionalInterface
public interface TabCompleteHandler {
/**

View File

@@ -1,14 +1,15 @@
package com.willfp.eco.internal.commands;
package com.willfp.eco.core.command.impl;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.command.CommandBase;
import com.willfp.eco.core.command.CommandHandler;
import com.willfp.eco.core.command.TabCompleteHandler;
import com.willfp.eco.internal.commands.util.CommandUtils;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
@@ -18,7 +19,14 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public abstract class HandledCommand extends PluginDependent<EcoPlugin> implements CommandBase {
/**
* Abstract class for commands that can be handled.
* <p>
* Handled commands have a method to pass in raw input from bukkit commands
* in order to execute the command-specific code. It's essentially an internal
* layer, hence why it's a package-private class.
*/
abstract class HandledCommand extends PluginDependent<EcoPlugin> implements CommandBase {
/**
* The name of the command.
*/
@@ -41,6 +49,20 @@ public abstract class HandledCommand extends PluginDependent<EcoPlugin> implemen
@Getter
private final boolean playersOnly;
/**
* The actual code to be executed in the command.
*/
@Getter
@Setter
private CommandHandler handler = (sender, args) -> { };
/**
* The tab completion code to be executed in the command.
*/
@Getter
@Setter
private TabCompleteHandler tabCompleter = (sender, args) -> new ArrayList<>();
/**
* All subcommands for the command.
*/
@@ -57,10 +79,10 @@ public abstract class HandledCommand extends PluginDependent<EcoPlugin> implemen
* @param permission The permission required to execute the command.
* @param playersOnly If only players should be able to execute this command.
*/
protected HandledCommand(@NotNull final EcoPlugin plugin,
@NotNull final String name,
@NotNull final String permission,
final boolean playersOnly) {
HandledCommand(@NotNull final EcoPlugin plugin,
@NotNull final String name,
@NotNull final String permission,
final boolean playersOnly) {
super(plugin);
this.name = name;
this.permission = permission;
@@ -89,14 +111,14 @@ public abstract class HandledCommand extends PluginDependent<EcoPlugin> implemen
*/
protected final void handle(@NotNull final CommandSender sender,
@NotNull final String[] args) {
if (!CommandUtils.canExecute(sender, this, this.getPlugin())) {
if (!canExecute(sender, this, this.getPlugin())) {
return;
}
if (args.length > 0) {
for (CommandBase subcommand : this.getSubcommands()) {
if (subcommand.getName().equalsIgnoreCase(args[0])) {
if (!CommandUtils.canExecute(sender, subcommand, this.getPlugin())) {
if (!canExecute(sender, subcommand, this.getPlugin())) {
return;
}
@@ -115,6 +137,7 @@ public abstract class HandledCommand extends PluginDependent<EcoPlugin> implemen
*
* @param sender The sender.
* @param args The arguments.
* @return The tab completion results.
*/
protected final List<String> handleTabCompletion(@NotNull final CommandSender sender,
@NotNull final String[] args) {
@@ -156,11 +179,27 @@ public abstract class HandledCommand extends PluginDependent<EcoPlugin> implemen
return this.getTabCompleter().tabComplete(sender, Arrays.asList(args));
}
@Override
public abstract CommandHandler getHandler();
/**
* If a sender can execute the command.
*
* @param sender The sender.
* @param command The command.
* @param plugin The plugin.
* @return If the sender can execute.
*/
public static boolean canExecute(@NotNull final CommandSender sender,
@NotNull final CommandBase command,
@NotNull final EcoPlugin plugin) {
if (command.isPlayersOnly() && !(sender instanceof Player)) {
sender.sendMessage(plugin.getLangYml().getMessage("not-player"));
return false;
}
@Override
public TabCompleteHandler getTabCompleter() {
return (sender, args) -> new ArrayList<>();
if (!sender.hasPermission(command.getPermission()) && sender instanceof Player) {
sender.sendMessage(plugin.getLangYml().getNoPermission());
return false;
}
return true;
}
}

View File

@@ -1,7 +1,6 @@
package com.willfp.eco.core.command.impl;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.internal.commands.HandledCommand;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@@ -12,13 +11,16 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* PluginCommands are the class to be used instead of CommandExecutor.
* <p>
* The command will not be registered until register() is called.
* <p>
* The name cannot be the same as an existing command as this will conflict.
*/
public abstract class PluginCommand extends HandledCommand implements CommandExecutor, TabCompleter {
/**
* Create a new command.
* <p>
* The command will not be registered until {@link this#register()} is called.
* <p>
* The name cannot be the same as an existing command as this will conflict.
*
* @param plugin The plugin.
* @param name The name used in execution.

View File

@@ -2,9 +2,11 @@ package com.willfp.eco.core.command.impl;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.command.CommandBase;
import com.willfp.eco.internal.commands.HandledCommand;
import org.jetbrains.annotations.NotNull;
/**
* Subcommands can be added to PluginCommands or to other Subcommands.
*/
public abstract class Subcommand extends HandledCommand {
/**
* Create subcommand.
@@ -24,7 +26,7 @@ public abstract class Subcommand extends HandledCommand {
/**
* Create subcommand.
*
* @param plugin The plugin.
* @param plugin The plugin.
* @param name The name of the subcommand.
* @param parent The parent command.
*/

View File

@@ -1,40 +0,0 @@
package com.willfp.eco.core.config;
import com.willfp.eco.internal.config.yaml.UpdatableYamlConfig;
import com.willfp.eco.core.EcoPlugin;
import org.jetbrains.annotations.NotNull;
public abstract class BaseConfig extends UpdatableYamlConfig {
/**
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
* <p>
* Automatically updates.
*
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
* @param updateBlacklist Substring of keys to not add/remove keys for.
*/
protected BaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin,
@NotNull final String... updateBlacklist) {
super(configName, plugin, "", plugin.getClass(), removeUnused, updateBlacklist);
}
/**
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
* <p>
* Automatically updates.
*
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
*/
protected BaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin) {
super(configName, plugin, "", plugin.getClass(), removeUnused, "");
}
}

View File

@@ -1,11 +0,0 @@
package com.willfp.eco.core.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ConfigUpdater {
}

View File

@@ -1,28 +0,0 @@
package com.willfp.eco.core.config;
import com.willfp.eco.internal.config.yaml.UpdatableYamlConfig;
import com.willfp.eco.core.EcoPlugin;
import org.jetbrains.annotations.NotNull;
public abstract class ExtendableConfig extends UpdatableYamlConfig {
/**
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
* <p>
* Automatically updates.
*
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
* @param updateBlacklist Substring of keys to not add/remove keys for.
* @param subDirectoryPath The subdirectory path.
* @param source The class that owns the resource.
*/
protected ExtendableConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin,
@NotNull final Class<?> source,
@NotNull final String subDirectoryPath,
@NotNull final String... updateBlacklist) {
super(configName, plugin, subDirectoryPath, source, removeUnused, updateBlacklist);
}
}

View File

@@ -1,20 +0,0 @@
package com.willfp.eco.core.config;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.internal.config.json.LoadableJsonConfig;
import org.jetbrains.annotations.NotNull;
public abstract class JsonStaticBaseConfig extends LoadableJsonConfig {
/**
* Config implementation for configs present in the plugin's base directory (eg config.json, lang.json).
* <p>
* Does not automatically update.
*
* @param configName The name of the config
* @param plugin The plugin.
*/
protected JsonStaticBaseConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin) {
super(configName, plugin, "", plugin.getClass());
}
}

View File

@@ -1,20 +0,0 @@
package com.willfp.eco.core.config;
import com.willfp.eco.internal.config.yaml.LoadableYamlConfig;
import com.willfp.eco.core.EcoPlugin;
import org.jetbrains.annotations.NotNull;
public abstract class StaticBaseConfig extends LoadableYamlConfig {
/**
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
* <p>
* Does not automatically update.
*
* @param configName The name of the config
* @param plugin The plugin.
*/
protected StaticBaseConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin) {
super(configName, plugin, "", plugin.getClass());
}
}

View File

@@ -1,18 +0,0 @@
package com.willfp.eco.core.config;
import com.willfp.eco.internal.config.yaml.YamlConfigWrapper;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
public abstract class YamlConfig extends YamlConfigWrapper<YamlConfiguration> {
/**
* Config implementation for passing YamlConfigurations.
* <p>
* Does not automatically update.
*
* @param config The YamlConfiguration handle.
*/
public YamlConfig(@NotNull final YamlConfiguration config) {
init(config);
}
}

View File

@@ -1,11 +1,13 @@
package com.willfp.eco.core.config.base;
import com.willfp.eco.core.config.BaseConfig;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.yaml.YamlBaseConfig;
import org.jetbrains.annotations.NotNull;
public class ConfigYml extends BaseConfig {
/**
* Default plugin config.yml.
*/
public class ConfigYml extends YamlBaseConfig {
/**
* Config.yml.
*

View File

@@ -1,10 +1,13 @@
package com.willfp.eco.core.config.base;
import com.willfp.eco.core.config.BaseConfig;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.yaml.YamlBaseConfig;
import org.jetbrains.annotations.NotNull;
public class LangYml extends BaseConfig {
/**
* Default plugin lang.yml.
*/
public class LangYml extends YamlBaseConfig {
/**
* Lang.yml.
*

View File

@@ -1,11 +1,16 @@
package com.willfp.eco.core.config;
package com.willfp.eco.core.config.interfaces;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface Config {
/**
* All canfigs implement this interface.
* <p>
* Contains all methods that must exist in yaml and json configurations.
*/
public interface Config extends Cloneable {
/**
* Clears cache.
*/
@@ -162,6 +167,17 @@ public interface Config {
@NotNull
String getString(@NotNull String path);
/**
* Get a string from config.
*
* @param path The key to fetch the value from.
* @param format If the string should be formatted.
* @return The found value, or an empty string if not found.
*/
@NotNull
String getString(@NotNull String path,
boolean format);
/**
* Get a string from config.
*
@@ -171,6 +187,17 @@ public interface Config {
@Nullable
String getStringOrNull(@NotNull String path);
/**
* Get a string from config.
*
* @param path The key to fetch the value from.
* @param format If the string should be formatted.
* @return The found value, or null if not found.
*/
@Nullable
String getStringOrNull(@NotNull String path,
boolean format);
/**
* Get a list of strings from config.
* <p>
@@ -185,7 +212,7 @@ public interface Config {
/**
* Get a list of strings from config.
*
* @param path The key to fetch the value from.
* @param path The key to fetch the value from.
* @param format If the strings should be formatted.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@@ -202,6 +229,17 @@ public interface Config {
@Nullable
List<String> getStringsOrNull(@NotNull String path);
/**
* Get a list of strings from config.
*
* @param path The key to fetch the value from.
* @param format If the strings should be formatted.
* @return The found value, or null if not found.
*/
@Nullable
List<String> getStringsOrNull(@NotNull String path,
boolean format);
/**
* Get a decimal from config.
*
@@ -236,4 +274,11 @@ public interface Config {
*/
@Nullable
List<Double> getDoublesOrNull(@NotNull String path);
/**
* Clone the config.
*
* @return The clone.
*/
Config clone();
}

View File

@@ -1,10 +1,15 @@
package com.willfp.eco.core.config;
package com.willfp.eco.core.config.interfaces;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* JSON configs have extra methods compared to yaml configs.
* <p>
* If you need to use them, then use JSONConfig instead.
*/
public interface JSONConfig extends Config {
/**
* Get a list of subsections from config.
@@ -23,4 +28,28 @@ public interface JSONConfig extends Config {
*/
@Nullable
List<JSONConfig> getSubsectionsOrNull(@NotNull String path);
/**
* Get subsection from config.
*
* @param path The key to check.
* @return The subsection. Throws NPE if not found.
*/
@Override
@NotNull
JSONConfig getSubsection(@NotNull String path);
/**
* Get subsection from config.
*
* @param path The key to check.
* @return The subsection, or null if not found.
*/
@Override
@Nullable
JSONConfig getSubsectionOrNull(@NotNull String path);
@Override
JSONConfig clone();
}

View File

@@ -1,8 +1,11 @@
package com.willfp.eco.internal.config;
package com.willfp.eco.core.config.interfaces;
import java.io.File;
import java.io.IOException;
/**
* Interface for configs that physically exist as files in plugins.
*/
public interface LoadableConfig {
/**
* Create the file.

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.core.config.interfaces;
import org.bukkit.configuration.file.YamlConfiguration;
/**
* Interface for configs that wrap an {@link YamlConfiguration}.
*
* @see com.willfp.eco.core.config.yaml.wrapper.YamlConfigWrapper
*/
public interface WrappedYamlConfiguration {
/**
* Get the ConfigurationSection handle.
*
* @return The handle.
*/
YamlConfiguration getBukkitHandle();
}

View File

@@ -0,0 +1,24 @@
package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
import org.jetbrains.annotations.NotNull;
/**
* Non-updatable JSON config that exists within a plugin jar.
*/
public abstract class JSONStaticBaseConfig extends LoadableJSONConfigWrapper {
/**
* Config implementation for configs present in the plugin's base directory (eg config.json, lang.json).
* <p>
* Does not automatically update.
*
* @param configName The name of the config
* @param plugin The plugin.
*/
protected JSONStaticBaseConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin) {
super(Eco.getHandler().getConfigFactory().createLoadableJSONConfig(configName, plugin, "", plugin.getClass()));
}
}

View File

@@ -0,0 +1,23 @@
package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.config.json.wrapper.JSONConfigWrapper;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
/**
* Raw JSON config with a map of values at its core.
*/
public class JSONTransientConfig extends JSONConfigWrapper {
/**
* Config implementation for passing maps.
* <p>
* Does not automatically update.
*
* @param values The map of values.
*/
public JSONTransientConfig(@NotNull final Map<String, Object> values) {
super(Eco.getHandler().getConfigFactory().createJSONConfig(values));
}
}

View File

@@ -0,0 +1,48 @@
package com.willfp.eco.core.config.json.wrapper;
import com.willfp.eco.core.config.interfaces.JSONConfig;
import com.willfp.eco.core.config.wrapper.ConfigWrapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* Wrapper to handle the backend JSON config implementations.
*/
public abstract class JSONConfigWrapper extends ConfigWrapper<JSONConfig> implements JSONConfig {
/**
* Create a config wrapper.
*
* @param handle The handle.
*/
protected JSONConfigWrapper(@NotNull final JSONConfig handle) {
super(handle);
}
@Override
public @NotNull List<JSONConfig> getSubsections(@NotNull final String path) {
return this.getHandle().getSubsections(path);
}
@Override
public @Nullable List<JSONConfig> getSubsectionsOrNull(@NotNull final String path) {
return this.getHandle().getSubsectionsOrNull(path);
}
@Override
public @NotNull JSONConfig getSubsection(@NotNull final String path) {
return this.getHandle().getSubsection(path);
}
@Override
public @Nullable JSONConfig getSubsectionOrNull(@NotNull final String path) {
return this.getHandle().getSubsectionOrNull(path);
}
@Override
public JSONConfig clone() {
return this.getHandle().clone();
}
}

View File

@@ -0,0 +1,51 @@
package com.willfp.eco.core.config.json.wrapper;
import com.willfp.eco.core.config.interfaces.JSONConfig;
import com.willfp.eco.core.config.interfaces.LoadableConfig;
import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
/**
* Wrapper to handle the backend loadable JSON config implementations.
*/
public abstract class LoadableJSONConfigWrapper extends JSONConfigWrapper implements LoadableConfig {
/**
* Create a config wrapper.
*
* @param handle The handle.
*/
protected LoadableJSONConfigWrapper(@NotNull final JSONConfig handle) {
super(handle);
Validate.isTrue(handle instanceof LoadableConfig, "Wrapped config must be loadable!");
}
@Override
public void createFile() {
((LoadableConfig) this.getHandle()).createFile();
}
@Override
public String getResourcePath() {
return ((LoadableConfig) this.getHandle()).getResourcePath();
}
@Override
public void save() throws IOException {
((LoadableConfig) this.getHandle()).save();
}
@Override
public File getConfigFile() {
return ((LoadableConfig) this.getHandle()).getConfigFile();
}
@Override
public String getName() {
return ((LoadableConfig) this.getHandle()).getName();
}
}

View File

@@ -1,21 +1,19 @@
package com.willfp.eco.core.config;
package com.willfp.eco.core.config.updating;
import com.willfp.eco.internal.config.LoadableConfig;
import com.willfp.eco.core.config.interfaces.LoadableConfig;
import org.jetbrains.annotations.NotNull;
/**
* Every {@link com.willfp.eco.core.EcoPlugin} has a config handler.
* <p>
* Handles updating and saving configs.
*/
public interface ConfigHandler {
/**
* Invoke all update methods.
*/
void callUpdate();
/**
* Register an updatable class.
*
* @param updatableClass The class with an update method.
*/
void registerUpdatableClass(@NotNull Class<?> updatableClass);
/**
* Save all configs.
*/

View File

@@ -0,0 +1,39 @@
package com.willfp.eco.core.config.updating;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to put on update methods.
* <p>
* All update methods must be public and static,
* and can accept an EcoPlugin as a parameter.
* <p>
* As such, there are only 2 valid update methods:
* <p>
* The first:
* <pre>{@code
* @ConfigUpdater
* public static void update() {
* // Update code
* }
* }</pre>
* <p>
* The second:
* <pre>{@code
* public static void update(EcoPlugin plugin) {}
* // Update code
* }</pre>
* <p>
* Config update methods in all classes in a plugin jar will be called
* on reload.
* <p>
* By having a plugin as a parameter, you shouldn't really need getInstance()
* calls in your code.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ConfigUpdater {
}

View File

@@ -0,0 +1,76 @@
package com.willfp.eco.core.config.wrapper;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.interfaces.Config;
import com.willfp.eco.core.config.interfaces.JSONConfig;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
/**
* Internal component to create backend config implementations.
*/
public interface ConfigFactory {
/**
* Updatable config.
*
* @param configName The name of the config
* @param plugin The plugin.
* @param subDirectoryPath The subdirectory path.
* @param source The class that owns the resource.
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param updateBlacklist Substring of keys to not add/remove keys for.
* @return The config implementation.
*/
Config createUpdatableYamlConfig(@NotNull String configName,
@NotNull EcoPlugin plugin,
@NotNull String subDirectoryPath,
@NotNull Class<?> source,
boolean removeUnused,
@NotNull String... updateBlacklist);
/**
* JSON loadable config.
*
* @param configName The name of the config
* @param plugin The plugin.
* @param subDirectoryPath The subdirectory path.
* @param source The class that owns the resource.
* @return The config implementation.
*/
JSONConfig createLoadableJSONConfig(@NotNull String configName,
@NotNull EcoPlugin plugin,
@NotNull String subDirectoryPath,
@NotNull Class<?> source);
/**
* Yaml loadable config.
*
* @param configName The name of the config
* @param plugin The plugin.
* @param subDirectoryPath The subdirectory path.
* @param source The class that owns the resource.
* @return The config implementation.
*/
Config createLoadableYamlConfig(@NotNull String configName,
@NotNull EcoPlugin plugin,
@NotNull String subDirectoryPath,
@NotNull Class<?> source);
/**
* Yaml config.
*
* @param config The handle.
* @return The config implementation.
*/
Config createYamlConfig(@NotNull YamlConfiguration config);
/**
* JSON config.
*
* @param values The values.
* @return The config implementation.
*/
JSONConfig createJSONConfig(@NotNull Map<String, Object> values);
}

View File

@@ -0,0 +1,196 @@
package com.willfp.eco.core.config.wrapper;
import com.willfp.eco.core.config.interfaces.Config;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* Configs from eco have an internal implementation,
* which is the handle.
* <p>
* This class handles them.
*
* @param <T> The type of the handle.
*/
public abstract class ConfigWrapper<T extends Config> implements Config {
/**
* Configs from eco have an internal implementation,
* which is the handle.
* <p>
* The handle should only ever be used if you want to
* do something <i>interesting</i> config-wise with some
* internals.
* <p>
* In general use, though, the handle isn't necessary.
*/
@Getter
private final T handle;
/**
* Create a config wrapper.
*
* @param handle The config that is being wrapped.
*/
protected ConfigWrapper(@NotNull final T handle) {
this.handle = handle;
}
@Override
public void clearCache() {
handle.clearCache();
}
@Override
public String toPlaintext() {
return handle.toPlaintext();
}
@Override
public boolean has(@NotNull final String path) {
return handle.has(path);
}
@Override
public @NotNull List<String> getKeys(final boolean deep) {
return handle.getKeys(deep);
}
@Override
public @Nullable Object get(@NotNull final String path) {
return handle.get(path);
}
@Override
public void set(@NotNull final String path,
@Nullable final Object object) {
handle.set(path, object);
}
@Override
public @NotNull Config getSubsection(@NotNull final String path) {
return handle.getSubsection(path);
}
@Override
public @Nullable Config getSubsectionOrNull(@NotNull final String path) {
return handle.getSubsectionOrNull(path);
}
@Override
public int getInt(@NotNull final String path) {
return handle.getInt(path);
}
@Override
public @Nullable Integer getIntOrNull(@NotNull final String path) {
return handle.getIntOrNull(path);
}
@Override
public int getInt(@NotNull final String path,
final int def) {
return handle.getInt(path, def);
}
@Override
public @NotNull List<Integer> getInts(@NotNull final String path) {
return handle.getInts(path);
}
@Override
public @Nullable List<Integer> getIntsOrNull(@NotNull final String path) {
return handle.getIntsOrNull(path);
}
@Override
public boolean getBool(@NotNull final String path) {
return handle.getBool(path);
}
@Override
public @Nullable Boolean getBoolOrNull(@NotNull final String path) {
return handle.getBoolOrNull(path);
}
@Override
public @NotNull List<Boolean> getBools(@NotNull final String path) {
return handle.getBools(path);
}
@Override
public @Nullable List<Boolean> getBoolsOrNull(@NotNull final String path) {
return handle.getBoolsOrNull(path);
}
@Override
public @NotNull String getString(@NotNull final String path) {
return handle.getString(path);
}
@Override
public @NotNull String getString(@NotNull final String path,
final boolean format) {
return handle.getString(path, format);
}
@Override
public @Nullable String getStringOrNull(@NotNull final String path) {
return handle.getStringOrNull(path);
}
@Override
public @Nullable String getStringOrNull(@NotNull final String path,
final boolean format) {
return handle.getStringOrNull(path, format);
}
@Override
public @NotNull List<String> getStrings(@NotNull final String path) {
return handle.getStrings(path);
}
@Override
public @NotNull List<String> getStrings(@NotNull final String path,
final boolean format) {
return handle.getStrings(path, format);
}
@Override
public @Nullable List<String> getStringsOrNull(@NotNull final String path) {
return handle.getStringsOrNull(path);
}
@Override
public @Nullable List<String> getStringsOrNull(@NotNull final String path,
final boolean format) {
return handle.getStringsOrNull(path, format);
}
@Override
public double getDouble(@NotNull final String path) {
return handle.getDouble(path);
}
@Override
public @Nullable Double getDoubleOrNull(@NotNull final String path) {
return handle.getDoubleOrNull(path);
}
@Override
public @NotNull List<Double> getDoubles(@NotNull final String path) {
return handle.getDoubles(path);
}
@Override
public @Nullable List<Double> getDoublesOrNull(@NotNull final String path) {
return handle.getDoublesOrNull(path);
}
@Override
public Config clone() {
return handle.clone();
}
}

View File

@@ -0,0 +1,53 @@
package com.willfp.eco.core.config.yaml;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull;
/**
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
* <p>
* Automatically updates.
*/
public abstract class YamlBaseConfig extends LoadableYamlConfigWrapper {
/**
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
* @param updateBlacklist Substring of keys to not add/remove keys for.
*/
protected YamlBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin,
@NotNull final String... updateBlacklist) {
super(
Eco.getHandler().getConfigFactory().createUpdatableYamlConfig(
configName,
plugin,
"",
plugin.getClass(),
removeUnused, updateBlacklist
)
);
}
/**
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
*/
protected YamlBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin) {
super(
Eco.getHandler().getConfigFactory().createUpdatableYamlConfig(
configName,
plugin,
"",
plugin.getClass(),
removeUnused
)
);
}
}

View File

@@ -0,0 +1,43 @@
package com.willfp.eco.core.config.yaml;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull;
/**
* Config implementation for configs present in one of two places:
* <ul>
* <li>Plugin base directory (eg config.yml, lang.yml)</li>
* <li>Other extension's configs</li>
* </ul>
* <p>
* Automatically updates.
*/
public abstract class YamlExtendableConfig extends LoadableYamlConfigWrapper {
/**
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
* @param updateBlacklist Substring of keys to not add/remove keys for.
* @param subDirectoryPath The subdirectory path.
* @param source The class that owns the resource.
*/
protected YamlExtendableConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin,
@NotNull final Class<?> source,
@NotNull final String subDirectoryPath,
@NotNull final String... updateBlacklist) {
super(
Eco.getHandler().getConfigFactory().createUpdatableYamlConfig(
configName,
plugin,
subDirectoryPath,
source,
removeUnused,
updateBlacklist
)
);
}
}

View File

@@ -0,0 +1,24 @@
package com.willfp.eco.core.config.yaml;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull;
/**
* Non-updatable yaml config that exists within a plugin jar.
*/
public abstract class YamlStaticBaseConfig extends LoadableYamlConfigWrapper {
/**
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
* <p>
* Does not automatically update.
*
* @param configName The name of the config
* @param plugin The plugin.
*/
protected YamlStaticBaseConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin) {
super(Eco.getHandler().getConfigFactory().createLoadableYamlConfig(configName, plugin, "", plugin.getClass()));
}
}

View File

@@ -0,0 +1,29 @@
package com.willfp.eco.core.config.yaml;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.config.yaml.wrapper.YamlConfigWrapper;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import java.io.StringReader;
/**
* Config implementation for passing YamlConfigurations.
* <p>
* Does not automatically update.
*/
public class YamlTransientConfig extends YamlConfigWrapper {
/**
* @param config The YamlConfiguration handle.
*/
public YamlTransientConfig(@NotNull final YamlConfiguration config) {
super(Eco.getHandler().getConfigFactory().createYamlConfig(config));
}
/**
* @param contents The contents of the config.
*/
public YamlTransientConfig(@NotNull final String contents) {
super(Eco.getHandler().getConfigFactory().createYamlConfig(YamlConfiguration.loadConfiguration(new StringReader(contents))));
}
}

View File

@@ -0,0 +1,51 @@
package com.willfp.eco.core.config.yaml.wrapper;
import com.willfp.eco.core.config.interfaces.Config;
import com.willfp.eco.core.config.interfaces.LoadableConfig;
import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
/**
* Wrapper to handle the backend loadable yaml config implementations.
*/
public abstract class LoadableYamlConfigWrapper extends YamlConfigWrapper implements LoadableConfig {
/**
* Create a config wrapper.
*
* @param handle The handle.
*/
protected LoadableYamlConfigWrapper(@NotNull final Config handle) {
super(handle);
Validate.isTrue(handle instanceof LoadableConfig, "Wrapped config must be loadable!");
}
@Override
public void createFile() {
((LoadableConfig) this.getHandle()).createFile();
}
@Override
public String getResourcePath() {
return ((LoadableConfig) this.getHandle()).getResourcePath();
}
@Override
public void save() throws IOException {
((LoadableConfig) this.getHandle()).save();
}
@Override
public File getConfigFile() {
return ((LoadableConfig) this.getHandle()).getConfigFile();
}
@Override
public String getName() {
return ((LoadableConfig) this.getHandle()).getName();
}
}

View File

@@ -0,0 +1,27 @@
package com.willfp.eco.core.config.yaml.wrapper;
import com.willfp.eco.core.config.interfaces.Config;
import com.willfp.eco.core.config.interfaces.WrappedYamlConfiguration;
import com.willfp.eco.core.config.wrapper.ConfigWrapper;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
/**
* Wrapper to handle the backend yaml config implementations.
*/
public abstract class YamlConfigWrapper extends ConfigWrapper<Config> implements WrappedYamlConfiguration {
/**
* Create a config wrapper.
*
* @param handle The handle.
*/
protected YamlConfigWrapper(@NotNull final Config handle) {
super(handle);
}
@Override
public YamlConfiguration getBukkitHandle() {
return ((WrappedYamlConfiguration) this.getHandle()).getBukkitHandle();
}
}

View File

@@ -1,85 +0,0 @@
package com.willfp.eco.core.data;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.Config;
import com.willfp.eco.core.config.JSONConfig;
import com.willfp.eco.core.config.JsonStaticBaseConfig;
import com.willfp.eco.internal.config.LoadableConfig;
import com.willfp.eco.internal.config.json.JsonConfigSection;
import lombok.experimental.UtilityClass;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@UtilityClass
public class Data {
/**
* Instance of eco data.yml.
*/
private static JSONConfig datafile = null;
/**
* All cached player data.
*/
private static final Map<UUID, Map<EcoPlugin, JSONConfig>> PLAYER_DATA = new HashMap<>();
/**
* Initialize the player data with an instance of data.json.
*
* @param config data.json.
*/
@ApiStatus.Internal
public void init(@NotNull final JsonStaticBaseConfig config) {
datafile = config;
}
/**
* Save to data.yml.
*
* @param config Instance of data.yml.
* @throws IOException Error during saving.
*/
@ApiStatus.Internal
public void save(@NotNull final Config config) throws IOException {
for (Map.Entry<UUID, Map<EcoPlugin, JSONConfig>> entry : PLAYER_DATA.entrySet()) {
entry.getValue().forEach((plugin, jsonConfig) -> {
for (String key : jsonConfig.getKeys(false)) {
config.set("player-data." + plugin.getName().toLowerCase() + "." + entry.getKey().toString() + "." + key, jsonConfig);
}
});
}
((LoadableConfig) config).save();
}
/**
* Get the data for a player.
*
* @param player The player.
* @param plugin The plugin.
* @return The data.
*/
public JSONConfig getData(@NotNull final OfflinePlayer player,
@NotNull final EcoPlugin plugin) {
if (!PLAYER_DATA.containsKey(player.getUniqueId())) {
PLAYER_DATA.put(player.getUniqueId(), new HashMap<>());
}
JSONConfig config = PLAYER_DATA.get(player.getUniqueId()).get(plugin);
if (config == null) {
config = (JSONConfig) datafile.getSubsectionOrNull("player-data." + plugin.getName().toLowerCase() + "." + player.getUniqueId());
if (config == null) {
config = new JsonConfigSection(new HashMap<>());
}
PLAYER_DATA.get(player.getUniqueId()).put(plugin, config);
return getData(player, plugin);
}
return config;
}
}

View File

@@ -3,22 +3,27 @@ package com.willfp.eco.core.display;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang.Validate;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Utility class to manage client-side item display.
*/
@UtilityClass
public class Display {
/**
* The prefix for lore lines.
* The prefix for client-side lore lines.
*/
public static final String PREFIX = "§z";
@@ -51,13 +56,21 @@ public class Display {
* Display on ItemStacks.
*
* @param itemStack The item.
* @return The itemstack.
* @return The ItemStack.
*/
public ItemStack display(@NotNull final ItemStack itemStack) {
if (!itemStack.hasItemMeta()) {
return itemStack; // return early if there's no customization of the item
}
return display(itemStack, null);
}
/**
* Display on ItemStacks.
*
* @param itemStack The item.
* @param player The player.
* @return The ItemStack.
*/
public ItemStack display(@NotNull final ItemStack itemStack,
@Nullable final Player player) {
Map<String, Object[]> pluginVarArgs = new HashMap<>();
for (DisplayPriority priority : DisplayPriority.values()) {
@@ -80,6 +93,9 @@ public class Display {
for (DisplayModule module : modules) {
Object[] varargs = pluginVarArgs.get(module.getPluginName());
module.display(itemStack, varargs);
if (player != null) {
module.display(itemStack, player, varargs);
}
}
}
@@ -90,27 +106,35 @@ public class Display {
* Display on ItemStacks and then finalize.
*
* @param itemStack The item.
* @return The itemstack.
* @return The ItemStack.
*/
public ItemStack displayAndFinalize(@NotNull final ItemStack itemStack) {
return finalize(display(itemStack));
return finalize(display(itemStack, null));
}
/**
* Display on ItemStacks and then finalize.
*
* @param itemStack The item.
* @param player The player.
* @return The ItemStack.
*/
public ItemStack displayAndFinalize(@NotNull final ItemStack itemStack,
@Nullable final Player player) {
return finalize(display(itemStack, player));
}
/**
* Revert on ItemStacks.
*
* @param itemStack The item.
* @return The itemstack.
* @return The ItemStack.
*/
public ItemStack revert(@NotNull final ItemStack itemStack) {
if (Display.isFinalized(itemStack)) {
unfinalize(itemStack);
}
if (!itemStack.hasItemMeta()) {
return itemStack;
}
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
@@ -138,7 +162,7 @@ public class Display {
* Finalize an ItemStacks.
*
* @param itemStack The item.
* @return The itemstack.
* @return The ItemStack.
*/
public ItemStack finalize(@NotNull final ItemStack itemStack) {
Validate.notNull(finalizeKey, "Key cannot be null!");
@@ -162,7 +186,7 @@ public class Display {
* Unfinalize an ItemStacks.
*
* @param itemStack The item.
* @return The itemstack.
* @return The ItemStack.
*/
public ItemStack unfinalize(@NotNull final ItemStack itemStack) {
Validate.notNull(finalizeKey, "Key cannot be null!");

View File

@@ -1,11 +1,16 @@
package com.willfp.eco.core.display;
import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import lombok.Getter;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Class for all plugin-specific client-side item display modules.
*/
public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
/**
* The priority of the module.
@@ -36,6 +41,19 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
// Technically optional.
}
/**
* Display an item.
*
* @param itemStack The item.
* @param player The player.
* @param args Optional args for display.
*/
protected void display(@NotNull final ItemStack itemStack,
@Nullable final Player player,
@NotNull final Object... args) {
// Technically optional.
}
/**
* Revert an item.
*
@@ -46,7 +64,7 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
}
/**
* Create varargs to pass back to itemstack after reverting, but before display.
* Create varargs to pass back to ItemStack after reverting, but before display.
*
* @param itemStack The itemStack.
* @return The plugin-specific varargs.
@@ -60,7 +78,7 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
*
* @return The plugin name.
*/
final String getPluginName() {
public final String getPluginName() {
return super.getPlugin().getName();
}
}

View File

@@ -1,5 +1,8 @@
package com.willfp.eco.core.display;
/**
* The priority (order) of display modules.
*/
public enum DisplayPriority {
/**
* Ran first.

View File

@@ -1,10 +1,6 @@
package com.willfp.eco.core.drops;
import com.willfp.eco.internal.drops.AbstractDropQueue;
import com.willfp.eco.internal.drops.DropManager;
import com.willfp.eco.internal.drops.DropQueueType;
import com.willfp.eco.internal.drops.impl.FastCollatedDropQueue;
import com.willfp.eco.internal.drops.impl.InternalDropQueue;
import com.willfp.eco.core.Eco;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -12,21 +8,26 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* A {@link DropQueue} is a set of drops linked to player.
* <p>
* All drops should be passed through a drop queue for telekinesis integration.
* <p>
* It functions essentially as a builder class, and runs very quickly.
*
* @see com.willfp.eco.util.TelekinesisUtils
*/
public class DropQueue {
/**
* The internally used {@link AbstractDropQueue}.
* The internally used {@link DropQueue}.
*/
private final AbstractDropQueue handle;
private final InternalDropQueue handle;
/**
* Create {@link DropQueue} linked to player.
* <p>
* All drops should be passed through a drop queue for telekinesis integration.
*
* @param player The player.
*/
public DropQueue(@NotNull final Player player) {
handle = DropManager.getType() == DropQueueType.COLLATED ? new FastCollatedDropQueue(player) : new InternalDropQueue(player);
handle = Eco.getHandler().getDropQueueFactory().create(player);
}
/**

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.core.drops;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Internal component to create backend DropQueue implementations.
*/
public interface DropQueueFactory {
/**
* Create a DropQueue.
*
* @param player The player.
* @return The Queue.
*/
InternalDropQueue create(@NotNull Player player);
}

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.internal.drops;
package com.willfp.eco.core.drops;
import org.bukkit.Location;
import org.bukkit.inventory.ItemStack;
@@ -6,14 +6,17 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public interface AbstractDropQueue {
/**
* Internal interface for backend DropQueue implementations.
*/
public interface InternalDropQueue {
/**
* Add item to queue.
*
* @param item The item to add.
* @return The DropQueue.
*/
AbstractDropQueue addItem(@NotNull ItemStack item);
InternalDropQueue addItem(@NotNull ItemStack item);
/**
* Add multiple items to queue.
@@ -21,7 +24,7 @@ public interface AbstractDropQueue {
* @param itemStacks The items to add.
* @return The DropQueue.
*/
AbstractDropQueue addItems(@NotNull Collection<ItemStack> itemStacks);
InternalDropQueue addItems(@NotNull Collection<ItemStack> itemStacks);
/**
* Add xp to queue.
@@ -29,7 +32,7 @@ public interface AbstractDropQueue {
* @param amount The amount to add.
* @return The DropQueue.
*/
AbstractDropQueue addXP(int amount);
InternalDropQueue addXP(int amount);
/**
* Set location of the origin of the drops.
@@ -37,14 +40,14 @@ public interface AbstractDropQueue {
* @param location The location.
* @return The DropQueue.
*/
AbstractDropQueue setLocation(@NotNull Location location);
InternalDropQueue setLocation(@NotNull Location location);
/**
* Force the queue to act as if player is telekinetic.
*
* @return The DropQueue.
*/
AbstractDropQueue forceTelekinesis();
InternalDropQueue forceTelekinesis();
/**
* Push the queue.

View File

@@ -0,0 +1,70 @@
package com.willfp.eco.core.events;
import lombok.Getter;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* The armor change event <b>does</b> contain information about the event.
* <p>
* Unlike {@link ArmorEquipEvent}, it is called the next tick and contains previous and current armor contents.
*/
public class ArmorChangeEvent extends PlayerEvent {
/**
* Bukkit parity.
*/
private static final HandlerList HANDLERS = new HandlerList();
/**
* The armor contents before. 0 is helmet, 3 is boots.
*/
@Getter
private final List<ItemStack> before;
/**
* The armor contents after. 0 is helmet, 3 is boots.
*/
@Getter
private final List<ItemStack> after;
/**
* Create a new ArmorChangeEvent.
*
* @param player The player.
* @param before The armor contents before.
* @param after The armor contents after.
*/
public ArmorChangeEvent(@NotNull final Player player,
@NotNull final List<ItemStack> before,
@NotNull final List<ItemStack> after) {
super(player);
this.before = before;
this.after = after;
}
/**
* Gets a list of handlers handling this event.
*
* @return A list of handlers handling this event.
*/
@Override
@NotNull
public HandlerList getHandlers() {
return HANDLERS;
}
/**
* Bukkit parity.
*
* @return The handler list.
*/
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@@ -5,10 +5,29 @@ import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* The armor equip event <b>does not contain information about the event.</b>
* <p>
* It is purely a trigger called whenever a player changes armor, you have to run
* your own checks.
* <p>
* The event is called before the player's inventory actually updates,
* so you can check a tick later to see the new contents.
*
* @see ArmorChangeEvent
*/
@Deprecated
public class ArmorEquipEvent extends PlayerEvent {
/**
* Bukkit parity.
*/
private static final HandlerList HANDLERS = new HandlerList();
/**
* Create a new ArmorEquipEvent.
*
* @param player The player.
*/
public ArmorEquipEvent(@NotNull final Player player) {
super(player);
}
@@ -25,6 +44,11 @@ public class ArmorEquipEvent extends PlayerEvent {
return HANDLERS;
}
/**
* Bukkit parity.
*
* @return The handler list.
*/
public static HandlerList getHandlerList() {
return HANDLERS;
}

View File

@@ -12,7 +12,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Event triggered when entity is killed by entity.
* Event called when an entity is killed by another entity.
* <p>
* Not sure why spigot doesn't have this event normally.
*/
public class EntityDeathByEntityEvent extends Event {
/**

View File

@@ -2,6 +2,9 @@ package com.willfp.eco.core.events;
import org.bukkit.event.Listener;
/**
* Manages listeners for a plugin.
*/
public interface EventManager {
/**
* Register a listener with bukkit.

View File

@@ -6,6 +6,10 @@ import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.jetbrains.annotations.NotNull;
/**
* Event similar to {@link PlayerExpChangeEvent}, except it
* isn't called if the exp is from a bottle.
*/
public class NaturalExpGainEvent extends Event {
/**
* Internal bukkit.

View File

@@ -1,15 +1,25 @@
package com.willfp.eco.core.events;
import org.bukkit.Location;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerMoveEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Event called when a player jumps.
*/
public class PlayerJumpEvent extends PlayerMoveEvent {
/**
* Internal bukkit.
*/
private static final HandlerList HANDLERS = new HandlerList();
/**
* The handled event.
*/
private final PlayerMoveEvent handle;
/**
* Create a new PlayerJumpEvent.
*
@@ -17,6 +27,8 @@ public class PlayerJumpEvent extends PlayerMoveEvent {
*/
public PlayerJumpEvent(@NotNull final PlayerMoveEvent event) {
super(event.getPlayer(), event.getFrom(), event.getTo());
this.handle = event;
}
/**
@@ -37,4 +49,36 @@ public class PlayerJumpEvent extends PlayerMoveEvent {
public static @NotNull HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public boolean isCancelled() {
return handle.isCancelled();
}
@Override
public void setCancelled(final boolean cancel) {
handle.setCancelled(cancel);
}
@NotNull
@Override
public Location getFrom() {
return handle.getFrom();
}
@Override
public void setFrom(@NotNull final Location from) {
handle.setFrom(from);
}
@Nullable
@Override
public Location getTo() {
return handle.getTo();
}
@Override
public void setTo(@NotNull final Location to) {
handle.setTo(to);
}
}

View File

@@ -1,12 +1,22 @@
package com.willfp.eco.core.extensions;
import com.willfp.eco.internal.extensions.ExtensionMetadata;
import com.willfp.eco.core.EcoPlugin;
import lombok.AccessLevel;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
/**
* An extension is a separate jar file that hooks into the base plugin jar.
* <p>
* If you take PlaceholderAPI as an example, the PAPI expansions are identical to
* extensions.
* <p>
* Syntactically, extensions are very similar to plugins in their own right, except that
* they are loaded by another plugin.
*
* @see <a href="https://ecoenchants.polymart.org">EcoEnchants extension examples.</a>
*/
public abstract class Extension {
/**
* The {@link EcoPlugin} that this extension is for.
@@ -74,6 +84,16 @@ public abstract class Extension {
return this.metadata.name();
}
/**
* Get the author of the extension.
*
* @return The author of the metadata attached to the extension.
*/
public final String getAuthor() {
Validate.notNull(metadata, "Metadata cannot be null!");
return this.metadata.author();
}
/**
* Get the version of the extension.
*

View File

@@ -3,11 +3,9 @@ package com.willfp.eco.core.extensions;
import java.util.Set;
/**
* Interface for extension loader.
* Some external plugins may modify extension loading for internal server purposes.
* Internal component to manage loading and unloading extensions.
*/
public interface ExtensionLoader {
/**
* Load all extensions.
*/

View File

@@ -0,0 +1,18 @@
package com.willfp.eco.core.extensions;
import org.jetbrains.annotations.NotNull;
/**
* The extension's metadata.
* <p>
* Stored as a record internally.
*
* @param version The extension version.
* @param name The extension name.
* @param author The extension's author.
*/
public record ExtensionMetadata(@NotNull String version,
@NotNull String name,
@NotNull String author) {
}

View File

@@ -3,16 +3,13 @@ package com.willfp.eco.core.extensions;
import org.jetbrains.annotations.NotNull;
/**
* Called when the extension is made incorrectly.
* Potential causes include:
* Missing or invalid extension.yml.
* Invalid filetype.
*/
public class MalformedExtensionException extends RuntimeException {
/**
* Create a new MalformedExtensionException.
* <p>
* Potential causes include:
* Missing or invalid extension.yml.
* Invalid filetype.
*
* @param errorMessage The error message to show.
*/

View File

@@ -3,6 +3,9 @@ package com.willfp.eco.core.factory;
import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
/**
* Factory to create metadata values for a specific plugin.
*/
public interface MetadataValueFactory {
/**
* Create a metadata value for a given plugin and object.

View File

@@ -3,6 +3,9 @@ package com.willfp.eco.core.factory;
import org.bukkit.NamespacedKey;
import org.jetbrains.annotations.NotNull;
/**
* Factory to create {@link NamespacedKey}s for a plugin.
*/
public interface NamespacedKeyFactory {
/**
* Create an {@link NamespacedKey} associated with an {@link com.willfp.eco.core.EcoPlugin}.

View File

@@ -5,6 +5,10 @@ import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
/**
* Factory to create runnables. Much cleaner syntax than instantiating
* {@link org.bukkit.scheduler.BukkitRunnable}s.
*/
public interface RunnableFactory {
/**
* Create a {@link RunnableTask}.

View File

@@ -0,0 +1,81 @@
package com.willfp.eco.core.fast;
import com.willfp.eco.core.Eco;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* FastItemStack contains methods to modify and read items faster than in default bukkit.
*/
public interface FastItemStack {
/**
* Get all enchantments on an item.
*
* @param checkStored If stored NBT should also be checked.
* @return A map of all enchantments.
*/
Map<Enchantment, Integer> getEnchantmentsOnItem(boolean checkStored);
/**
* Get the level of an enchantment on an item.
*
* @param enchantment The enchantment.
* @param checkStored If the stored NBT should also be checked.
* @return The enchantment level, or 0 if not found.
*/
int getLevelOnItem(@NotNull Enchantment enchantment,
boolean checkStored);
/**
* Set the item lore.
*
* @param lore The lore.
*/
void setLore(@Nullable List<String> lore);
/**
* Get the item lore.
*
* @return The lore.
*/
List<String> getLore();
/**
* Set the rework penalty.
*
* @param cost The rework penalty to set.
*/
void setRepairCost(int cost);
/**
* Get the rework penalty.
*.
* @return The rework penalty found on the item.
*/
int getRepairCost();
/**
* Get the Bukkit ItemStack again.
*
* @return The ItemStack.
*/
ItemStack unwrap();
/**
* Wrap an ItemStack to create a FastItemStack.
*
* @param itemStack The ItemStack.
* @return The FastItemStack.
*/
static FastItemStack wrap(final ItemStack itemStack) {
return Eco.getHandler().createFastItemStack(Objects.requireNonNullElseGet(itemStack, () -> new ItemStack(Material.AIR)));
}
}

View File

@@ -0,0 +1,29 @@
package com.willfp.eco.core.gui;
import com.willfp.eco.core.gui.menu.MenuBuilder;
import com.willfp.eco.core.gui.slot.SlotBuilder;
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Internal component used by {@link com.willfp.eco.core.gui.menu.Menu#builder(int)}
* and {@link com.willfp.eco.core.gui.slot.Slot#builder(ItemStack)}.
*/
public interface GUIFactory {
/**
* Create slot builder.
*
* @param provider The provider.
* @return The builder.
*/
SlotBuilder createSlotBuilder(@NotNull SlotProvider provider);
/**
* Create menu builder.
*
* @param rows The amount of rows.
* @return The builder.
*/
MenuBuilder createMenuBuilder(int rows);
}

View File

@@ -0,0 +1,19 @@
package com.willfp.eco.core.gui.menu;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.jetbrains.annotations.NotNull;
/**
* Interface to run on menu close.
*/
@FunctionalInterface
public interface CloseHandler {
/**
* Performs this operation on the given arguments.
*
* @param event The close event.
* @param menu The menu.
*/
void handle(@NotNull InventoryCloseEvent event,
@NotNull Menu menu);
}

View File

@@ -1,60 +0,0 @@
package com.willfp.eco.core.gui.menu;
import com.willfp.eco.core.gui.slot.Slot;
import com.willfp.eco.core.items.builder.ItemStackBuilder;
import com.willfp.eco.internal.gui.FillerSlot;
import com.willfp.eco.util.ListUtils;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class FillerMask {
/**
* Mask.
*/
@Getter
private final List<List<Slot>> mask;
/**
* Create a new filler mask.
*
* @param material The mask material.
* @param pattern The pattern.
*/
public FillerMask(@NotNull final Material material,
@NotNull final String... pattern) {
if (material == Material.AIR) {
throw new IllegalArgumentException("Material cannot be air!");
}
mask = ListUtils.create2DList(6, 9);
ItemStack itemStack = new ItemStackBuilder(material)
.setDisplayName("&r")
.build();
int row = 0;
for (String patternRow : pattern) {
int column = 0;
if (patternRow.length() != 9) {
throw new IllegalArgumentException("Invalid amount of columns in pattern!");
}
for (char c : patternRow.toCharArray()) {
if (c == '0') {
mask.get(row).set(column, null);
} else if (c == '1') {
mask.get(row).set(column, new FillerSlot(itemStack));
} else {
throw new IllegalArgumentException("Invalid character in pattern! (Must only be 0 and 1)");
}
column++;
}
row++;
}
}
}

View File

@@ -1,20 +1,19 @@
package com.willfp.eco.core.gui.menu;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.gui.slot.Slot;
import com.willfp.eco.internal.gui.EcoMenu;
import com.willfp.eco.internal.gui.FillerSlot;
import com.willfp.eco.util.ListUtils;
import com.willfp.eco.util.StringUtils;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.function.Consumer;
/**
* GUI version of {@link Inventory}.
* <p>
* A menu contains slots and is 1-indexed. (Top row has index 1, bottom row has index 6).
*/
public interface Menu {
/**
* Get the amount of rows.
@@ -48,99 +47,21 @@ public interface Menu {
*/
Inventory open(@NotNull Player player);
/**
* Get captive items.
*
* @param player The player.
* @return The items.
*/
List<ItemStack> getCaptiveItems(@NotNull Player player);
/**
* Create a builder with a given amount of rows.
*
* @param rows The rows.
* @return The builder.
*/
static Builder builder(final int rows) {
return new Builder(rows);
}
class Builder {
/**
* The amount of rows.
*/
private final int rows;
/**
* The title.
*/
private String title = "Menu";
/**
* The mask slots.
*/
private List<List<Slot>> maskSlots;
/**
* The slots.
*/
private final List<List<Slot>> slots;
/**
* The close event handler.
*/
private Consumer<InventoryCloseEvent> onClose = (event) -> {
};
Builder(final int rows) {
this.rows = rows;
this.slots = ListUtils.create2DList(rows, 9);
this.maskSlots = ListUtils.create2DList(rows, 9);
}
public Builder setTitle(@NotNull final String title) {
this.title = StringUtils.translate(title);
return this;
}
public Builder setSlot(final int row,
final int column,
@NotNull final Slot slot) {
if (row < 1 || row > this.rows) {
throw new IllegalArgumentException("Invalid row number!");
}
if (column < 1 || column > 9) {
throw new IllegalArgumentException("Invalid column number!");
}
slots.get(row - 1).set(column - 1, slot);
return this;
}
public Builder setMask(@NotNull final FillerMask mask) {
this.maskSlots = mask.getMask();
return this;
}
public Builder onClose(@NotNull final Consumer<InventoryCloseEvent> action) {
this.onClose = action;
return this;
}
public Menu build() {
List<List<Slot>> finalSlots = maskSlots;
for (int i = 0; i < slots.size(); i++) {
for (int j = 0; j < slots.get(i).size(); j++) {
Slot slot = slots.get(i).get(j);
if (slot != null) {
finalSlots.get(i).set(j, slot);
}
}
}
for (List<Slot> finalSlot : finalSlots) {
for (int j = 0; j < finalSlot.size(); j++) {
if (finalSlot.get(j) == null) {
finalSlot.set(j, new FillerSlot(new ItemStack(Material.AIR)));
}
}
}
return new EcoMenu(rows, finalSlots, title, onClose);
}
static MenuBuilder builder(final int rows) {
return Eco.getHandler().getGUIFactory().createMenuBuilder(rows);
}
}

View File

@@ -0,0 +1,75 @@
package com.willfp.eco.core.gui.menu;
import com.willfp.eco.core.gui.slot.FillerMask;
import com.willfp.eco.core.gui.slot.Slot;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
/**
* Builder to create menus.
*/
public interface MenuBuilder {
/**
* Set the menu title.
*
* @param title The title.
* @return The builder.
*/
MenuBuilder setTitle(@NotNull String title);
/**
* Set a slot.
*
* @param row The row.
* @param column The column.
* @param slot The slot.
* @return The builder.
*/
MenuBuilder setSlot(int row,
int column,
@NotNull Slot slot);
/**
* Run function to modify the builder.
*
* @param modifier The modifier.
* @return The builder.
*/
MenuBuilder modfiy(@NotNull Consumer<MenuBuilder> modifier);
/**
* Set the menu mask.
*
* @param mask The mask.
* @return The builder.
*/
MenuBuilder setMask(@NotNull FillerMask mask);
/**
* Set the menu close handler.
*
* @param action The handler.
* @return The builder.
*/
default MenuBuilder onClose(@NotNull Consumer<InventoryCloseEvent> action) {
onClose((event, menu) -> action.accept(event));
return this;
}
/**
* Set the menu close handler.
*
* @param action The handler.
* @return The builder.
*/
MenuBuilder onClose(@NotNull CloseHandler action);
/**
* Build the menu.
*
* @return The menu.
*/
Menu build();
}

View File

@@ -0,0 +1,85 @@
package com.willfp.eco.core.gui.slot;
import com.willfp.eco.core.items.builder.ItemStackBuilder;
import com.willfp.eco.util.ListUtils;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
/**
* Mask of filler slots.
* <p>
* A pattern consists of 1s and 0s, where a 1 is a filler slot,
* and a 0 isn't.
* <p>
* For example, creating a filler mask for a single-chest sized menu would look like this:
* <p>
* new FillerMask(
* material,
* "11111111"
* "10000001"
* "11111111"
* );
*/
public class FillerMask {
/**
* Mask.
*/
@Getter
private final List<List<Slot>> mask;
/**
* Create a new filler mask.
*
* @param material The mask material.
* @param pattern The pattern.
*/
public FillerMask(@NotNull final Material material,
@NotNull final String... pattern) {
this(new MaskMaterials(material), pattern);
}
/**
* Create a new filler mask.
*
* @param materials The mask materials.
* @param pattern The pattern.
*/
public FillerMask(@NotNull final MaskMaterials materials,
@NotNull final String... pattern) {
if (Arrays.stream(materials.materials()).anyMatch(material -> material == Material.AIR)) {
throw new IllegalArgumentException("Materials cannot be air!");
}
mask = ListUtils.create2DList(6, 9);
for (int i = 0; i < materials.materials().length; i++) {
ItemStack itemStack = new ItemStackBuilder(materials.materials()[i])
.setDisplayName("&r")
.build();
int row = 0;
for (String patternRow : pattern) {
int column = 0;
if (patternRow.length() != 9) {
throw new IllegalArgumentException("Invalid amount of columns in pattern!");
}
for (char c : patternRow.toCharArray()) {
if (c == '0') {
mask.get(row).set(column, null);
} else if (c == Character.forDigit(i + 1, 10)) {
mask.get(row).set(column, new FillerSlot(itemStack));
}
column++;
}
row++;
}
}
}
}

View File

@@ -0,0 +1,38 @@
package com.willfp.eco.core.gui.slot;
import lombok.Getter;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* A filler slot is a slot that does nothing when clicked.
* <p>
* Useful for backgrounds.
*/
public class FillerSlot implements Slot {
/**
* The ItemStack.
*/
@Getter
private final ItemStack itemStack;
/**
* Create new filler slot.
*
* @param itemStack The ItemStack.
*/
public FillerSlot(@NotNull final ItemStack itemStack) {
this.itemStack = itemStack;
}
@Override
public ItemStack getItemStack(@NotNull final Player player) {
return itemStack;
}
@Override
public boolean isCaptive() {
return false;
}
}

View File

@@ -0,0 +1,14 @@
package com.willfp.eco.core.gui.slot;
import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;
/**
* Mask materials store a set of materials which can be accessed by
* a filler mask.
*
* @param materials The materials.
*/
public record MaskMaterials(@NotNull Material... materials) {
}

View File

@@ -1,14 +1,17 @@
package com.willfp.eco.core.gui.slot;
import com.willfp.eco.internal.gui.EcoSlot;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.function.BiConsumer;
import java.util.function.Function;
/**
* A slot is an item in a GUI that can handle clicks.
*/
public interface Slot {
/**
* Get the ItemStack that would be shown to a player.
@@ -18,14 +21,30 @@ public interface Slot {
*/
ItemStack getItemStack(@NotNull Player player);
/**
* If the slot is captive. (Can items be placed in it).
*
* @return If captive.
*/
boolean isCaptive();
/**
* Create a builder for an ItemStack.
*
* @return The builder.
*/
static SlotBuilder builder() {
return Eco.getHandler().getGUIFactory().createSlotBuilder((player, menu) -> new ItemStack(Material.AIR));
}
/**
* Create a builder for an ItemStack.
*
* @param itemStack The ItemStack.
* @return The builder.
*/
static Builder builder(@NotNull final ItemStack itemStack) {
return new Builder((player) -> itemStack);
static SlotBuilder builder(@NotNull final ItemStack itemStack) {
return Eco.getHandler().getGUIFactory().createSlotBuilder((player, menu) -> itemStack);
}
/**
@@ -34,72 +53,17 @@ public interface Slot {
* @param provider The provider.
* @return The builder.
*/
static Builder builder(@NotNull final Function<Player, ItemStack> provider) {
return new Builder(provider);
static SlotBuilder builder(@NotNull final Function<Player, ItemStack> provider) {
return Eco.getHandler().getGUIFactory().createSlotBuilder((player, menu) -> provider.apply(player));
}
class Builder {
/**
* Provider.
*/
private final Function<Player, ItemStack> provider;
/**
* Left click handler.
*/
private BiConsumer<InventoryClickEvent, Slot> onLeftClick = null;
/**
* Right click handler.
*/
private BiConsumer<InventoryClickEvent, Slot> onRightClick = null;
/**
* Shift-Left-Click handler.
*/
private BiConsumer<InventoryClickEvent, Slot> onShiftLeftClick = null;
/**
* Shift-Right-Click handler.
*/
private BiConsumer<InventoryClickEvent, Slot> onShiftRightClick = null;
/**
* Middle click handler.
*/
private BiConsumer<InventoryClickEvent, Slot> onMiddleClick = null;
Builder(@NotNull final Function<Player, ItemStack> provider) {
this.provider = provider;
}
public Builder onLeftClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
this.onLeftClick = action;
return this;
}
public Builder onRightClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
this.onRightClick = action;
return this;
}
public Builder onShiftLeftClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
this.onShiftLeftClick = action;
return this;
}
public Builder onShiftRightClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
this.onShiftRightClick = action;
return this;
}
public Builder onMiddleClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
this.onMiddleClick = action;
return this;
}
public Slot build() {
return new EcoSlot(provider, onLeftClick, onRightClick, onShiftLeftClick, onShiftRightClick, onMiddleClick);
}
/**
* Create a builder for a player-specific ItemStack.
*
* @param provider The provider.
* @return The builder.
*/
static SlotBuilder builder(@NotNull final SlotProvider provider) {
return Eco.getHandler().getGUIFactory().createSlotBuilder(provider);
}
}

View File

@@ -0,0 +1,125 @@
package com.willfp.eco.core.gui.slot;
import com.willfp.eco.core.gui.slot.functional.SlotHandler;
import com.willfp.eco.core.gui.slot.functional.SlotModifier;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
import java.util.function.BiConsumer;
/**
* Builder to create slots.
*/
public interface SlotBuilder {
/**
* Set click handler.
*
* @param action The handler.
* @return The builder.
*/
default SlotBuilder onLeftClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
return onLeftClick((event, slot, menu) -> action.accept(event, slot));
}
/**
* Set click handler.
*
* @param handler The handler.
* @return The builder.
*/
SlotBuilder onLeftClick(@NotNull SlotHandler handler);
/**
* Set click handler.
*
* @param action The handler.
* @return The builder.
*/
default SlotBuilder onRightClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
return onRightClick((event, slot, menu) -> action.accept(event, slot));
}
/**
* Set click handler.
*
* @param handler The handler.
* @return The builder.
*/
SlotBuilder onRightClick(@NotNull SlotHandler handler);
/**
* Set click handler.
*
* @param action The handler.
* @return The builder.
*/
default SlotBuilder onShiftLeftClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
return onShiftLeftClick((event, slot, menu) -> action.accept(event, slot));
}
/**
* Set click handler.
*
* @param handler The handler.
* @return The builder.
*/
SlotBuilder onShiftLeftClick(@NotNull SlotHandler handler);
/**
* Set click handler.
*
* @param action The handler.
* @return The builder.
*/
default SlotBuilder onShiftRightClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
return onShiftRightClick((event, slot, menu) -> action.accept(event, slot));
}
/**
* Set click handler.
*
* @param handler The handler.
* @return The builder.
*/
SlotBuilder onShiftRightClick(@NotNull SlotHandler handler);
/**
* Set click handler.
*
* @param action The handler.
* @return The builder.
*/
default SlotBuilder onMiddleClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
return onMiddleClick((event, slot, menu) -> action.accept(event, slot));
}
/**
* Set click handler.
*
* @param handler The handler.
* @return The builder.
*/
SlotBuilder onMiddleClick(@NotNull SlotHandler handler);
/**
* Modify the ItemStack.
*
* @param modifier The modifier.
* @return The builder.
*/
SlotBuilder setModifier(@NotNull SlotModifier modifier);
/**
* Set slot to be a captive slot.
*
* @return The builder.
*/
SlotBuilder setCaptive();
/**
* Build the slot.
*
* @return The slot.
*/
Slot build();
}

View File

@@ -0,0 +1,23 @@
package com.willfp.eco.core.gui.slot.functional;
import com.willfp.eco.core.gui.menu.Menu;
import com.willfp.eco.core.gui.slot.Slot;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
/**
* Interface to run on slot click.
*/
@FunctionalInterface
public interface SlotHandler {
/**
* Performs this operation on the given arguments.
*
* @param event The click event.
* @param slot The slot
* @param menu The menu.
*/
void handle(@NotNull InventoryClickEvent event,
@NotNull Slot slot,
@NotNull Menu menu);
}

View File

@@ -0,0 +1,23 @@
package com.willfp.eco.core.gui.slot.functional;
import com.willfp.eco.core.gui.menu.Menu;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Interface to run on slot modify.
*/
@FunctionalInterface
public interface SlotModifier {
/**
* Performs this operation on the given arguments.
*
* @param player The player.
* @param menu The menu.
* @param previous The previous ItemStack.
*/
void modify(@NotNull Player player,
@NotNull Menu menu,
@NotNull ItemStack previous);
}

View File

@@ -0,0 +1,22 @@
package com.willfp.eco.core.gui.slot.functional;
import com.willfp.eco.core.gui.menu.Menu;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Interface to run on slot display.
*/
@FunctionalInterface
public interface SlotProvider {
/**
* Performs this operation on the given arguments.
*
* @param player The player.
* @param menu The menu.
* @return The ItemStack.
*/
ItemStack provide(@NotNull Player player,
@NotNull Menu menu);
}

View File

@@ -1,8 +1,12 @@
package com.willfp.eco.core.integrations;
/**
* Abstract class for integrations.
*/
public interface Integration {
/**
* Get the name of integration.
*
* @return The name.
*/
String getPluginName();

View File

@@ -3,6 +3,11 @@ package com.willfp.eco.core.integrations;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
/**
* An integration loader runs a runnable only if a specific plugin is present on the server.
* <p>
* Used by {@link com.willfp.eco.core.EcoPlugin} to load integrations.
*/
public class IntegrationLoader {
/**
* The lambda to be ran if the plugin is present.

View File

@@ -9,6 +9,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/**
* Class to handle anticheat integrations.
*/
@UtilityClass
public class AnticheatManager {
/**

View File

@@ -4,6 +4,9 @@ import com.willfp.eco.core.integrations.Integration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Wrapper class for anticheat integrations.
*/
public interface AnticheatWrapper extends Integration {
/**
* Exempt a player from checks.

View File

@@ -10,6 +10,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/**
* Class to handle antigrief integrations.
*/
@UtilityClass
public class AntigriefManager {
/**

View File

@@ -6,6 +6,9 @@ import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
/**
* Wrapper class for antigrief integrations.
*/
public interface AntigriefWrapper extends Integration {
/**
* Can player break block.

View File

@@ -0,0 +1,38 @@
package com.willfp.eco.core.integrations.customitems;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/**
* Class to handle custom item integrations.
*/
@UtilityClass
public class CustomItemsManager {
/**
* A set of all registered integrations.
*/
private final Set<CustomItemsWrapper> registered = new HashSet<>();
/**
* Register a new integration.
*
* @param integration The integration to register.
*/
public void register(@NotNull final CustomItemsWrapper integration) {
registered.add(integration);
}
/**
* Register all the custom items for a specific plugin into eco.
*
* @see com.willfp.eco.core.items.Items
*/
public void registerAllItems() {
for (CustomItemsWrapper customItemsWrapper : registered) {
customItemsWrapper.registerAllItems();
}
}
}

View File

@@ -0,0 +1,13 @@
package com.willfp.eco.core.integrations.customitems;
/**
* Wrapper class for custom item integrations.
*/
public interface CustomItemsWrapper {
/**
* Register all the custom items for a specific plugin into eco.
*
* @see com.willfp.eco.core.items.Items
*/
void registerAllItems();
}

View File

@@ -8,6 +8,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/**
* Class to handle mcmmo integrations.
*/
@UtilityClass
public class McmmoManager {
/**

View File

@@ -4,6 +4,9 @@ import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull;
/**
* Wrapper class for mcmmo integrations.
*/
public interface McmmoWrapper {
/**
* Get bonus drop count of block.

View File

@@ -8,6 +8,11 @@ import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
/**
* A {@link PlaceholderEntry} is a placeholder in and of itself.
* <p>
* It should be fairly straightforward.
*/
public class PlaceholderEntry {
/**
* The name of the placeholder, used in lookups.
@@ -72,4 +77,11 @@ public class PlaceholderEntry {
public boolean requiresPlayer() {
return requiresPlayer;
}
/**
* Register the placeholder.
*/
public void register() {
PlaceholderManager.registerPlaceholder(this);
}
}

View File

@@ -5,6 +5,9 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Wrapper class for placeholder integrations.
*/
public interface PlaceholderIntegration extends Integration {
/**
* Register the integration with the specified plugin.

View File

@@ -10,6 +10,9 @@ import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
* Class to handle placeholder integrations.
*/
@UtilityClass
public class PlaceholderManager {
/**

View File

@@ -8,6 +8,15 @@ import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* A custom item has 3 components:
*
* <ul>
* <li>The key to identify it</li>
* <li>The test to check if any item is this custom item</li>
* <li>The actual custom item {@link ItemStack}</li>
* </ul>
*/
public class CustomItem implements TestableItem {
/**
* The key.
@@ -18,7 +27,7 @@ public class CustomItem implements TestableItem {
/**
* The test for ItemStacks to pass.
*/
private final Predicate<ItemStack> test;
private final Predicate<@NotNull ItemStack> test;
/**
* Example Item: what the user should see.
@@ -33,7 +42,7 @@ public class CustomItem implements TestableItem {
* @param item The example ItemStacks.
*/
public CustomItem(@NotNull final NamespacedKey key,
@NotNull final Predicate<ItemStack> test,
@NotNull final Predicate<@NotNull ItemStack> test,
@NotNull final ItemStack item) {
this.key = key;
this.test = test;
@@ -42,6 +51,10 @@ public class CustomItem implements TestableItem {
@Override
public boolean matches(@Nullable final ItemStack itemStack) {
if (itemStack == null) {
return false;
}
return test.test(itemStack);
}

View File

@@ -1,19 +1,30 @@
package com.willfp.eco.core.items;
import com.willfp.eco.core.items.builder.ItemBuilder;
import com.willfp.eco.core.items.builder.ItemStackBuilder;
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
import com.willfp.eco.core.recipe.parts.MaterialTestableItem;
import com.willfp.eco.core.recipe.parts.ModifiedTestableItem;
import com.willfp.eco.core.recipe.parts.TestableStack;
import com.willfp.eco.util.NamespacedKeyUtils;
import lombok.experimental.UtilityClass;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Class to manage all custom and vanilla items.
*/
@UtilityClass
@SuppressWarnings("deprecation")
public final class Items {
/**
* All recipe parts.
@@ -31,6 +42,15 @@ public final class Items {
REGISTRY.put(key, part);
}
/**
* Remove an item.
*
* @param key The key of the recipe part.
*/
public void removeCustomItem(@NotNull final NamespacedKey key) {
REGISTRY.remove(key);
}
/**
* Lookup item from string.
* <p>
@@ -40,36 +60,103 @@ public final class Items {
* @return The found testable item, or an empty item if not found.
*/
public TestableItem lookup(@NotNull final String key) {
String[] split = key.toLowerCase().split(":");
if (key.contains("?")) {
String[] options = key.split("\\?");
for (String option : options) {
TestableItem lookup = lookup(option);
if (!(lookup instanceof EmptyTestableItem)) {
return lookup;
}
}
return new EmptyTestableItem();
}
String[] args = key.split(" ");
if (args.length == 0) {
return new EmptyTestableItem();
}
TestableItem item = null;
String[] split = args[0].toLowerCase().split(":");
if (split.length == 1) {
Material material = Material.getMaterial(key.toUpperCase());
Material material = Material.getMaterial(args[0].toUpperCase());
if (material == null || material == Material.AIR) {
return new EmptyTestableItem();
}
return new MaterialTestableItem(material);
item = new MaterialTestableItem(material);
}
if (split.length == 2) {
CustomItem part = REGISTRY.get(new NamespacedKey(split[0], split[1]));
CustomItem part = REGISTRY.get(NamespacedKeyUtils.create(split[0], split[1]));
if (part == null) {
Material material = Material.getMaterial(split[0].toUpperCase());
if (material == null || material == Material.AIR) {
return new EmptyTestableItem();
}
return new TestableStack(new MaterialTestableItem(material), Integer.parseInt(split[1]));
item = new TestableStack(new MaterialTestableItem(material), Integer.parseInt(split[1]));
} else {
return part;
item = part;
}
}
if (split.length == 3) {
CustomItem part = REGISTRY.get(new NamespacedKey(split[0], split[1]));
return part == null ? new EmptyTestableItem() : new TestableStack(part, Integer.parseInt(split[2]));
CustomItem part = REGISTRY.get(NamespacedKeyUtils.create(split[0], split[1]));
item = part == null ? new EmptyTestableItem() : new TestableStack(part, Integer.parseInt(split[2]));
}
return new EmptyTestableItem();
if (item == null || item instanceof EmptyTestableItem) {
return new EmptyTestableItem();
}
String[] enchantArgs = Arrays.copyOfRange(args, 1, args.length);
Map<Enchantment, Integer> requiredEnchantments = new HashMap<>();
for (String enchantArg : enchantArgs) {
String[] enchantArgSplit = enchantArg.split(":");
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(enchantArgSplit[0].toLowerCase()));
int level = Integer.parseInt(enchantArgSplit[1]);
requiredEnchantments.put(enchantment, level);
}
if (requiredEnchantments.isEmpty()) {
return item;
}
ItemBuilder builder = new ItemStackBuilder(item.getItem());
requiredEnchantments.forEach(builder::addEnchantment);
ItemStack example = builder.build();
return new ModifiedTestableItem(
item,
itemStack -> {
if (!itemStack.hasItemMeta()) {
return false;
}
ItemMeta meta = itemStack.getItemMeta();
assert meta != null;
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
if (!meta.hasEnchant(entry.getKey())) {
return false;
}
if (meta.getEnchantLevel(entry.getKey()) < entry.getValue()) {
return false;
}
}
return true;
},
example
);
}
/**
@@ -86,4 +173,13 @@ public final class Items {
}
return false;
}
/**
* Get all registered custom items.
*
* @return A set of all items.
*/
public Set<CustomItem> getCustomItems() {
return new HashSet<>(REGISTRY.values());
}
}

View File

@@ -3,6 +3,9 @@ package com.willfp.eco.core.items;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
/**
* An item with a test to see if any item is that item.
*/
public interface TestableItem {
/**
* If an ItemStack matches the recipe part.

View File

@@ -1,6 +1,5 @@
package com.willfp.eco.internal.items;
package com.willfp.eco.core.items.builder;
import com.willfp.eco.core.items.builder.ItemBuilder;
import com.willfp.eco.util.StringUtils;
import lombok.AccessLevel;
import lombok.Getter;
@@ -19,6 +18,12 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
/**
* Abstract item builder class to build items.
*
* @param <T> The meta type.
* @param <U> Itself.
*/
@SuppressWarnings("unchecked")
public abstract class AbstractItemStackBuilder<T extends ItemMeta, U extends AbstractItemStackBuilder<T, U>> implements ItemBuilder {
/**
@@ -80,7 +85,7 @@ public abstract class AbstractItemStackBuilder<T extends ItemMeta, U extends Abs
@Override
public U setDisplayName(@NotNull final String name) {
meta.setDisplayName(StringUtils.translate(name));
meta.setDisplayName(StringUtils.format(name));
return (U) this;
}
@@ -95,7 +100,7 @@ public abstract class AbstractItemStackBuilder<T extends ItemMeta, U extends Abs
public U addLoreLine(@NotNull final String line) {
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
assert lore != null;
lore.add(StringUtils.translate(line));
lore.add(StringUtils.format(line));
meta.setLore(lore);
return (U) this;
@@ -113,7 +118,7 @@ public abstract class AbstractItemStackBuilder<T extends ItemMeta, U extends Abs
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
assert lore != null;
for (String line : lines) {
lore.add(StringUtils.translate(line));
lore.add(StringUtils.format(line));
}
meta.setLore(lore);

View File

@@ -1,11 +1,15 @@
package com.willfp.eco.core.items.builder;
import com.willfp.eco.internal.items.AbstractItemStackBuilder;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
/**
* Class to build enchanted books.
*/
public class EnchantedBookBuilder extends AbstractItemStackBuilder<EnchantmentStorageMeta, EnchantedBookBuilder> {
/**
* Create a new EnchantedBookBuilder.
@@ -26,4 +30,16 @@ public class EnchantedBookBuilder extends AbstractItemStackBuilder<EnchantmentSt
this.getMeta().addStoredEnchant(enchantment, level, true);
return this;
}
/**
* Add an enchantment to the item.
*
* @param enchantment The enchantment.
* @param level The level.
* @return The builder.
*/
public EnchantedBookBuilder addStoredEnchantment(@NotNull final Supplier<Enchantment> enchantment,
final Supplier<Integer> level) {
return this.addStoredEnchantment(enchantment.get(), level.get());
}
}

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