Compare commits

..

229 Commits

Author SHA1 Message Date
Auxilor
08c14f4def Cleaned up BentoBox 2021-11-02 19:28:19 +00:00
Auxilor
0fa6f972c0 Fixed BentoBox 2021-11-02 19:26:34 +00:00
Auxilor
8837fecfa0 Added support for BentoBox 2021-11-02 19:24:34 +00:00
Auxilor
af1841770e (Hopefully) fixed HologramCMI 2021-11-02 18:54:21 +00:00
Auxilor
1d85dbf08d Altered rate limit settings 2021-11-02 18:52:57 +00:00
Auxilor
ba9812534a Increased timeframe to 2 2021-11-02 18:46:28 +00:00
Auxilor
1f95a33385 Added log errors option for async display 2021-11-02 18:39:29 +00:00
Auxilor
bc652a8154 MySQLDataHandler changes 2021-11-02 18:37:01 +00:00
Auxilor
0c2e1f0cae Fixed ServerUtils 2021-11-02 18:29:17 +00:00
Auxilor
39d6eb7f9a Updated to 6.13.0 2021-11-02 18:17:57 +00:00
Auxilor
61bae6de55 Rearranged config.yml 2021-11-02 18:17:40 +00:00
Auxilor
aa4ac4c6d1 Added option to set rate limit timeframe 2021-11-02 17:44:57 +00:00
Auxilor
7141b12e95 Removed redundant explicit type 2021-11-02 17:42:27 +00:00
Auxilor
2382548629 Added in rate limiting for PacketWindowItems.kt 2021-11-02 17:39:41 +00:00
Auxilor
0c4bd182f7 Ignored async exceptions in PacketWindowItems.kt 2021-11-02 17:09:48 +00:00
Auxilor
e90e053b45 Added emergency async display and ServerUtils 2021-11-02 16:50:04 +00:00
Auxilor
742c1abb00 Cleaned up async display 2021-11-02 14:10:57 +00:00
Auxilor
c0686ca386 Added guava and asynchronous window items processing 2021-11-02 13:53:30 +00:00
Auxilor
db2ea7daa9 Updated to 6.12.2 2021-11-02 09:24:23 +00:00
Auxilor
ed4f0b2ab6 Fixed EconomyManager and ListUtils 2021-11-02 09:24:16 +00:00
Auxilor
6decc68d1b Updated to 6.12.1 2021-11-02 08:30:39 +00:00
Auxilor
1e061313a4 Codestyle 2021-11-02 08:30:27 +00:00
Auxilor
4762004e94 @NotNull'ed PlayerProfile#read 2021-11-02 08:29:00 +00:00
Auxilor
0d9889ef43 Fixed paste calling the callback three times 2021-11-01 21:14:56 +00:00
Auxilor
b2a23e80a1 Added missing nullable annotation 2021-11-01 21:06:50 +00:00
Auxilor
0e439db7b3 Auto-registered PersistentDataKeys 2021-11-01 21:01:57 +00:00
Auxilor
f615006b23 Added missing PlayerProfile javadoc 2021-11-01 21:00:58 +00:00
Auxilor
d952dbc61b Added ListUtils#listToFrequencyMap 2021-11-01 20:00:46 +00:00
Auxilor
d95a96f4c6 Added in support for economy via vault 2021-11-01 19:55:47 +00:00
Auxilor
33940f5778 Improved MySQLDataHandler.kt 2021-11-01 19:38:30 +00:00
Auxilor
173d04595f Removed duplicate uuid field from Players table 2021-11-01 19:04:16 +00:00
Auxilor
c7c4ca3777 Updated plugin.yml 2021-11-01 19:02:40 +00:00
Auxilor
cbf7316db9 Fixed public static variable in display 2021-11-01 18:55:01 +00:00
Auxilor
601cadd582 Fixed weird IntelliJ bug 2021-11-01 18:54:25 +00:00
Auxilor
877647db03 Fixed various codestyle issues 2021-11-01 18:53:36 +00:00
Auxilor
81196bb132 Added PotionUtils 2021-11-01 18:44:44 +00:00
Auxilor
ef701f1f86 Added BlockUtils#isPlayerPlaced 2021-11-01 18:38:58 +00:00
Auxilor
58d8f72cf5 Fixed javadoc 2021-11-01 16:21:44 +00:00
Auxilor
3abf916f18 Fixed SuperiorSkyblock2 integration 2021-11-01 16:18:31 +00:00
Auxilor
b459a746e3 Merge branch 'master' into develop
# Conflicts:
#	eco-core/core-plugin/build.gradle
2021-11-01 16:15:00 +00:00
Will FP
30c37078a2 Merge pull request #47
Added SuperiorSkyblock2 Antigrief integration
2021-11-01 16:14:35 +00:00
Auxilor
36ccfb5fc6 Fixed McmmoIntegrationImpl.kt 2021-11-01 16:13:51 +00:00
Auxilor
c84f1a060a Fixed KingdomsX version 2021-11-01 16:12:23 +00:00
Auxilor
d8d5609f6b Renamed consumer to callback 2021-11-01 16:09:23 +00:00
Auxilor
462abd46c6 Marked Handler as internal 2021-11-01 16:07:14 +00:00
Auxilor
e89008cf97 Fixed SkullUtils#getSkullTexture 2021-11-01 16:00:38 +00:00
Auxilor
d34e43797d Registering a duplicate key will now replace the existing key 2021-11-01 15:51:22 +00:00
Auxilor
63ee83c795 Added Essentials / CMI AFK integrations 2021-11-01 15:50:10 +00:00
Auxilor
2eec17698e Updated paste 2021-11-01 15:34:02 +00:00
Auxilor
ad52c2a086 Improved EcoPlayerProfileHandler.kt 2021-11-01 15:31:10 +00:00
Auxilor
6e482cccda Registered player name key 2021-11-01 15:24:11 +00:00
Auxilor
899b4297f7 Added saved display name utils with persistent meta 2021-11-01 14:17:29 +00:00
Auxilor
ceb95e20b5 Added in hologram integrations for CMI/GHolo/HolographicDisplays 2021-11-01 14:09:41 +00:00
Auxilor
bdfeb9a0ab Updated to 6.12.0 2021-11-01 13:29:03 +00:00
Auxilor
e0707e2afa Added missing handler implementations 2021-11-01 13:28:51 +00:00
Auxilor
e8048f5a0a Added in persistent data storage 2021-11-01 13:25:14 +00:00
0ft3n
a36018e31a Merge branch 'Auxilor:master' into master 2021-10-27 22:45:29 +03:00
_OfTeN_
a34c63161d Added SuperiorSkyblock2 Antigrief integration 2021-10-27 22:44:45 +03:00
Auxilor
2eb350977c Updated to 6.11.2 2021-10-26 19:51:21 +01:00
Auxilor
8a89a63c5f PacketSetCreativeSlot and PacketSetSlot now clear frames 2021-10-26 19:51:06 +01:00
Auxilor
5c26e6e782 DisplayFrames now include the ItemStacks as well as the hashes: larger memory footprint should be fine with ttl and frequent clearing 2021-10-26 19:49:49 +01:00
Auxilor
f88b914fa6 Fixed gradient modifier issues 2021-10-26 19:41:38 +01:00
Auxilor
15ff6b3ea3 Merge branch 'master' into develop 2021-10-26 19:28:37 +01:00
Auxilor
b14eed696c Added alice anticheat support 2021-10-26 19:21:34 +01:00
Auxilor
cffae33c87 StringUtils change 2021-10-26 19:11:01 +01:00
Auxilor
adf6d1c800 Updated to 6.11.1 2021-10-15 10:27:58 +01:00
Auxilor
2b7c8962e7 Merge remote-tracking branch 'origin/master' 2021-10-15 10:27:51 +01:00
Auxilor
b60cbfce2c Fixed unpredicatable config behaviour 2021-10-15 10:27:44 +01:00
Auxilor
910ad18703 Updated towny 2021-10-15 10:25:32 +01:00
Auxilor
8a4a71ebc1 Updated lands integration 2021-10-15 10:24:18 +01:00
Will FP
2e748b1723 Update README.md 2021-10-12 20:12:09 +01:00
Auxilor
cb28726bc3 Cleaned up Multiverse-Inventories integration 2021-10-12 12:04:52 +01:00
Auxilor
c0c20d63bb Merge remote-tracking branch 'origin/master' into develop 2021-10-12 11:59:26 +01:00
Will FP
3b11610c45 Merge pull request #44
Multiverse-Inventories integration
2021-10-12 11:58:41 +01:00
Auxilor
232048022e Added extra config constructors 2021-10-12 11:51:22 +01:00
Auxilor
9abfe0ab01 Updated to 6.11.0 2021-10-12 11:36:07 +01:00
Auxilor
e7ac05278c Added lots of display frame options 2021-10-12 11:31:02 +01:00
Auxilor
85ba40c279 Added PluginLike, allowing extensions to have their own configs 2021-10-12 11:17:58 +01:00
_OfTeN_
1acf86492e Added Multiverse-Inventories integration (additional ArmorChangeEvent call for all effect to reapply for new players inventory. 2021-10-12 11:09:09 +03:00
Auxilor
4609d38389 Updated to 6.10.1 2021-10-08 10:50:57 +01:00
Auxilor
2d6836cc93 Moved frames to only affect player inventories 2021-10-08 10:50:47 +01:00
Auxilor
8e21617345 Finished up ChatComponent 2021-10-07 20:50:15 +01:00
Auxilor
2f99a17d02 TODO: Finish Components 2021-10-07 16:16:07 +01:00
Auxilor
34edf1d7b4 Switched mapChildrenDeep to mapChildren 2021-10-07 16:01:49 +01:00
Auxilor
be85ba5706 Fixed Stack Overflow 2021-10-07 15:44:59 +01:00
Auxilor
b817b00ca4 Updated ChatComponent to include siblings 2021-10-07 15:37:35 +01:00
Auxilor
ee02528abc Downgraded Reflections 2021-10-07 15:07:24 +01:00
Auxilor
794948c8f9 Altered Reflections constructor (again) 2021-10-07 15:01:35 +01:00
Auxilor
7c70dec2e7 Added AntigriefManager#unregister 2021-10-07 15:00:54 +01:00
Auxilor
d1f20b7111 Updated Reflections constructor 2021-10-07 14:49:52 +01:00
Auxilor
595751a094 Fixed build warnings 2021-10-07 14:45:42 +01:00
Auxilor
8231afdcbf Fixed dependency-related issues (Reflections) 2021-10-07 14:39:44 +01:00
Auxilor
4f55d66096 Updated to 6.10.0 2021-10-07 14:36:03 +01:00
Auxilor
d350febbdc Minor change 2021-10-07 14:35:52 +01:00
Auxilor
78755b0e9a (Hopefully) massively optimized display (PacketWindowItems) with DisplayFrame.kt 2021-10-07 14:34:40 +01:00
Auxilor
63d7bdab6b Re-Added Head Database integration 2021-10-07 13:58:42 +01:00
Auxilor
344032b7e3 Added ItemProvider 2021-10-07 13:45:45 +01:00
Auxilor
3ae5c8a72c Moved ArmorEquipEvent code to kotlin, finally 2021-10-07 13:13:33 +01:00
Auxilor
e4f2bc2e39 Finally recoded remaining java in NMS to kotlin 2021-10-07 13:03:19 +01:00
Auxilor
90ba0a0391 Updated dependencies 2021-10-07 12:50:53 +01:00
Auxilor
801a3cd4f9 Merge remote-tracking branch 'origin/master' 2021-10-07 12:48:44 +01:00
Will FP
ce9cada75a Merge pull request #35
Bump ProtocolLib from 4.6.0-SNAPSHOT to 4.7.1-SNAPSHOT
2021-10-07 12:48:24 +01:00
Will FP
ae551dd0f7 Merge pull request #36
Bump junit-jupiter-engine from 5.3.1 to 5.8.1
2021-10-07 12:47:38 +01:00
Will FP
1b3dd53fb8 Merge pull request #37
Bump reflections from 0.9.12 to 0.10.1
2021-10-07 12:47:29 +01:00
Will FP
dda4224e6e Merge pull request #38
Bump lombok from 1.18.20 to 1.18.22
2021-10-07 12:47:19 +01:00
dependabot[bot]
6e14265655 Bump lombok from 1.18.20 to 1.18.22
Bumps [lombok](https://github.com/projectlombok/lombok) from 1.18.20 to 1.18.22.
- [Release notes](https://github.com/projectlombok/lombok/releases)
- [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown)
- [Commits](https://github.com/projectlombok/lombok/compare/v1.18.20...v1.18.22)

---
updated-dependencies:
- dependency-name: org.projectlombok:lombok
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-07 11:47:09 +00:00
dependabot[bot]
77fd99d215 Bump reflections from 0.9.12 to 0.10.1
Bumps [reflections](https://github.com/ronmamo/reflections) from 0.9.12 to 0.10.1.
- [Release notes](https://github.com/ronmamo/reflections/releases)
- [Commits](https://github.com/ronmamo/reflections/compare/0.9.12...0.10.1)

---
updated-dependencies:
- dependency-name: org.reflections:reflections
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-07 11:47:01 +00:00
Will FP
cf05efc2ff Merge pull request #26
Bump kotlin-gradle-plugin from 1.5.21 to 1.5.31
2021-10-07 12:46:59 +01:00
dependabot[bot]
0e8c759a4c Bump junit-jupiter-engine from 5.3.1 to 5.8.1
Bumps [junit-jupiter-engine](https://github.com/junit-team/junit5) from 5.3.1 to 5.8.1.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.3.1...r5.8.1)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-engine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-07 11:46:18 +00:00
Will FP
ba7bfb828b Merge pull request #30
Bump adventure-text-serializer-gson from 4.8.1 to 4.9.2
2021-10-07 12:46:13 +01:00
dependabot[bot]
8dd1239b99 Bump ProtocolLib from 4.6.0-SNAPSHOT to 4.7.1-SNAPSHOT
Bumps ProtocolLib from 4.6.0-SNAPSHOT to 4.7.1-SNAPSHOT.

---
updated-dependencies:
- dependency-name: com.comphenix.protocol:ProtocolLib
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-07 11:46:04 +00:00
Will FP
edada09966 Merge pull request #31
Bump mcMMO from 2.1.157 to 2.1.202
2021-10-07 12:46:01 +01:00
Auxilor
19c300bbf3 Merge remote-tracking branch 'origin/master' 2021-10-07 12:45:45 +01:00
Will FP
4fc9c21034 Merge pull request #32
Bump Towny from 0.97.1.0 to 0.97.2.5
2021-10-07 12:45:20 +01:00
Auxilor
2366dcd293 Merge remote-tracking branch 'origin/master' 2021-10-07 12:44:48 +01:00
Auxilor
054e6a53c0 Fixed dumb Any? constraint 2021-10-07 11:51:42 +01:00
Auxilor
46f590fe3e Recoded PacketChat 2021-10-07 11:50:26 +01:00
dependabot[bot]
b46aaf547f Bump Towny from 0.97.1.0 to 0.97.2.5
Bumps [Towny](https://github.com/TownyAdvanced/Towny) from 0.97.1.0 to 0.97.2.5.
- [Release notes](https://github.com/TownyAdvanced/Towny/releases)
- [Commits](https://github.com/TownyAdvanced/Towny/compare/0.97.1.0...0.97.2.5)

---
updated-dependencies:
- dependency-name: com.github.TownyAdvanced:Towny
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-05 21:23:42 +00:00
dependabot[bot]
0f7125e1c8 Bump mcMMO from 2.1.157 to 2.1.202
Bumps [mcMMO](https://github.com/mcMMO-Dev/mcMMO) from 2.1.157 to 2.1.202.
- [Release notes](https://github.com/mcMMO-Dev/mcMMO/releases)
- [Changelog](https://github.com/mcMMO-Dev/mcMMO/blob/master/Changelog.txt)
- [Commits](https://github.com/mcMMO-Dev/mcMMO/commits)

---
updated-dependencies:
- dependency-name: com.gmail.nossr50.mcMMO:mcMMO
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-05 21:20:47 +00:00
dependabot[bot]
6cb99819f3 Bump adventure-text-serializer-gson from 4.8.1 to 4.9.2
Bumps [adventure-text-serializer-gson](https://github.com/KyoriPowered/adventure) from 4.8.1 to 4.9.2.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.8.1...v4.9.2)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-text-serializer-gson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-04 21:34:25 +00:00
Auxilor
a018a1fca5 Cleaned up dependencies 2021-10-03 18:57:52 +01:00
Auxilor
8a7b8f2b03 Cleaned up dependencies 2021-10-03 18:56:56 +01:00
Auxilor
abf3dc1e9e Updated to 6.9.4 2021-10-03 18:56:27 +01:00
Auxilor
e92cc41be6 Fixed BukkitAudiences bug on outdated versions of paper 2021-10-03 17:37:45 +01:00
Auxilor
49570c841b Reverted publication changes 2021-10-03 13:00:01 +01:00
Auxilor
9aa465844d Finally fixed Adventure + MiniMessage shading / Dependency issues 2021-10-03 12:54:38 +01:00
Auxilor
a692fbee01 Moved Adventure to api implementation, Removed GriefDefender 2021-10-03 11:51:55 +01:00
Auxilor
4223e8f17a Updated to 6.9.2 2021-10-02 12:20:37 +01:00
Auxilor
5f26b23a53 Adventure bug fixing 2021-10-02 12:20:27 +01:00
Auxilor
c8c179981c Adventure bug fixing 2021-10-02 12:20:05 +01:00
dependabot[bot]
4bb8bb62f9 Bump kotlin-gradle-plugin from 1.5.21 to 1.5.31
Bumps [kotlin-gradle-plugin](https://github.com/JetBrains/kotlin) from 1.5.21 to 1.5.31.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/v1.5.31/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.21...v1.5.31)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-gradle-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-01 21:29:48 +00:00
Auxilor
c1b3bec67c Moved adventure off to implementation and relocated 2021-10-01 18:57:00 +01:00
Auxilor
f2535ce75c Updated to 6.9.1 2021-10-01 18:33:14 +01:00
Auxilor
049d64821e Added adventure-api to plugin.yml 2021-10-01 18:32:57 +01:00
Auxilor
bf5766e61c Fixed minimessage bug 2021-10-01 15:32:38 +01:00
Auxilor
38da5fe6d1 Fixed adventure audience bug 2021-10-01 14:05:16 +01:00
Auxilor
e16649873b Moved MiniMessage to being shaded 2021-10-01 13:56:29 +01:00
Will FP
a3b0b4f847 Updated kotlin lib loader to 1.5.31 2021-10-01 12:09:08 +01:00
Will FP
d9f1ddd188 Merge pull request #19 from Auxilor/dependabot/gradle/me.clip-placeholderapi-2.10.10
Bump placeholderapi from 2.10.9 to 2.10.10
2021-10-01 12:07:54 +01:00
Will FP
14a4d9291b Merge pull request #20 from Auxilor/dependabot/gradle/org.jetbrains.kotlin-kotlin-stdlib-1.5.31
Bump kotlin-stdlib from 1.5.21 to 1.5.31
2021-10-01 12:07:40 +01:00
dependabot[bot]
6630044546 Bump placeholderapi from 2.10.9 to 2.10.10
Bumps placeholderapi from 2.10.9 to 2.10.10.

---
updated-dependencies:
- dependency-name: me.clip:placeholderapi
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-01 11:07:15 +00:00
Will FP
1043981fe4 Merge pull request #22 from Auxilor/dependabot/gradle/com.github.TechFortress-GriefPrevention-16.17.1
Bump GriefPrevention from 16.14.0 to 16.17.1
2021-10-01 12:06:54 +01:00
Will FP
fb0b7c52cf Merge pull request #18 from Auxilor/dependabot/gradle/org.spigotmc-spigot-api-1.17.1-R0.1-SNAPSHOT
Bump spigot-api from 1.17-R0.1-SNAPSHOT to 1.17.1-R0.1-SNAPSHOT
2021-10-01 12:06:26 +01:00
dependabot[bot]
74e5464f7d Bump GriefPrevention from 16.14.0 to 16.17.1
Bumps [GriefPrevention](https://github.com/TechFortress/GriefPrevention) from 16.14.0 to 16.17.1.
- [Release notes](https://github.com/TechFortress/GriefPrevention/releases)
- [Commits](https://github.com/TechFortress/GriefPrevention/compare/16.14.0...16.17.1)

---
updated-dependencies:
- dependency-name: com.github.TechFortress:GriefPrevention
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-01 11:02:04 +00:00
dependabot[bot]
2ad1ff4cdb Bump kotlin-stdlib from 1.5.21 to 1.5.31
Bumps [kotlin-stdlib](https://github.com/JetBrains/kotlin) from 1.5.21 to 1.5.31.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/v1.5.31/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.21...v1.5.31)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-01 11:01:47 +00:00
dependabot[bot]
2d47c18be6 Bump spigot-api from 1.17-R0.1-SNAPSHOT to 1.17.1-R0.1-SNAPSHOT
Bumps spigot-api from 1.17-R0.1-SNAPSHOT to 1.17.1-R0.1-SNAPSHOT.

---
updated-dependencies:
- dependency-name: org.spigotmc:spigot-api
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-01 11:00:17 +00:00
Will FP
69e67be436 Create dependabot.yml 2021-10-01 11:59:52 +01:00
Auxilor
c144723d5b Updated to 6.9.0 2021-10-01 11:13:01 +01:00
Auxilor
108375f545 Added formatToComponent throughout StringUtils 2021-10-01 11:12:48 +01:00
Auxilor
83d5b3e96e Closed adventure on disable 2021-10-01 11:09:25 +01:00
Auxilor
37e09a470e Added config thread-safety (hopefully) 2021-10-01 11:05:45 +01:00
Auxilor
1f064110b7 Added MiniMessage markdown (discord flavor) support 2021-10-01 11:01:40 +01:00
Auxilor
94a0b4de5d Moved order of StringUtils#format 2021-10-01 10:57:46 +01:00
Auxilor
8a68666f86 Added adventure into eco 2021-10-01 10:56:05 +01:00
Auxilor
2c218d1088 Internal menu changes 2021-10-01 10:38:46 +01:00
Auxilor
3fa95d82a6 Fixed gradient div by zero exception 2021-10-01 10:34:47 +01:00
Auxilor
9648b42c4d Added MiniMessage support to StringUtils#format 2021-10-01 10:33:09 +01:00
Auxilor
66887f0a3a Updated to 6.8.6 2021-09-30 12:22:16 +01:00
Auxilor
410cdfe7e3 Improved WorldGuard code 2021-09-30 12:22:03 +01:00
Auxilor
bbffdc7e23 Improved WorldGuard code 2021-09-30 12:21:55 +01:00
Will FP
0d267e2bec Merge pull request #16
Fixed WorldGuard AntiGrief manager using damage-animals flag only
2021-09-30 12:15:38 +01:00
Auxilor
578256f89b Updated to 6.8.5 2021-09-29 10:32:24 +01:00
Auxilor
90ecbfce00 Added use-lower-protocollib-priority 2021-09-29 10:32:12 +01:00
_OfTeN_
9945704338 Fixed WorldGuard AntiGrief manager using damage-animals flag only 2021-09-29 00:42:53 +03:00
Auxilor
5c7a7876d8 Improved GriefDefender support 2021-09-27 14:11:42 +01:00
Will FP
94df0e67a6 Merge pull request #15
GriefDefender support
2021-09-27 14:07:56 +01:00
_OfTeN_
92c4e62709 Hopefully added GriefDefender support 2021-09-26 15:00:05 +03:00
Auxilor
e094a1e934 Merge remote-tracking branch 'origin/master' 2021-09-24 09:50:12 +01:00
Auxilor
26c07a20e7 Updated to 6.8.3 2021-09-24 09:50:05 +01:00
Auxilor
ad68e1efef Fixed legacyToJson nullability bug 2021-09-24 09:49:54 +01:00
Auxilor
d8c3a3befa Removed redundant suppression 2021-09-21 19:18:01 +01:00
Auxilor
aa52dcdf94 Updated to 6.8.2 2021-09-20 17:01:39 +01:00
Auxilor
9d3ba7ea88 Improved towny integration 2021-09-20 17:01:16 +01:00
Auxilor
e2b417af74 Updated eco resource ID 2021-09-19 11:14:03 +01:00
Auxilor
77394d3038 Updated to 6.8.1 2021-09-19 11:12:45 +01:00
Auxilor
fcc7f82b38 Removed references to spigotmc. eco will now check polymart for updates 2021-09-19 11:11:01 +01:00
Auxilor
396f4dac44 Added more gradient syntaxes 2021-09-18 17:48:41 +01:00
Auxilor
3341093735 Fixed non-final params 2021-09-17 19:56:54 +01:00
Auxilor
714d04e48f Added missing javadoc 2021-09-17 19:55:29 +01:00
Auxilor
73b7ccea3a Merge branch 'dev'
# Conflicts:
#	gradle.properties
2021-09-17 19:53:40 +01:00
Auxilor
606bf8fcd2 Updated to 6.8.0 2021-09-17 19:53:24 +01:00
Auxilor
fbbf893d64 Added requirements into eco 2021-09-17 19:52:49 +01:00
Auxilor
36001373eb Removed redundant default methods from DisplayHandler 2021-09-16 15:07:37 +01:00
Auxilor
9ac34288eb EcoDisplayHandler.kt changes 2021-09-16 15:04:24 +01:00
Auxilor
6345d1fe92 Moved display impl code off to internals 2021-09-16 14:56:56 +01:00
Auxilor
a7fa0ecf26 Updated to 6.7.5 2021-09-14 08:35:02 +01:00
Auxilor
a65f16cfac Improved PR 2021-09-14 08:34:51 +01:00
Will FP
49965c091b Merge pull request #13
Added silent lightning option
2021-09-14 08:33:38 +01:00
Auxilor
f9bc2aba99 Merge remote-tracking branch 'origin/master' into dev 2021-09-13 12:12:33 +01:00
Auxilor
5627582bd5 Updated to 6.7.4 2021-09-13 10:10:14 +01:00
Auxilor
ab8065d06e Fixed ShopGUIPlus softdepend 2021-09-13 10:09:54 +01:00
Auxilor
444764e481 Fixed ShopGUIPlus integration not working 2021-09-13 10:09:34 +01:00
_OfTeN_
c240e94a6b Removed NPE warning in the console if Oraxen returns null on OraxenItems#getIdByItem 2021-09-12 23:03:04 +03:00
_OfTeN_
9da28a1dff Added boolean silent param to LightningUtils#strike method to make a lightning with sound only played locally for nearest players 2021-09-12 22:45:41 +03:00
Auxilor
cf3c1f8394 Added destructuring support to pairs 2021-09-10 13:48:50 +01:00
Auxilor
f98befbdce Used FastItemStack on display reverting 2021-09-09 13:03:24 +01:00
Auxilor
d0d8ea07e4 Added JSON updatable configs 2021-09-08 10:59:11 +01:00
Auxilor
109347a601 Updated to 6.7.3 2021-09-06 15:07:15 +01:00
Auxilor
43bef762bf Removed buggy headdb integration 2021-09-06 15:07:06 +01:00
Auxilor
69a2e0e247 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	eco-api/src/main/java/com/willfp/eco/core/items/args/EnchantmentArgParser.java
#	eco-api/src/main/java/com/willfp/eco/core/items/args/LookupArgParser.java
#	eco-api/src/main/java/com/willfp/eco/core/items/args/TextureArgParser.java
2021-09-06 15:05:32 +01:00
Auxilor
874a9b4f32 Updated to 6.7.2 2021-09-05 12:53:33 +01:00
Auxilor
5690221c27 Fixed crafting 2021-09-05 12:53:22 +01:00
Auxilor
f19b143804 Added validation to testable items 2021-09-05 12:02:35 +01:00
Auxilor
10a313bef5 Added missing javadoc 2021-09-05 11:08:05 +01:00
Auxilor
9ae40ae09e Removed redundant nullability 2021-09-05 11:07:15 +01:00
Auxilor
7b4e1d8d24 Updated to 6.7.1 2021-09-05 11:05:33 +01:00
Auxilor
7035280731 Item checks and improvements related to EmptyTestableItem 2021-09-05 11:05:23 +01:00
Auxilor
a1e3d53cd2 Janky HeadDB fix 2021-09-04 16:44:15 +01:00
Auxilor
d7885f05c3 Optimised placeholders 2021-09-04 13:59:46 +01:00
Auxilor
415c425097 Fixed bugs 2021-09-04 11:03:04 +01:00
Auxilor
cb4d992e7d Added option to create custom lang.yml and config.yml implementations 2021-09-04 10:59:49 +01:00
Auxilor
cb64d088d1 Added nullability annotations to all utility methods 2021-09-04 10:53:06 +01:00
Auxilor
bbbf19c041 Added missing javadoc 2021-09-03 13:03:28 +01:00
Auxilor
61ace5c8e5 Updated to 6.7.0 2021-09-03 12:50:23 +01:00
Auxilor
94b73ef35c Improved Arg Parser javadoc 2021-09-03 12:49:59 +01:00
Auxilor
5cfc2068e7 Added arg parser lookup system 2021-09-03 12:47:23 +01:00
Auxilor
0ce7d1dd6c Added texture:<base64> to Items.lookup 2021-09-03 12:28:03 +01:00
Auxilor
19eefaf879 Improved Items.lookup javadoc 2021-09-03 11:54:48 +01:00
Auxilor
1ebf7fb875 Added Head Database integration 2021-09-03 11:45:34 +01:00
Auxilor
e8afd15d80 Updated to 6.6.4 2021-09-02 18:55:49 +01:00
Auxilor
d024c9238e Switched TestableStack display to only show recipe lore in recipes 2021-09-02 18:55:37 +01:00
Auxilor
1356bd1f26 ItemsAdder fix 2021-09-02 18:50:01 +01:00
Auxilor
407ccca5e0 TestableStack changes don't stop ever 2021-09-02 11:49:48 +01:00
Auxilor
82de602d47 Hopefully fixed crafting exploit 2021-09-02 10:53:14 +01:00
Auxilor
b0873112af Added ItemsAdder and Oraxen to plugin.yml 2021-09-02 10:50:40 +01:00
Auxilor
3a0b81b7de Updated to 6.6.3 2021-09-02 10:50:12 +01:00
Auxilor
5142b9ce92 More Items#lookup improvements 2021-09-02 10:46:25 +01:00
Auxilor
9403a1cbcb Marked item:amount system as legacy and replaced it with item amount 2021-09-02 10:42:29 +01:00
Auxilor
e4ebea354d Added ItemsAdder support 2021-09-02 10:35:03 +01:00
172 changed files with 4620 additions and 1192 deletions

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gradle" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

View File

@@ -1,6 +1,6 @@
<h1 align="center"> <h1 align="center">
<br> <br>
<img src="https://i.imgur.com/p5uR2Qp.png" alt="eco logo" width="256"> <img src="https://i.imgur.com/kU3ejCt.png" alt="eco logo" width="256">
<br> <br>
</h1> </h1>
@@ -16,7 +16,7 @@
# Information for development # Information for development
## Javadoc ## Javadoc
The 6.0.0 Javadoc can be found [here](https://javadoc.jitpack.io/com/willfp/eco/6.0.0/javadoc/) The 6.8.0 Javadoc can be found [here](https://javadoc.jitpack.io/com/willfp/eco/6.8.0/javadoc/)
## Plugin Information ## Plugin Information
@@ -31,7 +31,6 @@ depend:
eco is available from any of these places: eco is available from any of these places:
- [GitHub](https://github.com/Auxilor/eco/releases) - [GitHub](https://github.com/Auxilor/eco/releases)
- [Spigot](https://www.spigotmc.org/resources/eco.87955/)
- [Polymart](https://polymart.org/resource/eco.773) - [Polymart](https://polymart.org/resource/eco.773)
- [Build it locally](https://github.com/Auxilor/eco#build-locally). - [Build it locally](https://github.com/Auxilor/eco#build-locally).
@@ -72,7 +71,7 @@ Maven:
</dependency> </dependency>
``` ```
Replace `Tag` with a release tag for eco, eg `6.0.0`. Replace `Tag` with a release tag for eco, eg `6.8.0`.
## Build locally: ## Build locally:
@@ -158,7 +157,7 @@ Here's a list of some (not all) of the features of eco:
<h1 align="center"> <h1 align="center">
<br> <br>
<a href="http://gamersupps.gg/discount/Auxilor?afmc=Auxilor" target="_blank"> <a href="https://gamersupps.gg/discount/Auxilor?afmc=Auxilor" target="_blank">
<img src="https://i.imgur.com/uFDpBAC.png" alt="supps banner"> <img src="https://i.imgur.com/uFDpBAC.png" alt="supps banner">
</a> </a>
<a href="https://dedimc.promo/Auxilor" target="_blank"> <a href="https://dedimc.promo/Auxilor" target="_blank">

View File

@@ -25,11 +25,14 @@ allprojects {
mavenLocal() mavenLocal()
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
// SuperiorSkyblock2
maven { url 'https://repo.bg-software.com/repository/api/' }
// NMS (for jitpack compilation) // NMS (for jitpack compilation)
maven { url 'https://repo.codemc.org/repository/nms/' } maven { url 'https://repo.codemc.org/repository/nms/' }
// bStats, mcMMO // bStats, mcMMO, BentoBox
maven { url 'https://repo.codemc.org/repository/maven-public' } maven { url 'https://repo.codemc.org/repository/maven-public/' }
// Spigot API // Spigot API
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
@@ -57,14 +60,14 @@ allprojects {
compileOnly 'org.jetbrains:annotations:19.0.0' compileOnly 'org.jetbrains:annotations:19.0.0'
// Lombok // Lombok
compileOnly 'org.projectlombok:lombok:1.18.20' compileOnly 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.20' annotationProcessor 'org.projectlombok:lombok:1.18.20'
testCompileOnly 'org.projectlombok:lombok:1.18.20' testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20' testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
// Test // Test
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
} }
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
@@ -84,6 +87,7 @@ allprojects {
shadowJar { shadowJar {
relocate('org.bstats', 'com.willfp.eco.shaded.bstats') relocate('org.bstats', 'com.willfp.eco.shaded.bstats')
relocate('net.kyori.adventure.text.minimessage', 'com.willfp.eco.shaded.minimessage')
} }
jar { jar {

View File

@@ -6,12 +6,18 @@ group 'com.willfp'
version rootProject.version version rootProject.version
dependencies { dependencies {
compileOnly 'org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT' // Adventure
compileOnly 'org.apache.maven:maven-artifact:3.0.3' compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT' compileOnly 'net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT'
compileOnly 'com.google.code.gson:gson:2.8.7' compileOnly 'net.kyori:adventure-api:4.9.2'
compileOnly 'net.kyori:adventure-text-serializer-gson:4.8.1' compileOnly 'net.kyori:adventure-text-serializer-gson:4.9.2'
compileOnly 'net.kyori:adventure-text-serializer-legacy:4.8.1' compileOnly 'net.kyori:adventure-text-serializer-legacy:4.9.2'
// Other
compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT'
compileOnly 'org.apache.maven:maven-artifact:3.8.1'
compileOnly 'com.comphenix.protocol:ProtocolLib:4.7.1-SNAPSHOT'
compileOnly 'com.google.code.gson:gson:2.8.8'
} }
java { java {

View File

@@ -1,6 +1,5 @@
package com.willfp.eco.core; package com.willfp.eco.core;
import lombok.Getter;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@@ -15,20 +14,12 @@ import org.jetbrains.annotations.NotNull;
public class Eco { public class Eco {
/** /**
* Instance of eco handler. * 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 @ApiStatus.Internal
private Handler handler; private Handler handler;
/** /**
* Set the handler. * Set the handler.
*
* @param handler The handler. * @param handler The handler.
*/ */
@ApiStatus.Internal @ApiStatus.Internal
@@ -37,4 +28,25 @@ public class Eco {
Eco.handler = handler; Eco.handler = handler;
} }
/**
* Get the instance of the 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, and you are likely to break things. All parts of
* the handler are abstracted into logically named parts of the API.
* <p>
* In versions of eco before 6.12.0, the handler was considered part of
* the eco API, however it has since been moved into an internal component
* that shouldn't be used in your plugins.
*
* @return The handler.
*/
@ApiStatus.Internal
public Handler getHandler() {
return handler;
}
} }

View File

@@ -52,9 +52,9 @@ import java.util.stream.Collectors;
* be cancelled.</b> * be cancelled.</b>
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public abstract class EcoPlugin extends JavaPlugin { public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
/** /**
* The spigot resource ID of the plugin. * The polymart resource ID of the plugin.
*/ */
@Getter @Getter
private final int resourceId; private final int resourceId;
@@ -169,14 +169,14 @@ public abstract class EcoPlugin extends JavaPlugin {
private final ProxyFactory proxyFactory; private final ProxyFactory proxyFactory;
/** /**
* Create a new plugin without a specified color, proxy support, spigot, or bStats. * Create a new plugin without a specified color, proxy support, polymart, or bStats.
*/ */
protected EcoPlugin() { protected EcoPlugin() {
this("&f"); this("&f");
} }
/** /**
* Create a new plugin without proxy support, spigot, or bStats. * Create a new plugin without proxy support, polymart, or bStats.
* *
* @param color The color. * @param color The color.
*/ */
@@ -186,7 +186,7 @@ public abstract class EcoPlugin extends JavaPlugin {
/** /**
* Create a new plugin unlinked to spigot and bStats. * Create a new plugin unlinked to polymart and bStats.
* *
* @param proxyPackage The package where proxy implementations are stored. * @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, using standard formatting) * @param color The color of the plugin (used in messages, using standard formatting)
@@ -199,7 +199,7 @@ public abstract class EcoPlugin extends JavaPlugin {
/** /**
* Create a new plugin without proxy or extension support. * Create a new plugin without proxy or extension support.
* *
* @param resourceId The spigot resource ID for the plugin. * @param resourceId The polymart resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin. * @param bStatsId The bStats resource ID for the plugin.
* @param color The color of the plugin (used in messages, using standard formatting) * @param color The color of the plugin (used in messages, using standard formatting)
*/ */
@@ -212,7 +212,7 @@ public abstract class EcoPlugin extends JavaPlugin {
/** /**
* Create a new plugin without proxy support. * Create a new plugin without proxy support.
* *
* @param resourceId The spigot resource ID for the plugin. * @param resourceId The polymart resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin. * @param bStatsId The bStats resource ID for the plugin.
* @param color The color of the plugin (used in messages, using standard formatting) * @param color The color of the plugin (used in messages, using standard formatting)
* @param supportingExtensions If the plugin supports extensions. * @param supportingExtensions If the plugin supports extensions.
@@ -227,7 +227,7 @@ public abstract class EcoPlugin extends JavaPlugin {
/** /**
* Create a new plugin without extension support. * Create a new plugin without extension support.
* *
* @param resourceId The spigot resource ID for the plugin. * @param resourceId The polymart resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin. * @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored. * @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, using standard formatting) * @param color The color of the plugin (used in messages, using standard formatting)
@@ -242,7 +242,7 @@ public abstract class EcoPlugin extends JavaPlugin {
/** /**
* Create a new plugin. * Create a new plugin.
* *
* @param resourceId The spigot resource ID for the plugin. * @param resourceId The polymart resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin. * @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored. * @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, using standard formatting) * @param color The color of the plugin (used in messages, using standard formatting)
@@ -305,10 +305,27 @@ public abstract class EcoPlugin extends JavaPlugin {
this.logger = Eco.getHandler().createLogger(this); this.logger = Eco.getHandler().createLogger(this);
this.proxyFactory = this.proxyPackage.equalsIgnoreCase("") ? null : Eco.getHandler().createProxyFactory(this); this.proxyFactory = this.proxyPackage.equalsIgnoreCase("") ? null : Eco.getHandler().createProxyFactory(this);
this.langYml = new LangYml(this); this.langYml = this.createLangYml();
this.configYml = new ConfigYml(this); this.configYml = this.createConfigYml();
Eco.getHandler().addNewPlugin(this); Eco.getHandler().addNewPlugin(this);
/*
The minimum eco version check was moved here because it's very common
to add a lot of code in the constructor of plugins; meaning that the plugin
can throw errors without it being obvious to the user that the reason is
because they have an outdated version of eco installed.
*/
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!");
this.getLogger().severe("You must be on at least" + this.getMinimumEcoVersion());
this.getLogger().severe("Download the newest version here:");
this.getLogger().severe("https://polymart.org/download/773/recent/JSpprMspkuyecf5y1wQ2Jn8OoLQSQ_IW");
Bukkit.getPluginManager().disablePlugin(this);
}
} }
/** /**
@@ -336,29 +353,22 @@ public abstract class EcoPlugin extends JavaPlugin {
}); });
} }
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!");
this.getLogger().severe("You must be on at least" + this.getMinimumEcoVersion());
this.getLogger().severe("Download the newest version here:");
this.getLogger().severe("https://polymart.org/download/773/recent/JSpprMspkuyecf5y1wQ2Jn8OoLQSQ_IW");
Bukkit.getPluginManager().disablePlugin(this);
}
if (this.getBStatsId() != 0) { if (this.getBStatsId() != 0) {
Eco.getHandler().registerBStats(this); Eco.getHandler().registerBStats(this);
} }
Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toSet()); Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins())
.map(Plugin::getName)
.map(String::toLowerCase)
.collect(Collectors.toSet());
if (enabledPlugins.contains("PlaceholderAPI")) { if (enabledPlugins.contains("PlaceholderAPI".toLowerCase())) {
this.loadedIntegrations.add("PlaceholderAPI"); this.loadedIntegrations.add("PlaceholderAPI");
PlaceholderManager.addIntegration(Eco.getHandler().createPAPIIntegration(this)); PlaceholderManager.addIntegration(Eco.getHandler().createPAPIIntegration(this));
} }
this.loadIntegrationLoaders().forEach((integrationLoader -> { this.loadIntegrationLoaders().forEach((integrationLoader -> {
if (enabledPlugins.contains(integrationLoader.getPluginName())) { if (enabledPlugins.contains(integrationLoader.getPluginName().toLowerCase())) {
this.loadedIntegrations.add(integrationLoader.getPluginName()); this.loadedIntegrations.add(integrationLoader.getPluginName());
integrationLoader.load(); integrationLoader.load();
} }
@@ -571,6 +581,28 @@ public abstract class EcoPlugin extends JavaPlugin {
*/ */
protected abstract List<Listener> loadListeners(); protected abstract List<Listener> loadListeners();
/**
* Useful for custom LangYml implementations.
* <p>
* Override if needed.
*
* @return lang.yml.
*/
protected LangYml createLangYml() {
return new LangYml(this);
}
/**
* Useful for custom ConfigYml implementations.
* <p>
* Override if needed.
*
* @return config.yml.
*/
protected ConfigYml createConfigYml() {
return new ConfigYml(this);
}
/** /**
* Create the display module for the plugin. * Create the display module for the plugin.
* *

View File

@@ -2,6 +2,8 @@ package com.willfp.eco.core;
import com.willfp.eco.core.config.updating.ConfigHandler; import com.willfp.eco.core.config.updating.ConfigHandler;
import com.willfp.eco.core.config.wrapper.ConfigFactory; import com.willfp.eco.core.config.wrapper.ConfigFactory;
import com.willfp.eco.core.data.keys.KeyRegistry;
import com.willfp.eco.core.data.PlayerProfileHandler;
import com.willfp.eco.core.drops.DropQueueFactory; import com.willfp.eco.core.drops.DropQueueFactory;
import com.willfp.eco.core.events.EventManager; import com.willfp.eco.core.events.EventManager;
import com.willfp.eco.core.extensions.ExtensionLoader; import com.willfp.eco.core.extensions.ExtensionLoader;
@@ -13,16 +15,21 @@ import com.willfp.eco.core.gui.GUIFactory;
import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration; import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration;
import com.willfp.eco.core.proxy.Cleaner; import com.willfp.eco.core.proxy.Cleaner;
import com.willfp.eco.core.proxy.ProxyFactory; import com.willfp.eco.core.proxy.ProxyFactory;
import com.willfp.eco.core.requirement.RequirementFactory;
import com.willfp.eco.core.scheduling.Scheduler; import com.willfp.eco.core.scheduling.Scheduler;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* @see Eco * @see Eco#getHandler()
*/ */
@ApiStatus.Internal
public interface Handler { public interface Handler {
/** /**
* Create a scheduler. * Create a scheduler.
@@ -30,6 +37,7 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
* @return The scheduler. * @return The scheduler.
*/ */
@NotNull
Scheduler createScheduler(@NotNull EcoPlugin plugin); Scheduler createScheduler(@NotNull EcoPlugin plugin);
/** /**
@@ -38,6 +46,7 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
* @return The event manager. * @return The event manager.
*/ */
@NotNull
EventManager createEventManager(@NotNull EcoPlugin plugin); EventManager createEventManager(@NotNull EcoPlugin plugin);
/** /**
@@ -46,6 +55,7 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
* @return The factory. * @return The factory.
*/ */
@NotNull
NamespacedKeyFactory createNamespacedKeyFactory(@NotNull EcoPlugin plugin); NamespacedKeyFactory createNamespacedKeyFactory(@NotNull EcoPlugin plugin);
/** /**
@@ -54,6 +64,7 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
* @return The factory. * @return The factory.
*/ */
@NotNull
MetadataValueFactory createMetadataValueFactory(@NotNull EcoPlugin plugin); MetadataValueFactory createMetadataValueFactory(@NotNull EcoPlugin plugin);
/** /**
@@ -62,6 +73,7 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
* @return The factory. * @return The factory.
*/ */
@NotNull
RunnableFactory createRunnableFactory(@NotNull EcoPlugin plugin); RunnableFactory createRunnableFactory(@NotNull EcoPlugin plugin);
/** /**
@@ -70,6 +82,7 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
* @return The factory. * @return The factory.
*/ */
@NotNull
ExtensionLoader createExtensionLoader(@NotNull EcoPlugin plugin); ExtensionLoader createExtensionLoader(@NotNull EcoPlugin plugin);
/** /**
@@ -78,6 +91,7 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
* @return The handler. * @return The handler.
*/ */
@NotNull
ConfigHandler createConfigHandler(@NotNull EcoPlugin plugin); ConfigHandler createConfigHandler(@NotNull EcoPlugin plugin);
/** /**
@@ -86,6 +100,7 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
* @return The logger. * @return The logger.
*/ */
@NotNull
Logger createLogger(@NotNull EcoPlugin plugin); Logger createLogger(@NotNull EcoPlugin plugin);
/** /**
@@ -94,6 +109,7 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
* @return The integration. * @return The integration.
*/ */
@NotNull
PlaceholderIntegration createPAPIIntegration(@NotNull EcoPlugin plugin); PlaceholderIntegration createPAPIIntegration(@NotNull EcoPlugin plugin);
/** /**
@@ -102,6 +118,7 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
* @return The factory. * @return The factory.
*/ */
@NotNull
ProxyFactory createProxyFactory(@NotNull EcoPlugin plugin); ProxyFactory createProxyFactory(@NotNull EcoPlugin plugin);
/** /**
@@ -109,6 +126,7 @@ public interface Handler {
* *
* @return The plugin. * @return The plugin.
*/ */
@NotNull
EcoPlugin getEcoPlugin(); EcoPlugin getEcoPlugin();
/** /**
@@ -116,6 +134,7 @@ public interface Handler {
* *
* @return The factory. * @return The factory.
*/ */
@NotNull
ConfigFactory getConfigFactory(); ConfigFactory getConfigFactory();
/** /**
@@ -123,6 +142,7 @@ public interface Handler {
* *
* @return The factory. * @return The factory.
*/ */
@NotNull
DropQueueFactory getDropQueueFactory(); DropQueueFactory getDropQueueFactory();
/** /**
@@ -130,6 +150,7 @@ public interface Handler {
* *
* @return The factory. * @return The factory.
*/ */
@NotNull
GUIFactory getGUIFactory(); GUIFactory getGUIFactory();
/** /**
@@ -137,6 +158,7 @@ public interface Handler {
* *
* @return The cleaner. * @return The cleaner.
*/ */
@NotNull
Cleaner getCleaner(); Cleaner getCleaner();
/** /**
@@ -152,6 +174,7 @@ public interface Handler {
* @param name The name. * @param name The name.
* @return The plugin. * @return The plugin.
*/ */
@Nullable
EcoPlugin getPluginByName(@NotNull String name); EcoPlugin getPluginByName(@NotNull String name);
/** /**
@@ -159,6 +182,7 @@ public interface Handler {
* *
* @return A list of plugin names in lowercase. * @return A list of plugin names in lowercase.
*/ */
@NotNull
List<String> getLoadedPlugins(); List<String> getLoadedPlugins();
/** /**
@@ -167,6 +191,7 @@ public interface Handler {
* @param itemStack The base ItemStack. * @param itemStack The base ItemStack.
* @return The FastItemStack. * @return The FastItemStack.
*/ */
@NotNull
FastItemStack createFastItemStack(@NotNull ItemStack itemStack); FastItemStack createFastItemStack(@NotNull ItemStack itemStack);
/** /**
@@ -175,4 +200,35 @@ public interface Handler {
* @param plugin The plugin. * @param plugin The plugin.
*/ */
void registerBStats(@NotNull EcoPlugin plugin); void registerBStats(@NotNull EcoPlugin plugin);
/**
* Get the requirement factory.
*
* @return The factory.
*/
@NotNull
RequirementFactory getRequirementFactory();
/**
* Get Adventure audiences.
*
* @return The audiences.
*/
@Nullable
BukkitAudiences getAdventure();
/**
* Get the key registry.
*
* @return The registry.
*/
@NotNull
KeyRegistry getKeyRegistry();
/**
* Get the PlayerProfile handler.
*
* @return The handler.
*/
PlayerProfileHandler getPlayerProfileHandler();
} }

View File

@@ -14,6 +14,7 @@ public abstract class PluginDependent<T extends EcoPlugin> {
* The {@link EcoPlugin} that is stored. * The {@link EcoPlugin} that is stored.
*/ */
@Getter(AccessLevel.PROTECTED) @Getter(AccessLevel.PROTECTED)
@NotNull
private final T plugin; private final T plugin;
/** /**

View File

@@ -0,0 +1,29 @@
package com.willfp.eco.core;
import com.willfp.eco.core.config.updating.ConfigHandler;
import java.io.File;
/**
* Represents any class that acts like a plugin, for example {@link EcoPlugin}
* or {@link com.willfp.eco.core.extensions.Extension}. This exists to create
* things such as extension base configs rather than needing to pass an instance
* of the owning plugin.
*/
public interface PluginLike {
/**
* Get the data folder of the object.
* <p>
* Returns the plugin data folder for a plugin, or the extension's parent plugin's folder
*
* @return The data folder.
*/
File getDataFolder();
/**
* Get the handler class for updatable classes.
*
* @return The config handler.
*/
ConfigHandler getConfigHandler();
}

View File

@@ -34,7 +34,7 @@ public interface LoadableConfig {
File getConfigFile(); File getConfigFile();
/** /**
* Get the config name (including extension) * Get the config name (including extension).
* *
* @return The name. * @return The name.
*/ */

View File

@@ -0,0 +1,78 @@
package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
import org.jetbrains.annotations.NotNull;
/**
* Config implementation for configs present in the plugin's base directory (eg config.json).
* <p>
* Automatically updates.
*/
public abstract class JSONBaseConfig extends LoadableJSONConfigWrapper {
/**
* @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 JSONBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final PluginLike plugin,
@NotNull final String... updateBlacklist) {
super(
Eco.getHandler().getConfigFactory().createUpdatableJSONConfig(
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 JSONBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final PluginLike plugin) {
super(
Eco.getHandler().getConfigFactory().createUpdatableJSONConfig(
configName,
plugin,
"",
plugin.getClass(),
removeUnused
)
);
}
/**
* @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 JSONBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin,
@NotNull final String... updateBlacklist) {
this(configName, removeUnused, (PluginLike) plugin, 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 JSONBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin) {
this(configName, removeUnused, (PluginLike) plugin);
}
}

View File

@@ -0,0 +1,60 @@
package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
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 JSONExtendableConfig extends LoadableJSONConfigWrapper {
/**
* @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 JSONExtendableConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final PluginLike plugin,
@NotNull final Class<?> source,
@NotNull final String subDirectoryPath,
@NotNull final String... updateBlacklist) {
super(
Eco.getHandler().getConfigFactory().createUpdatableJSONConfig(
configName,
plugin,
subDirectoryPath,
source,
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.
* @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 JSONExtendableConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin,
@NotNull final Class<?> source,
@NotNull final String subDirectoryPath,
@NotNull final String... updateBlacklist) {
this(configName, removeUnused, (PluginLike) plugin, source, subDirectoryPath, updateBlacklist);
}
}

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper; import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -18,7 +19,20 @@ public abstract class JSONStaticBaseConfig extends LoadableJSONConfigWrapper {
* @param plugin The plugin. * @param plugin The plugin.
*/ */
protected JSONStaticBaseConfig(@NotNull final String configName, protected JSONStaticBaseConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin) { @NotNull final PluginLike plugin) {
super(Eco.getHandler().getConfigFactory().createLoadableJSONConfig(configName, plugin, "", plugin.getClass())); super(Eco.getHandler().getConfigFactory().createLoadableJSONConfig(configName, plugin, "", plugin.getClass()));
} }
/**
* 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) {
this(configName, (PluginLike) plugin);
}
} }

View File

@@ -4,7 +4,7 @@ import com.willfp.eco.core.config.interfaces.LoadableConfig;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* Every {@link com.willfp.eco.core.EcoPlugin} has a config handler. * Every {@link com.willfp.eco.core.PluginLike} has a config handler.
* <p> * <p>
* Handles updating and saving configs. * Handles updating and saving configs.
*/ */

View File

@@ -1,6 +1,6 @@
package com.willfp.eco.core.config.wrapper; package com.willfp.eco.core.config.wrapper;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.interfaces.Config; import com.willfp.eco.core.config.interfaces.Config;
import com.willfp.eco.core.config.interfaces.JSONConfig; import com.willfp.eco.core.config.interfaces.JSONConfig;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
@@ -24,7 +24,25 @@ public interface ConfigFactory {
* @return The config implementation. * @return The config implementation.
*/ */
Config createUpdatableYamlConfig(@NotNull String configName, Config createUpdatableYamlConfig(@NotNull String configName,
@NotNull EcoPlugin plugin, @NotNull PluginLike plugin,
@NotNull String subDirectoryPath,
@NotNull Class<?> source,
boolean removeUnused,
@NotNull String... updateBlacklist);
/**
* 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.
*/
JSONConfig createUpdatableJSONConfig(@NotNull String configName,
@NotNull PluginLike plugin,
@NotNull String subDirectoryPath, @NotNull String subDirectoryPath,
@NotNull Class<?> source, @NotNull Class<?> source,
boolean removeUnused, boolean removeUnused,
@@ -40,7 +58,7 @@ public interface ConfigFactory {
* @return The config implementation. * @return The config implementation.
*/ */
JSONConfig createLoadableJSONConfig(@NotNull String configName, JSONConfig createLoadableJSONConfig(@NotNull String configName,
@NotNull EcoPlugin plugin, @NotNull PluginLike plugin,
@NotNull String subDirectoryPath, @NotNull String subDirectoryPath,
@NotNull Class<?> source); @NotNull Class<?> source);
@@ -54,7 +72,7 @@ public interface ConfigFactory {
* @return The config implementation. * @return The config implementation.
*/ */
Config createLoadableYamlConfig(@NotNull String configName, Config createLoadableYamlConfig(@NotNull String configName,
@NotNull EcoPlugin plugin, @NotNull PluginLike plugin,
@NotNull String subDirectoryPath, @NotNull String subDirectoryPath,
@NotNull Class<?> source); @NotNull Class<?> source);

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.config.yaml;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper; import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -19,7 +20,7 @@ public abstract class YamlBaseConfig extends LoadableYamlConfigWrapper {
*/ */
protected YamlBaseConfig(@NotNull final String configName, protected YamlBaseConfig(@NotNull final String configName,
final boolean removeUnused, final boolean removeUnused,
@NotNull final EcoPlugin plugin, @NotNull final PluginLike plugin,
@NotNull final String... updateBlacklist) { @NotNull final String... updateBlacklist) {
super( super(
Eco.getHandler().getConfigFactory().createUpdatableYamlConfig( Eco.getHandler().getConfigFactory().createUpdatableYamlConfig(
@@ -39,7 +40,7 @@ public abstract class YamlBaseConfig extends LoadableYamlConfigWrapper {
*/ */
protected YamlBaseConfig(@NotNull final String configName, protected YamlBaseConfig(@NotNull final String configName,
final boolean removeUnused, final boolean removeUnused,
@NotNull final EcoPlugin plugin) { @NotNull final PluginLike plugin) {
super( super(
Eco.getHandler().getConfigFactory().createUpdatableYamlConfig( Eco.getHandler().getConfigFactory().createUpdatableYamlConfig(
configName, configName,
@@ -50,4 +51,28 @@ 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) {
this(configName, removeUnused, (PluginLike) plugin, 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) {
this(configName, removeUnused, (PluginLike) plugin);
}
} }

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.config.yaml;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper; import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -25,7 +26,7 @@ public abstract class YamlExtendableConfig extends LoadableYamlConfigWrapper {
*/ */
protected YamlExtendableConfig(@NotNull final String configName, protected YamlExtendableConfig(@NotNull final String configName,
final boolean removeUnused, final boolean removeUnused,
@NotNull final EcoPlugin plugin, @NotNull final PluginLike plugin,
@NotNull final Class<?> source, @NotNull final Class<?> source,
@NotNull final String subDirectoryPath, @NotNull final String subDirectoryPath,
@NotNull final String... updateBlacklist) { @NotNull final String... updateBlacklist) {
@@ -40,4 +41,20 @@ 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) {
this(configName, removeUnused, (PluginLike) plugin, source, subDirectoryPath, updateBlacklist);
}
} }

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.config.yaml;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper; import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -18,7 +19,20 @@ public abstract class YamlStaticBaseConfig extends LoadableYamlConfigWrapper {
* @param plugin The plugin. * @param plugin The plugin.
*/ */
protected YamlStaticBaseConfig(@NotNull final String configName, protected YamlStaticBaseConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin) { @NotNull final PluginLike plugin) {
super(Eco.getHandler().getConfigFactory().createLoadableYamlConfig(configName, plugin, "", plugin.getClass())); super(Eco.getHandler().getConfigFactory().createLoadableYamlConfig(configName, plugin, "", plugin.getClass()));
} }
/**
* 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) {
this(configName, (PluginLike) plugin);
}
} }

View File

@@ -0,0 +1,56 @@
package com.willfp.eco.core.data;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.data.keys.PersistentDataKey;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
/**
* Persistent data storage interface for players.
* <p>
* Profiles save automatically, so there is no need to save after changes.
*/
public interface PlayerProfile {
/**
* Write a key to a player's persistent data.
*
* @param key The key.
* @param value The value.
* @param <T> The type of the key.
*/
<T> void write(@NotNull PersistentDataKey<T> key,
@NotNull T value);
/**
* Read a key from a player's persistent data.
*
* @param key The key.
* @param <T> The type of the key.
* @return The value, or the default value if not found.
*/
<T> @NotNull T read(@NotNull PersistentDataKey<T> key);
/**
* Load a player profile.
*
* @param player The player.
* @return The profile.
*/
@NotNull
static PlayerProfile load(@NotNull final OfflinePlayer player) {
return load(player.getUniqueId());
}
/**
* Load a player profile.
*
* @param uuid The player's UUID.
* @return The profile.
*/
@NotNull
static PlayerProfile load(@NotNull final UUID uuid) {
return Eco.getHandler().getPlayerProfileHandler().load(uuid);
}
}

View File

@@ -0,0 +1,32 @@
package com.willfp.eco.core.data;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
/**
* API to handle player profiles.
*/
public interface PlayerProfileHandler {
/**
* Load a player profile.
*
* @param uuid The UUID.
* @return The profile.
*/
PlayerProfile load(@NotNull UUID uuid);
/**
* Save a player profile.
*
* @param uuid The uuid.
*/
void savePlayer(@NotNull UUID uuid);
/**
* Save all player data.
*
* @param async If the saving should be done asynchronously.
*/
void saveAll(boolean async);
}

View File

@@ -0,0 +1,24 @@
package com.willfp.eco.core.data.keys;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* API to register persistent data keys.
*/
public interface KeyRegistry {
/**
* Register a persistent data key to be stored.
*
* @param key The key.
*/
void registerKey(@NotNull PersistentDataKey<?> key);
/**
* Get all registered keys.
*
* @return The keys.
*/
Set<PersistentDataKey<?>> getRegisteredKeys();
}

View File

@@ -0,0 +1,57 @@
package com.willfp.eco.core.data.keys;
import com.willfp.eco.core.Eco;
import lombok.Getter;
import org.bukkit.NamespacedKey;
import org.jetbrains.annotations.NotNull;
/**
* A persistent data key is a key with a type that can be stored about an offline player.
*
* @param <T> The type of the data.
*/
public class PersistentDataKey<T> {
/**
* The key of the persistent data value.
*/
@Getter
private final NamespacedKey key;
/**
* The default value for the key.
*/
@Getter
private final T defaultValue;
/**
* The persistent data key type.
*/
@Getter
private final PersistentDataKeyType type;
/**
* Create a new Persistent Data Key.
*
* @param key The key.
* @param type The data type.
* @param defaultValue The default value.
*/
public PersistentDataKey(@NotNull final NamespacedKey key,
@NotNull final PersistentDataKeyType type,
@NotNull final T defaultValue) {
this.key = key;
this.defaultValue = defaultValue;
this.type = type;
Eco.getHandler().getKeyRegistry().registerKey(this);
}
@Override
public String toString() {
return "PersistentDataKey{"
+ "key=" + key
+ ", defaultValue=" + defaultValue
+ ", type=" + type
+ '}';
}
}

View File

@@ -0,0 +1,26 @@
package com.willfp.eco.core.data.keys;
/**
* All storable data key types.
*/
public enum PersistentDataKeyType {
/**
* String.
*/
STRING,
/**
* Boolean.
*/
BOOLEAN,
/**
* Integer.
*/
INT,
/**
* Double.
*/
DOUBLE
}

View File

@@ -1,22 +1,12 @@
package com.willfp.eco.core.display; package com.willfp.eco.core.display;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.apache.commons.lang.Validate;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; 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.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; 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. * Utility class to manage client-side item display.
*/ */
@@ -28,29 +18,9 @@ public class Display {
public static final String PREFIX = "§z"; public static final String PREFIX = "§z";
/** /**
* All registered display modules. * The display handler.
*/ */
private static final Map<DisplayPriority, List<DisplayModule>> MODULES = new HashMap<>(); private static DisplayHandler handler = null;
/**
* NamespacedKey for finalizing.
*/
private static NamespacedKey finalizeKey = null;
/**
* Register display module.
*
* @param module The module.
*/
public void registerDisplayModule(@NotNull final DisplayModule module) {
List<DisplayModule> modules = MODULES.get(module.getPriority());
modules.removeIf(module1 -> module1.getPluginName().equalsIgnoreCase(module.getPluginName()));
modules.add(module);
MODULES.put(module.getPriority(), modules);
}
/** /**
* Display on ItemStacks. * Display on ItemStacks.
@@ -71,35 +41,7 @@ public class Display {
*/ */
public ItemStack display(@NotNull final ItemStack itemStack, public ItemStack display(@NotNull final ItemStack itemStack,
@Nullable final Player player) { @Nullable final Player player) {
Map<String, Object[]> pluginVarArgs = new HashMap<>(); return handler.display(itemStack, player);
for (DisplayPriority priority : DisplayPriority.values()) {
List<DisplayModule> modules = MODULES.get(priority);
for (DisplayModule module : modules) {
pluginVarArgs.put(module.getPluginName(), module.generateVarArgs(itemStack));
}
}
revert(itemStack);
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return itemStack;
}
for (DisplayPriority priority : DisplayPriority.values()) {
List<DisplayModule> modules = MODULES.get(priority);
for (DisplayModule module : modules) {
Object[] varargs = pluginVarArgs.get(module.getPluginName());
module.display(itemStack, varargs);
if (player != null) {
module.display(itemStack, player, varargs);
}
}
}
return itemStack;
} }
/** /**
@@ -131,31 +73,7 @@ public class Display {
* @return The ItemStack. * @return The ItemStack.
*/ */
public ItemStack revert(@NotNull final ItemStack itemStack) { public ItemStack revert(@NotNull final ItemStack itemStack) {
if (Display.isFinalized(itemStack)) { return handler.revert(itemStack);
unfinalize(itemStack);
}
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return itemStack;
}
List<String> lore = meta.getLore();
if (lore != null && lore.removeIf(line -> line.startsWith(Display.PREFIX))) { // only apply lore modification if needed
meta.setLore(lore);
itemStack.setItemMeta(meta);
}
for (DisplayPriority priority : DisplayPriority.values()) {
List<DisplayModule> modules = MODULES.get(priority);
for (DisplayModule module : modules) {
module.revert(itemStack);
}
}
return itemStack;
} }
/** /**
@@ -165,21 +83,7 @@ public class Display {
* @return The ItemStack. * @return The ItemStack.
*/ */
public ItemStack finalize(@NotNull final ItemStack itemStack) { public ItemStack finalize(@NotNull final ItemStack itemStack) {
Validate.notNull(finalizeKey, "Key cannot be null!"); return handler.finalize(itemStack);
if (itemStack.getType().getMaxStackSize() > 1) {
return itemStack;
}
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return itemStack;
}
PersistentDataContainer container = meta.getPersistentDataContainer();
container.set(finalizeKey, PersistentDataType.INTEGER, 1);
itemStack.setItemMeta(meta);
return itemStack;
} }
/** /**
@@ -189,18 +93,7 @@ public class Display {
* @return The ItemStack. * @return The ItemStack.
*/ */
public ItemStack unfinalize(@NotNull final ItemStack itemStack) { public ItemStack unfinalize(@NotNull final ItemStack itemStack) {
Validate.notNull(finalizeKey, "Key cannot be null!"); return handler.unfinalize(itemStack);
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return itemStack;
}
PersistentDataContainer container = meta.getPersistentDataContainer();
container.remove(finalizeKey);
itemStack.setItemMeta(meta);
return itemStack;
} }
/** /**
@@ -210,31 +103,77 @@ public class Display {
* @return If finalized. * @return If finalized.
*/ */
public boolean isFinalized(@NotNull final ItemStack itemStack) { public boolean isFinalized(@NotNull final ItemStack itemStack) {
Validate.notNull(finalizeKey, "Key cannot be null!"); return handler.isFinalized(itemStack);
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return false;
}
PersistentDataContainer container = meta.getPersistentDataContainer();
return container.has(finalizeKey, PersistentDataType.INTEGER);
} }
/** /**
* Set key to be used for finalization. * Register a new display module.
* *
* @param finalizeKey The key. * @param module The module.
*/ */
@ApiStatus.Internal public void registerDisplayModule(@NotNull final DisplayModule module) {
public static void setFinalizeKey(@NotNull final NamespacedKey finalizeKey) { handler.registerDisplayModule(module);
Display.finalizeKey = finalizeKey;
} }
static { /**
for (DisplayPriority priority : DisplayPriority.values()) { * Initialize the display system.
MODULES.put(priority, new ArrayList<>()); *
* @param handler The handler.
*/
@ApiStatus.Internal
public static void init(@NotNull final DisplayHandler handler) {
if (Display.handler != null) {
throw new IllegalArgumentException("Already Initialized!");
}
Display.handler = handler;
}
/**
* Extremely janky method - also internal, so don't use it. <b>This method is
* NOT part of the API and may be removed at any time!</b>
* <p>
* This calls a display module with the specified parameters, now
* you might ask why I need a static java method when the DisplayHandler
* implementation could just call it itself? Well, kotlin doesn't really
* like dealing with vararg ambiguity, and so while kotlin can't figure out
* what is and isn't a vararg when I call display with a player, java can.
* <p>
* Because of this, I need to have this part of the code in java.
*
* <b>Don't call this method as part of your plugins!</b>
* <p>
* No, seriously - don't. This skips a bunch of checks and you'll almost
* definitely break something.
*
* @param module The display module.
* @param itemStack The ItemStack.
* @param player The player.
* @param args The args.
*/
@ApiStatus.Internal
public static void callDisplayModule(@NotNull final DisplayModule module,
@NotNull final ItemStack itemStack,
@Nullable final Player player,
@NotNull final Object... args) {
module.display(itemStack, args);
if (player != null) {
module.display(itemStack, player, args);
} }
} }
/**
* Set the display handler.
* <p>
* Internal API component, you will cause bugs if you create your own handler.
*
* @param handler The handler.
*/
@ApiStatus.Internal
public static void setHandler(@NotNull final DisplayHandler handler) {
if (Display.handler != null) {
throw new IllegalStateException("Display already initialized!");
}
Display.handler = handler;
}
} }

View File

@@ -0,0 +1,60 @@
package com.willfp.eco.core.display;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Interface for display implementations.
*/
public interface DisplayHandler {
/**
* Register display module.
*
* @param module The module.
*/
void registerDisplayModule(@NotNull DisplayModule module);
/**
* Display on ItemStacks.
*
* @param itemStack The item.
* @param player The player.
* @return The ItemStack.
*/
ItemStack display(@NotNull ItemStack itemStack,
@Nullable Player player);
/**
* Revert on ItemStacks.
*
* @param itemStack The item.
* @return The ItemStack.
*/
ItemStack revert(@NotNull ItemStack itemStack);
/**
* Finalize an ItemStacks.
*
* @param itemStack The item.
* @return The ItemStack.
*/
ItemStack finalize(@NotNull ItemStack itemStack);
/**
* Unfinalize an ItemStacks.
*
* @param itemStack The item.
* @return The ItemStack.
*/
ItemStack unfinalize(@NotNull ItemStack itemStack);
/**
* If an item is finalized.
*
* @param itemStack The item.
* @return If finalized.
*/
boolean isFinalized(@NotNull ItemStack itemStack);
}

View File

@@ -36,7 +36,7 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
* @param itemStack The item. * @param itemStack The item.
* @param args Optional args for display. * @param args Optional args for display.
*/ */
protected void display(@NotNull final ItemStack itemStack, public void display(@NotNull final ItemStack itemStack,
@NotNull final Object... args) { @NotNull final Object... args) {
// Technically optional. // Technically optional.
} }
@@ -48,7 +48,7 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
* @param player The player. * @param player The player.
* @param args Optional args for display. * @param args Optional args for display.
*/ */
protected void display(@NotNull final ItemStack itemStack, public void display(@NotNull final ItemStack itemStack,
@Nullable final Player player, @Nullable final Player player,
@NotNull final Object... args) { @NotNull final Object... args) {
// Technically optional. // Technically optional.
@@ -59,7 +59,7 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
* *
* @param itemStack The item. * @param itemStack The item.
*/ */
protected void revert(@NotNull final ItemStack itemStack) { public void revert(@NotNull final ItemStack itemStack) {
// Technically optional. // Technically optional.
} }
@@ -69,7 +69,7 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
* @param itemStack The itemStack. * @param itemStack The itemStack.
* @return The plugin-specific varargs. * @return The plugin-specific varargs.
*/ */
protected Object[] generateVarArgs(@NotNull final ItemStack itemStack) { public Object[] generateVarArgs(@NotNull final ItemStack itemStack) {
return new Object[0]; return new Object[0];
} }

View File

@@ -1,11 +1,15 @@
package com.willfp.eco.core.extensions; package com.willfp.eco.core.extensions;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.updating.ConfigHandler;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.File;
/** /**
* An extension is a separate jar file that hooks into the base plugin jar. * An extension is a separate jar file that hooks into the base plugin jar.
* <p> * <p>
@@ -15,9 +19,9 @@ import org.jetbrains.annotations.NotNull;
* Syntactically, extensions are very similar to plugins in their own right, except that * Syntactically, extensions are very similar to plugins in their own right, except that
* they are loaded by another plugin. * they are loaded by another plugin.
* *
* @see <a href="https://ecoenchants.polymart.org">EcoEnchants extension examples.</a> * @see <a href="https://auxilor.polymart.org">Extension examples.</a>
*/ */
public abstract class Extension { public abstract class Extension implements PluginLike {
/** /**
* The {@link EcoPlugin} that this extension is for. * The {@link EcoPlugin} that this extension is for.
*/ */
@@ -103,4 +107,14 @@ public abstract class Extension {
Validate.notNull(metadata, "Metadata cannot be null!"); Validate.notNull(metadata, "Metadata cannot be null!");
return this.metadata.version(); return this.metadata.version();
} }
@Override
public File getDataFolder() {
return this.plugin.getDataFolder();
}
@Override
public ConfigHandler getConfigHandler() {
return this.plugin.getConfigHandler();
}
} }

View File

@@ -107,7 +107,7 @@ public interface FastItemStack {
* @param itemStack The ItemStack. * @param itemStack The ItemStack.
* @return The FastItemStack. * @return The FastItemStack.
*/ */
static FastItemStack wrap(final ItemStack itemStack) { static FastItemStack wrap(@Nullable final ItemStack itemStack) {
return Eco.getHandler().createFastItemStack(Objects.requireNonNullElseGet(itemStack, () -> new ItemStack(Material.AIR))); return Eco.getHandler().createFastItemStack(Objects.requireNonNullElseGet(itemStack, () -> new ItemStack(Material.AIR)));
} }
} }

View File

@@ -0,0 +1,44 @@
package com.willfp.eco.core.integrations.afk;
import lombok.experimental.UtilityClass;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/**
* Class to handle afk integrations.
*/
@UtilityClass
public class AFKManager {
/**
* A set of all registered integrations.
*/
private final Set<AFKWrapper> registered = new HashSet<>();
/**
* Register a new integration.
*
* @param integration The integration to register.
*/
public void register(@NotNull final AFKWrapper integration) {
registered.add(integration);
}
/**
* Get if a player is afk.
*
* @param player The player.
* @return If afk.
*/
public boolean isAfk(@NotNull final Player player) {
for (AFKWrapper afkWrapper : registered) {
if (afkWrapper.isAfk(player)) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,18 @@
package com.willfp.eco.core.integrations.afk;
import com.willfp.eco.core.integrations.Integration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Wrapper class for afk integrations.
*/
public interface AFKWrapper extends Integration {
/**
* Get if a player is afk.
*
* @param player The player.
* @return If afk.
*/
boolean isAfk(@NotNull Player player);
}

View File

@@ -29,6 +29,16 @@ public class AntigriefManager {
registered.add(antigrief); registered.add(antigrief);
} }
/**
* Unregister an AntiGrief/Land Management integration.
*
* @param antigrief The integration to unregister.
*/
public void unregister(@NotNull final AntigriefWrapper antigrief) {
registered.removeIf(it -> it.getPluginName().equalsIgnoreCase(antigrief.getPluginName()));
registered.remove(antigrief);
}
/** /**
* Can player break block. * Can player break block.
* *

View File

@@ -1,9 +1,11 @@
package com.willfp.eco.core.integrations.customitems; package com.willfp.eco.core.integrations.customitems;
import com.willfp.eco.core.integrations.Integration;
/** /**
* Wrapper class for custom item integrations. * Wrapper class for custom item integrations.
*/ */
public interface CustomItemsWrapper { public interface CustomItemsWrapper extends Integration {
/** /**
* Register all the custom items for a specific plugin into eco. * Register all the custom items for a specific plugin into eco.
* *

View File

@@ -0,0 +1,99 @@
package com.willfp.eco.core.integrations.economy;
import lombok.experimental.UtilityClass;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/**
* Class to handle economy.
*/
@UtilityClass
public class EconomyManager {
/**
* A set of all registered integrations.
*/
private final Set<EconomyWrapper> registered = new HashSet<>();
/**
* Register a new integration.
*
* @param integration The integration to register.
*/
public void register(@NotNull final EconomyWrapper integration) {
registered.add(integration);
}
/**
* Get if any economy registrations are registered.
*
* @return If any economy.
*/
public boolean hasRegistrations() {
return !registered.isEmpty();
}
/**
* Get if a player has a certain amount.
*
* @param player The player.
* @param amount The amount.
* @return If the player has the amount.
*/
public boolean hasAmount(@NotNull final OfflinePlayer player,
final double amount) {
for (EconomyWrapper wrapper : registered) {
return wrapper.hasAmount(player, amount);
}
return false;
}
/**
* Give money to a player.
*
* @param player The player.
* @param amount The amount to give.
* @return If the transaction was a success.
*/
public boolean giveMoney(@NotNull final OfflinePlayer player,
final double amount) {
for (EconomyWrapper wrapper : registered) {
return wrapper.giveMoney(player, amount);
}
return false;
}
/**
* Remove money from a player.
*
* @param player The player.
* @param amount The amount to remove.
* @return If the transaction was a success.
*/
public boolean removeMoney(@NotNull final OfflinePlayer player,
final double amount) {
for (EconomyWrapper wrapper : registered) {
return wrapper.removeMoney(player, amount);
}
return false;
}
/**
* Get the balance of a player.
*
* @param player The player.
* @return The balance.
*/
public double getBalance(@NotNull final OfflinePlayer player) {
for (EconomyWrapper wrapper : registered) {
return wrapper.getBalance(player);
}
return 0;
}
}

View File

@@ -0,0 +1,48 @@
package com.willfp.eco.core.integrations.economy;
import com.willfp.eco.core.integrations.Integration;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
/**
* Wrapper class for economy integrations.
*/
public interface EconomyWrapper extends Integration {
/**
* Get if a player has a certain amount.
*
* @param player The player.
* @param amount The amount.
* @return If the player has the amount.
*/
boolean hasAmount(@NotNull OfflinePlayer player,
double amount);
/**
* Give money to a player.
*
* @param player The player.
* @param amount The amount to give.
* @return If the transaction was a success.
*/
boolean giveMoney(@NotNull OfflinePlayer player,
double amount);
/**
* Remove money from a player.
*
* @param player The player.
* @param amount The amount to remove.
* @return If the transaction was a success.
*/
boolean removeMoney(@NotNull OfflinePlayer player,
double amount);
/**
* Get the balance of a player.
*
* @param player The player.
* @return The balance.
*/
double getBalance(@NotNull OfflinePlayer player);
}

View File

@@ -0,0 +1,20 @@
package com.willfp.eco.core.integrations.hologram;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Dummy hologram, created if no integrations are present on the server.
*/
class DummyHologram implements Hologram {
@Override
public void remove() {
// Do nothing.
}
@Override
public void setContents(@NotNull final List<String> contents) {
// Do nothing.
}
}

View File

@@ -0,0 +1,22 @@
package com.willfp.eco.core.integrations.hologram;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Wrapper class for plugin-specific holograms.
*/
public interface Hologram {
/**
* Remove the hologram.
*/
void remove();
/**
* Set the hologram contents.
*
* @param contents The contents.
*/
void setContents(@NotNull List<String> contents);
}

View File

@@ -0,0 +1,45 @@
package com.willfp.eco.core.integrations.hologram;
import lombok.experimental.UtilityClass;
import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Class to handle hologram integrations.
*/
@UtilityClass
public class HologramManager {
/**
* A set of all registered integrations.
*/
private final Set<HologramWrapper> registered = new HashSet<>();
/**
* Register a new integration.
*
* @param integration The integration to register.
*/
public void register(@NotNull final HologramWrapper integration) {
registered.add(integration);
}
/**
* Create hologram.
*
* @param location The location.
* @param contents The contents for the hologram.
* @return The hologram.
*/
public Hologram createHologram(@NotNull final Location location,
@NotNull final List<String> contents) {
for (HologramWrapper wrapper : registered) {
return wrapper.createHologram(location, contents);
}
return new DummyHologram();
}
}

View File

@@ -0,0 +1,22 @@
package com.willfp.eco.core.integrations.hologram;
import com.willfp.eco.core.integrations.Integration;
import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Wrapper class for hologram integrations.
*/
public interface HologramWrapper extends Integration {
/**
* Create hologram.
*
* @param location The location.
* @param contents The contents for the hologram.
* @return The hologram.
*/
Hologram createHologram(@NotNull Location location,
@NotNull List<String> contents);
}

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.integrations.mcmmo; package com.willfp.eco.core.integrations.mcmmo;
import com.willfp.eco.core.integrations.Integration;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -7,7 +8,7 @@ import org.jetbrains.annotations.NotNull;
/** /**
* Wrapper class for mcmmo integrations. * Wrapper class for mcmmo integrations.
*/ */
public interface McmmoWrapper { public interface McmmoWrapper extends Integration {
/** /**
* Get bonus drop count of block. * Get bonus drop count of block.
* *

View File

@@ -5,10 +5,10 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Optional; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/** /**
* Class to handle placeholder integrations. * Class to handle placeholder integrations.
@@ -18,7 +18,7 @@ public class PlaceholderManager {
/** /**
* All registered placeholders. * All registered placeholders.
*/ */
private static final Set<PlaceholderEntry> REGISTERED_PLACEHOLDERS = new HashSet<>(); private static final Map<String, PlaceholderEntry> REGISTERED_PLACEHOLDERS = new HashMap<>();
/** /**
* All registered placeholder integrations. * All registered placeholder integrations.
@@ -41,8 +41,8 @@ public class PlaceholderManager {
* @param expansion The {@link PlaceholderEntry} to register. * @param expansion The {@link PlaceholderEntry} to register.
*/ */
public static void registerPlaceholder(@NotNull final PlaceholderEntry expansion) { public static void registerPlaceholder(@NotNull final PlaceholderEntry expansion) {
REGISTERED_PLACEHOLDERS.removeIf(placeholderEntry -> placeholderEntry.getIdentifier().equalsIgnoreCase(expansion.getIdentifier())); REGISTERED_PLACEHOLDERS.remove(expansion.getIdentifier());
REGISTERED_PLACEHOLDERS.add(expansion); REGISTERED_PLACEHOLDERS.put(expansion.getIdentifier(), expansion);
} }
/** /**
@@ -54,14 +54,15 @@ public class PlaceholderManager {
*/ */
public static String getResult(@Nullable final Player player, public static String getResult(@Nullable final Player player,
@NotNull final String identifier) { @NotNull final String identifier) {
Optional<PlaceholderEntry> matching = REGISTERED_PLACEHOLDERS.stream().filter(expansion -> expansion.getIdentifier().equalsIgnoreCase(identifier)).findFirst(); PlaceholderEntry entry = REGISTERED_PLACEHOLDERS.get(identifier.toLowerCase());
if (matching.isEmpty()) { if (entry == null) {
return ""; return "";
} }
PlaceholderEntry entry = matching.get();
if (player == null && entry.requiresPlayer()) { if (player == null && entry.requiresPlayer()) {
return ""; return "";
} }
return entry.getResult(player); return entry.getResult(player);
} }
@@ -74,8 +75,10 @@ public class PlaceholderManager {
*/ */
public static String translatePlaceholders(@NotNull final String text, public static String translatePlaceholders(@NotNull final String text,
@Nullable final Player player) { @Nullable final Player player) {
AtomicReference<String> translatedReference = new AtomicReference<>(text); String processed = text;
REGISTERED_INTEGRATIONS.forEach(placeholderIntegration -> translatedReference.set(placeholderIntegration.translate(translatedReference.get(), player))); for (PlaceholderIntegration integration : REGISTERED_INTEGRATIONS) {
return translatedReference.get(); processed = integration.translate(processed, player);
}
return processed;
} }
} }

View File

@@ -1,9 +1,11 @@
package com.willfp.eco.core.integrations.shop; package com.willfp.eco.core.integrations.shop;
import com.willfp.eco.core.integrations.Integration;
/** /**
* Wrapper class for shop integrations. * Wrapper class for shop integrations.
*/ */
public interface ShopWrapper { public interface ShopWrapper extends Integration {
/** /**
* Register eco item provider for shop plugins. * Register eco item provider for shop plugins.
*/ */

View File

@@ -1,6 +1,8 @@
package com.willfp.eco.core.items; package com.willfp.eco.core.items;
import com.willfp.eco.core.Eco;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -9,7 +11,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate; import java.util.function.Predicate;
/** /**
* A custom item has 3 components: * A custom item has 3 components.
* *
* <ul> * <ul>
* <li>The key to identify it</li> * <li>The key to identify it</li>
@@ -47,6 +49,12 @@ public class CustomItem implements TestableItem {
this.key = key; this.key = key;
this.test = test; this.test = test;
this.item = item; this.item = item;
Eco.getHandler().getEcoPlugin().getScheduler().runLater(() -> {
if (!matches(getItem())) {
Bukkit.getLogger().severe("Item with key " + key + " is invalid!");
}
}, 1);
} }
@Override @Override

View File

@@ -1,25 +1,29 @@
package com.willfp.eco.core.items; package com.willfp.eco.core.items;
import com.willfp.eco.core.items.args.LookupArgParser;
import com.willfp.eco.core.items.provider.ItemProvider;
import com.willfp.eco.core.recipe.parts.EmptyTestableItem; import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
import com.willfp.eco.core.recipe.parts.MaterialTestableItem; import com.willfp.eco.core.recipe.parts.MaterialTestableItem;
import com.willfp.eco.core.recipe.parts.ModifiedTestableItem; import com.willfp.eco.core.recipe.parts.ModifiedTestableItem;
import com.willfp.eco.core.recipe.parts.TestableStack; import com.willfp.eco.core.recipe.parts.TestableStack;
import com.willfp.eco.util.NamespacedKeyUtils; import com.willfp.eco.util.NamespacedKeyUtils;
import com.willfp.eco.util.NumberUtils;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.List;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/** /**
* Class to manage all custom and vanilla items. * Class to manage all custom and vanilla items.
@@ -29,17 +33,45 @@ public final class Items {
/** /**
* All recipe parts. * All recipe parts.
*/ */
private static final Map<NamespacedKey, CustomItem> REGISTRY = new HashMap<>(); private static final Map<NamespacedKey, TestableItem> REGISTRY = new ConcurrentHashMap<>();
/** /**
* Register a new recipe part. * All item providers.
*/
private static final Map<String, ItemProvider> PROVIDERS = new ConcurrentHashMap<>();
/**
* All recipe parts.
*/
private static final List<LookupArgParser> ARG_PARSERS = new ArrayList<>();
/**
* Register a new custom item.
* *
* @param key The key of the recipe part. * @param key The key of the item.
* @param part The recipe part. * @param item The item.
*/ */
public void registerCustomItem(@NotNull final NamespacedKey key, public void registerCustomItem(@NotNull final NamespacedKey key,
@NotNull final CustomItem part) { @NotNull final TestableItem item) {
REGISTRY.put(key, part); REGISTRY.put(key, item);
}
/**
* Register a new item provider.
*
* @param provider The provider.
*/
public void registerItemProvider(@NotNull final ItemProvider provider) {
PROVIDERS.put(provider.getNamespace(), provider);
}
/**
* Register a new arg parser.
*
* @param parser The parser.
*/
public void registerArgParser(@NotNull final LookupArgParser parser) {
ARG_PARSERS.add(parser);
} }
/** /**
@@ -52,12 +84,27 @@ public final class Items {
} }
/** /**
* Lookup item from string. * This is the backbone of the entire eco item system.
* <p> * <p>
* Used for recipes. * You can lookup a TestableItem for any material, custom item,
* or item in general, and it will return it with any modifiers
* passed as parameters. This includes stack size (item amount)
* and enchantments that should be present on the item.
* <p>
* If you want to get an ItemStack instance from this, then just call
* {@link TestableItem#getItem()}.
* <p>
* The advantages of the testable item system are that there is the inbuilt
* {@link TestableItem#matches(ItemStack)} - this allows to check if any item
* is that testable item; which may sound negligible but actually it allows for
* much more power an flexibility. For example, you can have an item with an
* extra metadata tag, extra lore lines, different display name - and it
* will still work as long as the test passes. This is very important
* for custom crafting recipes where other plugins may add metadata
* values or the play may rename the item.
* *
* @param key The string to test. * @param key The lookup string.
* @return The found testable item, or an empty item if not found. * @return The testable item, or an {@link EmptyTestableItem}.
*/ */
public TestableItem lookup(@NotNull final String key) { public TestableItem lookup(@NotNull final String key) {
if (key.contains("?")) { if (key.contains("?")) {
@@ -79,6 +126,8 @@ public final class Items {
TestableItem item = null; TestableItem item = null;
int stackAmount = 1;
String[] split = args[0].toLowerCase().split(":"); String[] split = args[0].toLowerCase().split(":");
if (split.length == 1) { if (split.length == 1) {
@@ -90,86 +139,89 @@ public final class Items {
} }
if (split.length == 2) { if (split.length == 2) {
CustomItem part = REGISTRY.get(NamespacedKeyUtils.create(split[0], split[1])); String namespace = split[0];
String keyID = split[1];
NamespacedKey namespacedKey = NamespacedKeyUtils.create(namespace, keyID);
TestableItem part = REGISTRY.get(namespacedKey);
if (part == null && PROVIDERS.containsKey(namespace)) {
ItemProvider provider = PROVIDERS.get(namespace);
item = provider.provideForKey(keyID);
if (item instanceof EmptyTestableItem || item == null) {
return new EmptyTestableItem();
}
registerCustomItem(namespacedKey, item);
}
/*
Legacy id:amount format
This has been superseded by id amount
*/
if (part == null) { if (part == null) {
Material material = Material.getMaterial(split[0].toUpperCase()); Material material = Material.getMaterial(split[0].toUpperCase());
if (material == null || material == Material.AIR) { if (material == null || material == Material.AIR) {
return new EmptyTestableItem(); return new EmptyTestableItem();
} }
item = new TestableStack(new MaterialTestableItem(material), Integer.parseInt(split[1])); item = new MaterialTestableItem(material);
stackAmount = Integer.parseInt(split[1]);
} else { } else {
item = part; item = part;
} }
} }
/*
Legacy namespace:id:amount format
This has been superseded by namespace:id amount
*/
if (split.length == 3) { if (split.length == 3) {
CustomItem part = REGISTRY.get(NamespacedKeyUtils.create(split[0], split[1])); TestableItem part = REGISTRY.get(NamespacedKeyUtils.create(split[0], split[1]));
item = part == null ? new EmptyTestableItem() : new TestableStack(part, Integer.parseInt(split[2])); if (part == null) {
return new EmptyTestableItem();
}
item = part;
stackAmount = Integer.parseInt(split[2]);
} }
boolean usingNewStackFormat = false;
if (args.length >= 2) {
try {
stackAmount = Integer.parseInt(args[1]);
usingNewStackFormat = true;
} catch (NumberFormatException ignored) {
}
}
// Marked as redundant but i am covering all bases here
if (item == null || item instanceof EmptyTestableItem) { if (item == null || item instanceof EmptyTestableItem) {
return new 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;
}
ItemStack example = item.getItem(); ItemStack example = item.getItem();
if (example.getItemMeta() instanceof EnchantmentStorageMeta storageMeta) {
requiredEnchantments.forEach((enchantment, integer) -> storageMeta.addStoredEnchant(enchantment, integer, true));
example.setItemMeta(storageMeta);
} else {
ItemMeta meta = example.getItemMeta(); ItemMeta meta = example.getItemMeta();
assert meta != null; assert meta != null;
requiredEnchantments.forEach((enchantment, integer) -> meta.addEnchant(enchantment, integer, true));
String[] modifierArgs = Arrays.copyOfRange(args, usingNewStackFormat ? 2 : 1, args.length);
List<Predicate<ItemStack>> predicates = new ArrayList<>();
for (LookupArgParser argParser : ARG_PARSERS) {
Predicate<ItemStack> predicate = argParser.parseArguments(modifierArgs, meta);
if (predicate != null) {
predicates.add(argParser.parseArguments(modifierArgs, meta));
}
}
example.setItemMeta(meta); example.setItemMeta(meta);
} if (!predicates.isEmpty()) {
item = new ModifiedTestableItem(
return new ModifiedTestableItem(
item, item,
itemStack -> { test -> {
if (!itemStack.hasItemMeta()) { for (Predicate<ItemStack> predicate : predicates) {
if (!predicate.test(test)) {
return false; return false;
} }
ItemMeta meta = itemStack.getItemMeta();
assert meta != null;
if (meta instanceof EnchantmentStorageMeta storageMeta) {
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
if (!storageMeta.hasStoredEnchant(entry.getKey())) {
return false;
}
if (storageMeta.getStoredEnchantLevel(entry.getKey()) < entry.getValue()) {
return false;
}
}
} else {
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; return true;
@@ -178,6 +230,13 @@ public final class Items {
); );
} }
if (stackAmount <= 1) {
return item;
} else {
return new TestableStack(item, stackAmount);
}
}
/** /**
* Get if itemStack is a custom item. * Get if itemStack is a custom item.
* *
@@ -185,7 +244,7 @@ public final class Items {
* @return If is recipe. * @return If is recipe.
*/ */
public boolean isCustomItem(@NotNull final ItemStack itemStack) { public boolean isCustomItem(@NotNull final ItemStack itemStack) {
for (CustomItem item : REGISTRY.values()) { for (TestableItem item : REGISTRY.values()) {
if (item.matches(itemStack)) { if (item.matches(itemStack)) {
return true; return true;
} }
@@ -201,9 +260,9 @@ public final class Items {
*/ */
@Nullable @Nullable
public CustomItem getCustomItem(@NotNull final ItemStack itemStack) { public CustomItem getCustomItem(@NotNull final ItemStack itemStack) {
for (CustomItem item : REGISTRY.values()) { for (TestableItem item : REGISTRY.values()) {
if (item.matches(itemStack)) { if (item.matches(itemStack)) {
return item; return getOrWrap(item);
} }
} }
return null; return null;
@@ -215,6 +274,27 @@ public final class Items {
* @return A set of all items. * @return A set of all items.
*/ */
public Set<CustomItem> getCustomItems() { public Set<CustomItem> getCustomItems() {
return new HashSet<>(REGISTRY.values()); return REGISTRY.values().stream().map(Items::getOrWrap).collect(Collectors.toSet());
}
/**
* Return a CustomItem instance for a given TestableItem.
* <p>
* Used internally since 6.10.0 when the registration moved from {@link CustomItem}
* to {@link TestableItem} for added flexibility.
*
* @param item The item.
* @return The CustomItem.
*/
public CustomItem getOrWrap(@NotNull final TestableItem item) {
if (item instanceof CustomItem) {
return (CustomItem) item;
} else {
return new CustomItem(
NamespacedKeyUtils.createEcoKey("wrapped_" + NumberUtils.randInt(0, 100000)),
item::matches,
item.getItem()
);
}
} }
} }

View File

@@ -0,0 +1,83 @@
package com.willfp.eco.core.items.args;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
/**
* Parses enchantment arguments.
*/
public class EnchantmentArgParser implements LookupArgParser {
@Override
public @Nullable Predicate<ItemStack> parseArguments(@NotNull final String[] args,
@NotNull final ItemMeta meta) {
Map<Enchantment, Integer> requiredEnchantments = new HashMap<>();
for (String enchantArg : args) {
String[] enchantArgSplit = enchantArg.split(":");
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(enchantArgSplit[0].toLowerCase()));
if (enchantment == null) {
continue;
}
if (enchantArgSplit.length < 2) {
continue;
}
int level = Integer.parseInt(enchantArgSplit[1]);
requiredEnchantments.put(enchantment, level);
}
if (requiredEnchantments.isEmpty()) {
return null;
}
if (meta instanceof EnchantmentStorageMeta storageMeta) {
requiredEnchantments.forEach((enchantment, integer) -> storageMeta.addStoredEnchant(enchantment, integer, true));
} else {
requiredEnchantments.forEach((enchantment, integer) -> meta.addEnchant(enchantment, integer, true));
}
return test -> {
if (!test.hasItemMeta()) {
return false;
}
ItemMeta testMeta = test.getItemMeta();
assert testMeta != null;
if (testMeta instanceof EnchantmentStorageMeta storageMeta) {
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
if (!storageMeta.hasStoredEnchant(entry.getKey())) {
return false;
}
if (storageMeta.getStoredEnchantLevel(entry.getKey()) < entry.getValue()) {
return false;
}
}
} else {
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
if (!testMeta.hasEnchant(entry.getKey())) {
return false;
}
if (testMeta.getEnchantLevel(entry.getKey()) < entry.getValue()) {
return false;
}
}
}
return true;
};
}
}

View File

@@ -0,0 +1,25 @@
package com.willfp.eco.core.items.args;
import com.willfp.eco.core.items.TestableItem;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* An argument parser should generate the predicate as well
* as modify the ItemMeta for {@link TestableItem#getItem()}.
*/
public interface LookupArgParser {
/**
* Parse the arguments.
*
* @param args The arguments.
* @param meta The ItemMeta to modify.
* @return The predicate test to apply to the modified item.
*/
@Nullable Predicate<ItemStack> parseArguments(@NotNull String[] args,
@NotNull ItemMeta meta);
}

View File

@@ -0,0 +1,59 @@
package com.willfp.eco.core.items.args;
import com.willfp.eco.util.SkullUtils;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* Parse skull textures.
*/
public class TextureArgParser implements LookupArgParser {
@Override
public @Nullable Predicate<ItemStack> parseArguments(@NotNull final String[] args,
@NotNull final ItemMeta meta) {
String skullTexture = null;
for (String arg : args) {
String[] argSplit = arg.split(":");
if (!argSplit[0].equalsIgnoreCase("texture")) {
continue;
}
if (argSplit.length < 2) {
continue;
}
skullTexture = argSplit[1];
}
if (meta instanceof SkullMeta skullMeta && skullTexture != null) {
SkullUtils.setSkullTexture(skullMeta, skullTexture);
}
if (skullTexture == null) {
return null;
}
String finalSkullTexture = skullTexture;
return test -> {
if (!test.hasItemMeta()) {
return false;
}
ItemMeta testMeta = test.getItemMeta();
assert testMeta != null;
if (testMeta instanceof SkullMeta skullMeta) {
return finalSkullTexture.equalsIgnoreCase(SkullUtils.getSkullTexture(skullMeta));
}
return true;
};
}
}

View File

@@ -0,0 +1,40 @@
package com.willfp.eco.core.items.provider;
import com.willfp.eco.core.items.TestableItem;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Item providers are call-site registrations for items. In other words,
* they only register their items when a request is made. This is marginally
* slower, however it is required for certain plugins, and fixes bugs related to
* loading orders.
*
* @see TestableItem
*/
public abstract class ItemProvider {
/**
* The namespace.
*/
@Getter
private final String namespace;
/**
* Create a new ItemProvider for a specific namespace.
*
* @param namespace The namespace.
*/
protected ItemProvider(@NotNull final String namespace) {
this.namespace = namespace;
}
/**
* Provide a TestableItem for a given key.
*
* @param key The item ID.
* @return The TestableItem, or null if not found.
*/
@Nullable
public abstract TestableItem provideForKey(@NotNull String key);
}

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.recipe.parts;
import com.willfp.eco.core.items.TestableItem; import com.willfp.eco.core.items.TestableItem;
import lombok.Getter; import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -23,6 +24,8 @@ public class MaterialTestableItem implements TestableItem {
* @param material The material. * @param material The material.
*/ */
public MaterialTestableItem(@NotNull final Material material) { public MaterialTestableItem(@NotNull final Material material) {
Validate.isTrue(material != Material.AIR, "You can't have air as the type!");
this.material = material; this.material = material;
} }

View File

@@ -1,17 +1,12 @@
package com.willfp.eco.core.recipe.parts; package com.willfp.eco.core.recipe.parts;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.items.TestableItem; import com.willfp.eco.core.items.TestableItem;
import lombok.Getter; import lombok.Getter;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/** /**
* Stacks of items. * Stacks of items.
*/ */
@@ -36,7 +31,8 @@ public class TestableStack implements TestableItem {
*/ */
public TestableStack(@NotNull final TestableItem item, public TestableStack(@NotNull final TestableItem item,
final int amount) { final int amount) {
Validate.isTrue(!(item instanceof TestableStack)); Validate.isTrue(!(item instanceof TestableStack), "You can't stack a stack!");
Validate.isTrue(!(item instanceof EmptyTestableItem), "You can't stack air!");
this.handle = item; this.handle = item;
this.amount = amount; this.amount = amount;
@@ -56,19 +52,7 @@ public class TestableStack implements TestableItem {
@Override @Override
public ItemStack getItem() { public ItemStack getItem() {
ItemStack temp = handle.getItem().clone(); ItemStack temp = handle.getItem().clone();
ItemMeta meta = temp.getItemMeta();
assert meta != null;
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
assert lore != null;
lore.add("");
String add = Eco.getHandler().getEcoPlugin().getLangYml().getString("multiple-in-craft");
add = add.replace("%amount%", String.valueOf(amount));
lore.add(add);
meta.setLore(lore);
temp.setItemMeta(meta);
temp.setAmount(amount); temp.setAmount(amount);
return temp; return temp;
} }
} }

View File

@@ -1,16 +1,19 @@
package com.willfp.eco.core.recipe.recipes; package com.willfp.eco.core.recipe.recipes;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent; import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.items.TestableItem; import com.willfp.eco.core.items.TestableItem;
import com.willfp.eco.core.recipe.Recipes; import com.willfp.eco.core.recipe.Recipes;
import com.willfp.eco.core.recipe.parts.EmptyTestableItem; import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
import com.willfp.eco.core.recipe.parts.TestableStack;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.RecipeChoice; import org.bukkit.inventory.RecipeChoice;
import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
@@ -79,6 +82,10 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
ShapedRecipe shapedRecipe = new ShapedRecipe(this.getKey(), this.getOutput()); ShapedRecipe shapedRecipe = new ShapedRecipe(this.getKey(), this.getOutput());
shapedRecipe.shape("012", "345", "678"); shapedRecipe.shape("012", "345", "678");
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
if (parts.get(i) instanceof EmptyTestableItem) {
continue;
}
char character = String.valueOf(i).toCharArray()[0]; char character = String.valueOf(i).toCharArray()[0];
shapedRecipe.setIngredient(character, parts.get(i).getItem().getType()); shapedRecipe.setIngredient(character, parts.get(i).getItem().getType());
} }
@@ -86,8 +93,28 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
ShapedRecipe displayedRecipe = new ShapedRecipe(this.getDisplayedKey(), this.getOutput()); ShapedRecipe displayedRecipe = new ShapedRecipe(this.getDisplayedKey(), this.getOutput());
displayedRecipe.shape("012", "345", "678"); displayedRecipe.shape("012", "345", "678");
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
if (parts.get(i) instanceof EmptyTestableItem) {
continue;
}
char character = String.valueOf(i).toCharArray()[0]; char character = String.valueOf(i).toCharArray()[0];
displayedRecipe.setIngredient(character, new RecipeChoice.ExactChoice(parts.get(i).getItem())); ItemStack item = parts.get(i).getItem();
if (parts.get(i) instanceof TestableStack) {
ItemMeta meta = item.getItemMeta();
assert meta != null;
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
assert lore != null;
lore.add("");
String add = Eco.getHandler().getEcoPlugin().getLangYml().getString("multiple-in-craft");
add = add.replace("%amount%", String.valueOf(item.getAmount()));
lore.add(add);
meta.setLore(lore);
item.setItemMeta(meta);
}
displayedRecipe.setIngredient(character, new RecipeChoice.ExactChoice(item));
} }
Bukkit.getServer().addRecipe(shapedRecipe); Bukkit.getServer().addRecipe(shapedRecipe);

View File

@@ -0,0 +1,28 @@
package com.willfp.eco.core.requirement;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* A requirement is a defined goal that a player must meet.
*/
public abstract class Requirement {
/**
* Create a new requirement.
*/
protected Requirement() {
}
/**
* Test if the player meets the requirement.
*
* @param player The player.
* @param args The arguments.
* @return The requirement.
*/
public abstract boolean doesPlayerMeet(@NotNull Player player,
@NotNull List<String> args);
}

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.core.requirement;
import org.jetbrains.annotations.NotNull;
/**
* Interface for internal requirement factory implementations.
*/
public interface RequirementFactory {
/**
* Create a requirement.
*
* @param name The name.
* @return The requirement returned for the name.
* Will return a requirement that is always true if not found.
*/
Requirement create(@NotNull String name);
}

View File

@@ -0,0 +1,41 @@
package com.willfp.eco.core.requirement;
import com.willfp.eco.core.Eco;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
/**
* Contains methods and fields pertaining to requirements.
*/
@UtilityClass
public class Requirements {
/**
* Requires a player to have a permission.
*/
public static final Requirement HAS_PERMISSION = Eco.getHandler().getRequirementFactory().create("has-permission");
/**
* Placeholder equals value.
*/
public static final Requirement PLACEHOLDER_EQUALS = Eco.getHandler().getRequirementFactory().create("placeholder-equals");
/**
* Numeric placeholder greater than value.
*/
public static final Requirement PLACEHOLDER_GREATER_THAN = Eco.getHandler().getRequirementFactory().create("placeholder-greater-than");
/**
* Numeric placeholder less than value.
*/
public static final Requirement PLACEHOLDER_LESS_THAN = Eco.getHandler().getRequirementFactory().create("placeholder-less-than");
/**
* Get Requirements matching ID.
*
* @param name The ID to search for.
* @return The matching Requirements.
*/
public static Requirement getByID(@NotNull final String name) {
return Eco.getHandler().getRequirementFactory().create(name);
}
}

View File

@@ -38,4 +38,26 @@ public class Pair<A, B> {
this.first = first; this.first = first;
this.second = second; this.second = second;
} }
/**
* component1 exists to allow a pair to be destructured by kotlin.
* The default kotlin pair already has this, however there is no default
* pair in java so this exists for parity.
*
* @return First.
*/
public A component1() {
return first;
}
/**
* component2 exists to allow a pair to be destructured by kotlin.
* The default kotlin pair already has this, however there is no default
* pair in java so this exists for parity.
*
* @return First.
*/
public B component2() {
return second;
}
} }

View File

@@ -34,4 +34,15 @@ public class Triplet<A, B, C> extends Pair<A, B> {
this.third = third; this.third = third;
} }
/**
* component3 exists to allow a pair to be destructured by kotlin.
* The default kotlin pair already has this, however there is no default
* pair in java so this exists for parity.
*
* @return First.
*/
public C component3() {
return third;
}
} }

View File

@@ -4,6 +4,7 @@ import com.willfp.eco.core.Eco;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
@@ -11,7 +12,6 @@ import java.io.InputStreamReader;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -40,45 +40,42 @@ public class Paste {
* <p> * <p>
* Runs asynchronously to avoid hangups. * Runs asynchronously to avoid hangups.
* *
* @param responseHandler The consumer to accept the response token. * @param callback The consumer to accept the response token.
*/ */
public void getHastebinToken(@NotNull final Consumer<String> responseHandler) { public void getHastebinToken(@NotNull final Consumer<String> callback) {
Eco.getHandler().getEcoPlugin().getScheduler().runAsync(() -> { Eco.getHandler().getEcoPlugin().getScheduler().runAsync(() -> {
try { try {
String url = "https://hastebin.com/documents"; byte[] postData = contents.getBytes(StandardCharsets.UTF_8);
URL obj = new URL(url); int postDataLength = postData.length;
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST"); String requestURL = "https://hastebin.com/documents";
con.setRequestProperty("Content-Type", "application/json"); URL url = new URL(requestURL);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setInstanceFollowRedirects(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("User-Agent", "eco-Hastebin");
conn.setRequestProperty("Content-Length", Integer.toString(postDataLength));
conn.setUseCaches(false);
con.setDoOutput(true); String response;
DataOutputStream wr = new DataOutputStream(con.getOutputStream()); DataOutputStream wr;
wr.writeBytes(URLEncoder.encode(contents, StandardCharsets.UTF_8));
wr.flush();
wr.close();
BufferedReader iny = new BufferedReader( wr = new DataOutputStream(conn.getOutputStream());
new InputStreamReader(con.getInputStream())); wr.write(postData);
String output; BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder responseBuilder = new StringBuilder(); response = reader.readLine();
while ((output = iny.readLine()) != null) { assert response != null;
responseBuilder.append(output);
if (response.contains("\"key\"")) {
response = response.substring(response.indexOf(":") + 2, response.length() - 2);
callback.accept(response);
} }
iny.close();
String responseString = responseBuilder.toString();
responseString = responseString.replace("{\"key\":\"", "");
responseString = responseString.replace("\"}", "");
responseHandler.accept(responseString);
} catch (IOException e) { } catch (IOException e) {
responseHandler.accept(e.getMessage()); callback.accept(e.getMessage());
} }
responseHandler.accept("");
}); });
} }

View File

@@ -26,16 +26,18 @@ public class UpdateChecker extends PluginDependent<EcoPlugin> {
/** /**
* Get the latest version of the plugin. * Get the latest version of the plugin.
* *
* @param consumer The process to run after checking. * @param callback The process to run after checking.
*/ */
public void getVersion(@NotNull final Consumer<? super String> consumer) { public void getVersion(@NotNull final Consumer<? super String> callback) {
this.getPlugin().getScheduler().runAsync(() -> { this.getPlugin().getScheduler().runAsync(() -> {
try { try {
InputStream inputStream = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + this.getPlugin().getResourceId()).openStream(); InputStream inputStream = new URL(
"https://api.polymart.org/v1/getResourceInfoSimple?key=version&resource_id=" + this.getPlugin().getResourceId()
).openStream();
Scanner scanner = new Scanner(inputStream); Scanner scanner = new Scanner(inputStream);
if (scanner.hasNext()) { if (scanner.hasNext()) {
consumer.accept(scanner.next()); callback.accept(scanner.next());
} }
} catch (IOException e) { } catch (IOException e) {
this.getPlugin().getLogger().warning("Failed to check for updates: " + e.getMessage()); this.getPlugin().getLogger().warning("Failed to check for updates: " + e.getMessage());

View File

@@ -19,7 +19,7 @@ public class ArrowUtils {
* Get the bow from an arrow. * Get the bow from an arrow.
* *
* @param arrow The arrow. * @param arrow The arrow.
* @return The bow. * @return The bow, or null if no bow.
*/ */
@Nullable @Nullable
public ItemStack getBow(@NotNull final Arrow arrow) { public ItemStack getBow(@NotNull final Arrow arrow) {

View File

@@ -2,12 +2,14 @@ package com.willfp.eco.util;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -63,6 +65,7 @@ public class BlockUtils {
* @param limit The maximum size of vein to return. * @param limit The maximum size of vein to return.
* @return A set of all {@link Block}s. * @return A set of all {@link Block}s.
*/ */
@NotNull
public Set<Block> getVein(@NotNull final Block start, public Set<Block> getVein(@NotNull final Block start,
@NotNull final List<Material> allowedMaterials, @NotNull final List<Material> allowedMaterials,
final int limit) { final int limit) {
@@ -91,6 +94,21 @@ public class BlockUtils {
blockBreakConsumer.accept(player, block); blockBreakConsumer.accept(player, block);
} }
/**
* Get if a block was placed by a player.
*
* @param block The block.
* @return If placed by a player.
*/
public boolean isPlayerPlaced(@NotNull final Block block) {
Chunk chunk = block.getChunk();
return chunk.getPersistentDataContainer().has(
NamespacedKeyUtils.createEcoKey(Integer.toString(block.getLocation().hashCode(), 16)),
PersistentDataType.INTEGER
);
}
/** /**
* Initialize the block break function. * Initialize the block break function.
* *

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.util;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -10,18 +11,37 @@ import org.jetbrains.annotations.NotNull;
*/ */
@UtilityClass @UtilityClass
public class LightningUtils { public class LightningUtils {
/** /**
* Strike lightning on player without fire. * Strike lightning on player without fire.
* *
* @param victim The entity to smite. * @param victim The entity to smite.
* @param damage The damage to deal. * @param damage The damage to deal.
* @param silent If the lightning sound should be played locally
*/
public void strike(@NotNull final LivingEntity victim,
final double damage,
final boolean silent) {
Location loc = victim.getLocation();
if (silent) {
victim.getWorld().spigot().strikeLightningEffect(loc, true);
victim.getWorld().playSound(loc, Sound.ENTITY_LIGHTNING_BOLT_IMPACT, 1, 1);
} else {
victim.getWorld().strikeLightningEffect(loc);
}
victim.damage(damage);
}
/**
* Strike lightning on a victim without fire.
*
* @param victim The entity to smite.
* @param damage The damage to deal.
*/ */
public void strike(@NotNull final LivingEntity victim, public void strike(@NotNull final LivingEntity victim,
final double damage) { final double damage) {
Location loc = victim.getLocation(); strike(victim, damage, false);
victim.getWorld().strikeLightningEffect(loc);
victim.damage(damage);
} }
} }

View File

@@ -1,9 +1,13 @@
package com.willfp.eco.util; package com.willfp.eco.util;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Utilities / API methods for lists. * Utilities / API methods for lists.
@@ -18,7 +22,8 @@ public class ListUtils {
* @param <T> The type of the object stored in the list. * @param <T> The type of the object stored in the list.
* @return The list, filled will null objects. * @return The list, filled will null objects.
*/ */
public <T> List<List<T>> create2DList(final int rows, @NotNull
public static <@Nullable T> List<List<T>> create2DList(final int rows,
final int columns) { final int columns) {
List<List<T>> list = new ArrayList<>(rows); List<List<T>> list = new ArrayList<>(rows);
while (list.size() < rows) { while (list.size() < rows) {
@@ -31,4 +36,25 @@ public class ListUtils {
return list; return list;
} }
/**
* Convert a list potentially containing duplicates to a map where the value is the frequency of the key.
*
* @param list The list.
* @param <T> The type parameter of the list.
* @return The frequency map.
*/
@NotNull
public static <T> Map<T, Integer> listToFrequencyMap(@NotNull final List<T> list) {
Map<T, Integer> frequencyMap = new HashMap<>();
for (T object : list) {
if (frequencyMap.containsKey(object)) {
frequencyMap.put(object, frequencyMap.get(object) + 1);
} else {
frequencyMap.put(object, 1);
}
}
return frequencyMap;
}
} }

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.util;
import com.willfp.eco.core.tuples.Pair; import com.willfp.eco.core.tuples.Pair;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
/** /**
* Utilities / API methods for menus. * Utilities / API methods for menus.
@@ -14,6 +15,7 @@ public class MenuUtils {
* @param slot The slot. * @param slot The slot.
* @return The pair of row and columns. * @return The pair of row and columns.
*/ */
@NotNull
public Pair<Integer, Integer> convertSlotToRowColumn(final int slot) { public Pair<Integer, Integer> convertSlotToRowColumn(final int slot) {
int row = Math.floorDiv(slot, 9); int row = Math.floorDiv(slot, 9);
int column = slot - row * 9; int column = slot - row * 9;

View File

@@ -17,6 +17,7 @@ public class NamespacedKeyUtils {
* @param string The string. * @param string The string.
* @return The key. * @return The key.
*/ */
@NotNull
public NamespacedKey createEcoKey(@NotNull final String string) { public NamespacedKey createEcoKey(@NotNull final String string) {
return Objects.requireNonNull(NamespacedKey.fromString("eco:" + string)); return Objects.requireNonNull(NamespacedKey.fromString("eco:" + string));
} }
@@ -28,6 +29,7 @@ public class NamespacedKeyUtils {
* @param key The key. * @param key The key.
* @return The key. * @return The key.
*/ */
@NotNull
public NamespacedKey create(@NotNull final String namespace, public NamespacedKey create(@NotNull final String namespace,
@NotNull final String key) { @NotNull final String key) {
return Objects.requireNonNull(NamespacedKey.fromString(namespace + ":" + key)); return Objects.requireNonNull(NamespacedKey.fromString(namespace + ":" + key));

View File

@@ -109,6 +109,7 @@ public class NumberUtils {
* @param number The number to convert. * @param number The number to convert.
* @return The number, converted to a roman numeral. * @return The number, converted to a roman numeral.
*/ */
@NotNull
public String toNumeral(final int number) { public String toNumeral(final int number) {
if (number >= 1 && number <= 4096) { if (number >= 1 && number <= 4096) {
int l = NUMERALS.floorKey(number); int l = NUMERALS.floorKey(number);
@@ -199,6 +200,7 @@ public class NumberUtils {
* @param toFormat The number to format. * @param toFormat The number to format.
* @return Formatted. * @return Formatted.
*/ */
@NotNull
public String format(final double toFormat) { public String format(final double toFormat) {
DecimalFormat df = new DecimalFormat("0.00"); DecimalFormat df = new DecimalFormat("0.00");
String formatted = df.format(toFormat); String formatted = df.format(toFormat);

View File

@@ -0,0 +1,105 @@
package com.willfp.eco.util;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.Prerequisite;
import com.willfp.eco.core.data.PlayerProfile;
import com.willfp.eco.core.data.keys.PersistentDataKey;
import com.willfp.eco.core.data.keys.PersistentDataKeyType;
import lombok.experimental.UtilityClass;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Utilities / API methods for players.
*/
@UtilityClass
public class PlayerUtils {
/**
* The data key for saved player names.
*/
private static final PersistentDataKey<String> PLAYER_NAME_KEY = new PersistentDataKey<>(
NamespacedKeyUtils.createEcoKey("player_name"),
PersistentDataKeyType.STRING,
"Unknown Player"
);
/**
* Get the audience from a player.
*
* @param player The player.
* @return The audience.
*/
@NotNull
public Audience getAudience(@NotNull final Player player) {
BukkitAudiences adventure = Eco.getHandler().getAdventure();
if (Prerequisite.HAS_PAPER.isMet()) {
if (player instanceof Audience) {
return (Audience) player;
} else {
return Audience.empty();
}
} else {
if (adventure == null) {
return Audience.empty();
} else {
return adventure.player(player);
}
}
}
/**
* Get the audience from a command sender.
*
* @param sender The command sender.
* @return The audience.
*/
@NotNull
public Audience getAudience(@NotNull final CommandSender sender) {
BukkitAudiences adventure = Eco.getHandler().getAdventure();
if (Prerequisite.HAS_PAPER.isMet()) {
if (sender instanceof Audience) {
return (Audience) sender;
} else {
return Audience.empty();
}
} else {
if (adventure == null) {
return Audience.empty();
} else {
return adventure.sender(sender);
}
}
}
/**
* Get saved display name for an offline player.
*
* @param player The player.
* @return The player name.
*/
public String getSavedDisplayName(@NotNull final OfflinePlayer player) {
PlayerProfile profile = PlayerProfile.load(player);
if (player instanceof Player onlinePlayer) {
profile.write(PLAYER_NAME_KEY, onlinePlayer.getDisplayName());
}
return profile.read(PLAYER_NAME_KEY);
}
/**
* Update the saved display name for a player.
*
* @param player The player.
*/
public void updateSavedDisplayName(@NotNull final Player player) {
PlayerProfile profile = PlayerProfile.load(player);
profile.write(PLAYER_NAME_KEY, player.getDisplayName());
}
}

View File

@@ -0,0 +1,47 @@
package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import org.bukkit.potion.PotionData;
import org.jetbrains.annotations.NotNull;
/**
* Utilities / API methods for potions.
*/
@UtilityClass
public class PotionUtils {
/**
* Get the duration (in ticks) for potion data.
*
* @param data The data.
* @return The duration.
*/
public int getDuration(@NotNull final PotionData data) {
if (data.isExtended()) {
return switch (data.getType()) {
case INSTANT_DAMAGE, INSTANT_HEAL: yield 0;
case POISON, REGEN: yield 1800;
case SLOW_FALLING, WEAKNESS, SLOWNESS: yield 4800;
case TURTLE_MASTER: yield 800;
default: yield 9600;
};
}
if (data.isUpgraded()) {
return switch (data.getType()) {
case INSTANT_DAMAGE, INSTANT_HEAL: yield 0;
case POISON, REGEN: yield 420;
case SLOW_FALLING, WEAKNESS, SLOWNESS: yield 440;
case TURTLE_MASTER: yield 400;
default: yield 1800;
};
}
return switch (data.getType()) {
case INSTANT_DAMAGE, INSTANT_HEAL: yield 0;
case POISON, REGEN: yield 900;
case SLOW_FALLING, WEAKNESS, SLOWNESS: yield 400;
case TURTLE_MASTER: yield 1800;
default: yield 3600;
};
}
}

View File

@@ -0,0 +1,48 @@
package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
/**
* Utilities / API methods for the server.
*/
@UtilityClass
public class ServerUtils {
/**
* The TPS supplier.
*/
private Supplier<Double> tpsSupplier = null;
/**
* Get the current server TPS.
*
* @return The TPS.
*/
public double getTps() {
Validate.notNull(tpsSupplier, "Not initialized!");
double tps = tpsSupplier.get();
if (tps > 20) {
return 20;
} else {
return tps;
}
}
/**
* Initialize the tps supplier function.
*
* @param function The function.
*/
@ApiStatus.Internal
public void initialize(@NotNull final Supplier<Double> function) {
Validate.isTrue(tpsSupplier == null, "Already initialized!");
tpsSupplier = function;
}
}

View File

@@ -5,8 +5,10 @@ import org.apache.commons.lang.Validate;
import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Function;
/** /**
* Utilities / API methods for player heads. * Utilities / API methods for player heads.
@@ -23,6 +25,11 @@ public class SkullUtils {
*/ */
private BiConsumer<SkullMeta, String> metaSetConsumer = null; private BiConsumer<SkullMeta, String> metaSetConsumer = null;
/**
* The meta get function.
*/
private Function<SkullMeta, String> metaGetConsumer = null;
/** /**
* Set the texture of a skull from base64. * Set the texture of a skull from base64.
* *
@@ -37,16 +44,33 @@ public class SkullUtils {
metaSetConsumer.accept(meta, base64); metaSetConsumer.accept(meta, base64);
} }
/**
* Get the texture of a skull - in base64.
*
* @param meta The meta to modify.
* @return The texture, potentially null.
*/
@Nullable
public String getSkullTexture(@NotNull final SkullMeta meta) {
Validate.isTrue(initialized, "Must be initialized!");
Validate.notNull(metaGetConsumer, "Must be initialized!");
return metaGetConsumer.apply(meta);
}
/** /**
* Initialize the skull texture function. * Initialize the skull texture function.
* *
* @param function The function. * @param function The function.
* @param function2 Get function.
*/ */
@ApiStatus.Internal @ApiStatus.Internal
public void initialize(@NotNull final BiConsumer<SkullMeta, String> function) { public void initialize(@NotNull final BiConsumer<SkullMeta, String> function,
@NotNull final Function<SkullMeta, String> function2) {
Validate.isTrue(!initialized, "Already initialized!"); Validate.isTrue(!initialized, "Already initialized!");
metaSetConsumer = function; metaSetConsumer = function;
metaGetConsumer = function2;
initialized = true; initialized = true;
} }
} }

View File

@@ -1,10 +1,14 @@
package com.willfp.eco.util; package com.willfp.eco.util;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.willfp.eco.core.Prerequisite;
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager; import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.markdown.DiscordFlavor;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
@@ -16,11 +20,17 @@ import java.awt.Color;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static net.md_5.bungee.api.ChatColor.BOLD;
import static net.md_5.bungee.api.ChatColor.COLOR_CHAR; import static net.md_5.bungee.api.ChatColor.COLOR_CHAR;
import static net.md_5.bungee.api.ChatColor.ITALIC;
import static net.md_5.bungee.api.ChatColor.MAGIC;
import static net.md_5.bungee.api.ChatColor.STRIKETHROUGH;
import static net.md_5.bungee.api.ChatColor.UNDERLINE;
/** /**
* Utilities / API methods for strings. * Utilities / API methods for strings.
@@ -34,6 +44,8 @@ public class StringUtils {
.add(Pattern.compile("<GRADIENT:([0-9A-Fa-f]{6})>(.*?)</GRADIENT:([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE)) .add(Pattern.compile("<GRADIENT:([0-9A-Fa-f]{6})>(.*?)</GRADIENT:([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE))
.add(Pattern.compile("<GRADIENT:#([0-9A-Fa-f]{6})>(.*?)</GRADIENT:#([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE)) .add(Pattern.compile("<GRADIENT:#([0-9A-Fa-f]{6})>(.*?)</GRADIENT:#([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE))
.add(Pattern.compile("<G:([0-9A-Fa-f]{6})>(.*?)</G:([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE)) .add(Pattern.compile("<G:([0-9A-Fa-f]{6})>(.*?)</G:([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE))
.add(Pattern.compile("<G:#([0-9A-Fa-f]{6})>(.*?)</G:#([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE))
.add(Pattern.compile("<G#([0-9A-Fa-f]{6})>(.*?)</G#([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE))
.add(Pattern.compile("<#:([0-9A-Fa-f]{6})>(.*?)</#:([0-9A-Fa-f]{6})>")) .add(Pattern.compile("<#:([0-9A-Fa-f]{6})>(.*?)</#:([0-9A-Fa-f]{6})>"))
.add(Pattern.compile("\\{#:([0-9A-Fa-f]{6})}(.*?)\\{/#:([0-9A-Fa-f]{6})}")) .add(Pattern.compile("\\{#:([0-9A-Fa-f]{6})}(.*?)\\{/#:([0-9A-Fa-f]{6})}"))
.build(); .build();
@@ -56,6 +68,22 @@ public class StringUtils {
.hexColors() .hexColors()
.build(); .build();
/**
* Color map.
*/
private static final Map<String, ChatColor> COLOR_MAP = new ImmutableMap.Builder<String, ChatColor>()
.put("&l", BOLD)
.put("&o", ITALIC)
.put("&n", UNDERLINE)
.put("&m", STRIKETHROUGH)
.put("&k", MAGIC)
.put("§l", BOLD)
.put("§o", ITALIC)
.put("§n", UNDERLINE)
.put("§m", STRIKETHROUGH)
.put("§k", MAGIC)
.build();
/** /**
* Format a list of strings. * Format a list of strings.
* <p> * <p>
@@ -64,6 +92,7 @@ public class StringUtils {
* @param list The messages to format. * @param list The messages to format.
* @return The message, formatted. * @return The message, formatted.
*/ */
@NotNull
public List<String> formatList(@NotNull final List<String> list) { public List<String> formatList(@NotNull final List<String> list) {
return formatList(list, (Player) null); return formatList(list, (Player) null);
} }
@@ -77,6 +106,7 @@ public class StringUtils {
* @param player The player to translate placeholders with respect to. * @param player The player to translate placeholders with respect to.
* @return The message, format. * @return The message, format.
*/ */
@NotNull
public List<String> formatList(@NotNull final List<String> list, public List<String> formatList(@NotNull final List<String> list,
@Nullable final Player player) { @Nullable final Player player) {
return formatList(list, player, FormatOption.WITH_PLACEHOLDERS); return formatList(list, player, FormatOption.WITH_PLACEHOLDERS);
@@ -91,6 +121,7 @@ public class StringUtils {
* @param option The format option. * @param option The format option.
* @return The message, formatted. * @return The message, formatted.
*/ */
@NotNull
public List<String> formatList(@NotNull final List<String> list, public List<String> formatList(@NotNull final List<String> list,
@NotNull final FormatOption option) { @NotNull final FormatOption option) {
return formatList(list, null, option); return formatList(list, null, option);
@@ -106,6 +137,7 @@ public class StringUtils {
* @param option The options. * @param option The options.
* @return The message, format. * @return The message, format.
*/ */
@NotNull
public List<String> formatList(@NotNull final List<String> list, public List<String> formatList(@NotNull final List<String> list,
@Nullable final Player player, @Nullable final Player player,
@NotNull final FormatOption option) { @NotNull final FormatOption option) {
@@ -126,6 +158,7 @@ public class StringUtils {
* @return The message, formatted. * @return The message, formatted.
* @see StringUtils#format(String, Player) * @see StringUtils#format(String, Player)
*/ */
@NotNull
public String format(@NotNull final String message) { public String format(@NotNull final String message) {
return format(message, (Player) null); return format(message, (Player) null);
} }
@@ -139,6 +172,7 @@ public class StringUtils {
* @param player The player to translate placeholders with respect to. * @param player The player to translate placeholders with respect to.
* @return The message, formatted. * @return The message, formatted.
*/ */
@NotNull
public String format(@NotNull final String message, public String format(@NotNull final String message,
@Nullable final Player player) { @Nullable final Player player) {
return format(message, player, FormatOption.WITH_PLACEHOLDERS); return format(message, player, FormatOption.WITH_PLACEHOLDERS);
@@ -154,11 +188,74 @@ public class StringUtils {
* @return The message, formatted. * @return The message, formatted.
* @see StringUtils#format(String, Player) * @see StringUtils#format(String, Player)
*/ */
@NotNull
public String format(@NotNull final String message, public String format(@NotNull final String message,
@NotNull final FormatOption option) { @NotNull final FormatOption option) {
return format(message, null, option); return format(message, null, option);
} }
/**
* Format a string to a component.
* <p>
* Converts color codes and placeholders.
*
* @param message The message to translate.
* @return The message, formatted, as a component.
* @see StringUtils#format(String, Player)
*/
@NotNull
public Component formatToComponent(@NotNull final String message) {
return formatToComponent(message, (Player) null);
}
/**
* Format a string.
* <p>
* Converts color codes and placeholders for a player.
*
* @param message The message to format.
* @param player The player to translate placeholders with respect to.
* @return The message, formatted.
*/
@NotNull
public Component formatToComponent(@NotNull final String message,
@Nullable final Player player) {
return formatToComponent(message, player, FormatOption.WITH_PLACEHOLDERS);
}
/**
* Format a string to a component.
* <p>
* Converts color codes and placeholders if specified.
*
* @param message The message to translate.
* @param option The format option.
* @return The message, formatted, as a component.
* @see StringUtils#format(String, Player)
*/
@NotNull
public Component formatToComponent(@NotNull final String message,
@NotNull final FormatOption option) {
return formatToComponent(message, null, option);
}
/**
* Format a string to a component.
* <p>
* Coverts color codes and placeholders for a player if specified.
*
* @param message The message to format.
* @param player The player to translate placeholders with respect to.
* @param option The format options.
* @return The message, formatted, as a component.
*/
@NotNull
public Component formatToComponent(@NotNull final String message,
@Nullable final Player player,
@NotNull final FormatOption option) {
return toComponent(format(message, player, option));
}
/** /**
* Format a string. * Format a string.
* <p> * <p>
@@ -169,19 +266,27 @@ public class StringUtils {
* @param option The format options. * @param option The format options.
* @return The message, formatted. * @return The message, formatted.
*/ */
@NotNull
public String format(@NotNull final String message, public String format(@NotNull final String message,
@Nullable final Player player, @Nullable final Player player,
@NotNull final FormatOption option) { @NotNull final FormatOption option) {
String processedMessage = message; String processedMessage = message;
processedMessage = translateGradients(processedMessage);
if (option == FormatOption.WITH_PLACEHOLDERS) { if (option == FormatOption.WITH_PLACEHOLDERS) {
processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, player); processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, player);
} }
processedMessage = translateHexColorCodes(processedMessage);
processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage); processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage);
processedMessage = translateGradients(processedMessage);
processedMessage = translateHexColorCodes(processedMessage);
if (Prerequisite.HAS_PAPER.isMet()) {
processedMessage = translateMiniMessage(processedMessage);
}
return processedMessage; return processedMessage;
} }
private static String translateMiniMessage(@NotNull final String message) {
return LEGACY_COMPONENT_SERIALIZER.serialize(MiniMessage.withMarkdownFlavor(DiscordFlavor.get()).parse(message));
}
private static String translateHexColorCodes(@NotNull final String message) { private static String translateHexColorCodes(@NotNull final String message) {
String processedMessage = message; String processedMessage = message;
for (Pattern pattern : HEX_PATTERNS) { for (Pattern pattern : HEX_PATTERNS) {
@@ -211,26 +316,12 @@ public class StringUtils {
@NotNull final Color end) { @NotNull final Color end) {
String processedString = string; String processedString = string;
List<ChatColor> modifiers = new ArrayList<>(); List<ChatColor> modifiers = new ArrayList<>();
if (processedString.contains("&l")) { for (Map.Entry<String, ChatColor> entry : COLOR_MAP.entrySet()) {
modifiers.add(ChatColor.BOLD); if (processedString.contains(entry.getKey())) {
modifiers.add(entry.getValue());
} }
if (processedString.contains("&o")) { processedString = processedString.replace(entry.getKey(), "");
modifiers.add(ChatColor.ITALIC);
} }
if (processedString.contains("&n")) {
modifiers.add(ChatColor.UNDERLINE);
}
if (processedString.contains("&m")) {
modifiers.add(ChatColor.STRIKETHROUGH);
}
if (processedString.contains("&k")) {
modifiers.add(ChatColor.MAGIC);
}
processedString = processedString.replace("&l", "");
processedString = processedString.replace("&o", "");
processedString = processedString.replace("&n", "");
processedString = processedString.replace("&k", "");
processedString = processedString.replace("&m", "");
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
ChatColor[] colors = getGradientColors(start, end, processedString.length()); ChatColor[] colors = getGradientColors(start, end, processedString.length());
@@ -247,6 +338,9 @@ public class StringUtils {
@NotNull final Color end, @NotNull final Color end,
final int step) { final int step) {
ChatColor[] colors = new ChatColor[step]; ChatColor[] colors = new ChatColor[step];
if (step <= 1) {
return colors;
}
int stepR = Math.abs(start.getRed() - end.getRed()) / (step - 1); int stepR = Math.abs(start.getRed() - end.getRed()) / (step - 1);
int stepG = Math.abs(start.getGreen() - end.getGreen()) / (step - 1); int stepG = Math.abs(start.getGreen() - end.getGreen()) / (step - 1);
int stepB = Math.abs(start.getBlue() - end.getBlue()) / (step - 1); int stepB = Math.abs(start.getBlue() - end.getBlue()) / (step - 1);
@@ -284,6 +378,7 @@ public class StringUtils {
* @param object The object to convert to string. * @param object The object to convert to string.
* @return The object stringified. * @return The object stringified.
*/ */
@NotNull
public String internalToString(@Nullable final Object object) { public String internalToString(@Nullable final Object object) {
if (object == null) { if (object == null) {
return "null"; return "null";
@@ -309,6 +404,7 @@ public class StringUtils {
* @param prefix The substring to remove. * @param prefix The substring to remove.
* @return The string with the prefix removed. * @return The string with the prefix removed.
*/ */
@NotNull
public String removePrefix(@NotNull final String string, public String removePrefix(@NotNull final String string,
@NotNull final String prefix) { @NotNull final String prefix) {
if (string.startsWith(prefix)) { if (string.startsWith(prefix)) {
@@ -323,10 +419,15 @@ public class StringUtils {
* @param legacy The legacy string. * @param legacy The legacy string.
* @return The JSON String. * @return The JSON String.
*/ */
public String legacyToJson(@NotNull final String legacy) { @NotNull
public String legacyToJson(@Nullable final String legacy) {
String processed = legacy;
if (legacy == null) {
processed = "";
}
return GsonComponentSerializer.gson().serialize( return GsonComponentSerializer.gson().serialize(
Component.empty().decoration(TextDecoration.ITALIC, false).append( Component.empty().decoration(TextDecoration.ITALIC, false).append(
LEGACY_COMPONENT_SERIALIZER.deserialize(legacy) LEGACY_COMPONENT_SERIALIZER.deserialize(processed)
) )
); );
} }
@@ -337,12 +438,40 @@ public class StringUtils {
* @param json The JSON string. * @param json The JSON string.
* @return The legacy string. * @return The legacy string.
*/ */
@NotNull
public String jsonToLegacy(@NotNull final String json) { public String jsonToLegacy(@NotNull final String json) {
return LEGACY_COMPONENT_SERIALIZER.serialize( return LEGACY_COMPONENT_SERIALIZER.serialize(
GsonComponentSerializer.gson().deserialize(json) GsonComponentSerializer.gson().deserialize(json)
); );
} }
/**
* Convert legacy (bukkit) text to Component.
*
* @param legacy The legacy text.
* @return The component.
*/
@NotNull
public Component toComponent(@Nullable final String legacy) {
String processed = legacy;
if (legacy == null) {
processed = "";
}
return LEGACY_COMPONENT_SERIALIZER.deserialize(processed);
}
/**
* Convert Component to legacy (bukkit) text.
*
* @param component The component.
* @return The legacy text.
*/
@NotNull
public String toLegacy(@NotNull final Component component) {
return LEGACY_COMPONENT_SERIALIZER.serialize(component);
}
/** /**
* Options for formatting. * Options for formatting.
*/ */

View File

@@ -43,6 +43,7 @@ public class TeamUtils {
* @param color The color to find the team for. * @param color The color to find the team for.
* @return The team. * @return The team.
*/ */
@NotNull
public Team fromChatColor(@NotNull final ChatColor color) { public Team fromChatColor(@NotNull final ChatColor color) {
if (CHAT_COLOR_TEAMS.containsKey(color)) { if (CHAT_COLOR_TEAMS.containsKey(color)) {
return CHAT_COLOR_TEAMS.get(color); return CHAT_COLOR_TEAMS.get(color);
@@ -70,6 +71,7 @@ public class TeamUtils {
* @param material The material to find the team from. * @param material The material to find the team from.
* @return The team. * @return The team.
*/ */
@NotNull
public Team getMaterialColorTeam(@NotNull final Material material) { public Team getMaterialColorTeam(@NotNull final Material material) {
return fromChatColor(MATERIAL_COLORS.getOrDefault(material, ChatColor.WHITE)); return fromChatColor(MATERIAL_COLORS.getOrDefault(material, ChatColor.WHITE));
} }

View File

@@ -44,6 +44,7 @@ public class VectorUtils {
* @param vec The vector to simplify. * @param vec The vector to simplify.
* @return The vector, simplified. * @return The vector, simplified.
*/ */
@NotNull
public Vector simplifyVector(@NotNull final Vector vec) { public Vector simplifyVector(@NotNull final Vector vec) {
double x = Math.abs(vec.getX()); double x = Math.abs(vec.getX());
double y = Math.abs(vec.getY()); double y = Math.abs(vec.getY());
@@ -76,6 +77,7 @@ public class VectorUtils {
* @param radius The radius. * @param radius The radius.
* @return An array of {@link Vector}s. * @return An array of {@link Vector}s.
*/ */
@NotNull
public Vector[] getCircle(final int radius) { public Vector[] getCircle(final int radius) {
Vector[] cached = CIRCLE_CACHE.get(radius); Vector[] cached = CIRCLE_CACHE.get(radius);
if (cached != null) { if (cached != null) {
@@ -112,6 +114,7 @@ public class VectorUtils {
* @param radius The radius of the square. * @param radius The radius of the square.
* @return An array of {@link Vector}s. * @return An array of {@link Vector}s.
*/ */
@NotNull
public Vector[] getSquare(final int radius) { public Vector[] getSquare(final int radius) {
List<Vector> vectors = new ArrayList<>(); List<Vector> vectors = new ArrayList<>();
@@ -136,6 +139,7 @@ public class VectorUtils {
* @param radius The radius of the cube. * @param radius The radius of the cube.
* @return An array of {@link Vector}s. * @return An array of {@link Vector}s.
*/ */
@NotNull
public Vector[] getCube(final int radius) { public Vector[] getCube(final int radius) {
List<Vector> vectors = new ArrayList<>(); List<Vector> vectors = new ArrayList<>();

View File

@@ -4,7 +4,7 @@ buildscript {
} }
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"
} }
} }
@@ -16,6 +16,14 @@ subprojects {
dependencies { dependencies {
compileOnly project(":eco-api") compileOnly project(":eco-api")
compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.5.21' compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.5.31'
}
compileKotlin {
kotlinOptions {
jvmTarget = "16"
}
targetCompatibility = JavaVersion.VERSION_16
sourceCompatibility = JavaVersion.VERSION_16
} }
} }

View File

@@ -2,7 +2,10 @@ group 'com.willfp'
version rootProject.version version rootProject.version
dependencies { dependencies {
compileOnly 'org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT' compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT'
compileOnly 'me.clip:placeholderapi:2.10.9' compileOnly 'me.clip:placeholderapi:2.10.10'
compileOnly 'org.reflections:reflections:0.9.12' compileOnly 'org.reflections:reflections:0.9.12'
compileOnly 'net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT'
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
compileOnly 'com.google.guava:guava:31.0.1-jre'
} }

View File

@@ -1,11 +1,12 @@
package com.willfp.eco.internal.config package com.willfp.eco.internal.config
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.PluginLike
import com.willfp.eco.core.config.interfaces.Config import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.core.config.interfaces.JSONConfig import com.willfp.eco.core.config.interfaces.JSONConfig
import com.willfp.eco.core.config.wrapper.ConfigFactory import com.willfp.eco.core.config.wrapper.ConfigFactory
import com.willfp.eco.internal.config.json.EcoJSONConfigSection import com.willfp.eco.internal.config.json.EcoJSONConfigSection
import com.willfp.eco.internal.config.json.EcoLoadableJSONConfig import com.willfp.eco.internal.config.json.EcoLoadableJSONConfig
import com.willfp.eco.internal.config.json.EcoUpdatableJSONConfig
import com.willfp.eco.internal.config.yaml.EcoLoadableYamlConfig import com.willfp.eco.internal.config.yaml.EcoLoadableYamlConfig
import com.willfp.eco.internal.config.yaml.EcoUpdatableYamlConfig import com.willfp.eco.internal.config.yaml.EcoUpdatableYamlConfig
import com.willfp.eco.internal.config.yaml.EcoYamlConfigSection import com.willfp.eco.internal.config.yaml.EcoYamlConfigSection
@@ -14,7 +15,7 @@ import org.bukkit.configuration.file.YamlConfiguration
class EcoConfigFactory : ConfigFactory { class EcoConfigFactory : ConfigFactory {
override fun createUpdatableYamlConfig( override fun createUpdatableYamlConfig(
configName: String, configName: String,
plugin: EcoPlugin, plugin: PluginLike,
subDirectoryPath: String, subDirectoryPath: String,
source: Class<*>, source: Class<*>,
removeUnused: Boolean, removeUnused: Boolean,
@@ -30,9 +31,27 @@ class EcoConfigFactory : ConfigFactory {
) )
} }
override fun createUpdatableJSONConfig(
configName: String,
plugin: PluginLike,
subDirectoryPath: String,
source: Class<*>,
removeUnused: Boolean,
vararg updateBlacklist: String
): JSONConfig {
return EcoUpdatableJSONConfig(
configName,
plugin,
subDirectoryPath,
source,
removeUnused,
*updateBlacklist
)
}
override fun createLoadableJSONConfig( override fun createLoadableJSONConfig(
configName: String, configName: String,
plugin: EcoPlugin, plugin: PluginLike,
subDirectoryPath: String, subDirectoryPath: String,
source: Class<*> source: Class<*>
): JSONConfig { ): JSONConfig {
@@ -46,7 +65,7 @@ class EcoConfigFactory : ConfigFactory {
override fun createLoadableYamlConfig( override fun createLoadableYamlConfig(
configName: String, configName: String,
plugin: EcoPlugin, plugin: PluginLike,
subDirectoryPath: String, subDirectoryPath: String,
source: Class<*> source: Class<*>
): Config { ): Config {

View File

@@ -4,16 +4,16 @@ import com.google.gson.Gson
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.willfp.eco.core.config.interfaces.JSONConfig import com.willfp.eco.core.config.interfaces.JSONConfig
import com.willfp.eco.util.StringUtils import com.willfp.eco.util.StringUtils
import org.apache.commons.lang.Validate
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
open class EcoJSONConfigWrapper : JSONConfig { open class EcoJSONConfigWrapper : JSONConfig {
val handle: Gson = GsonBuilder().setPrettyPrinting().create() val handle: Gson = GsonBuilder().setPrettyPrinting().create()
val values = mutableMapOf<String, Any?>() val values = ConcurrentHashMap<String, Any?>()
private val cache = mutableMapOf<String, Any>() private val cache = ConcurrentHashMap<String, Any>()
fun init(values: Map<String, Any?>) { fun init(values: Map<String, Any?>) {
this.values.clear() this.values.clear()
@@ -123,8 +123,7 @@ open class EcoJSONConfigWrapper : JSONConfig {
override fun getSubsection(path: String): JSONConfig { override fun getSubsection(path: String): JSONConfig {
val subsection = getSubsectionOrNull(path) val subsection = getSubsectionOrNull(path)
Validate.notNull(subsection) return subsection ?: EcoJSONConfigSection(emptyMap())
return subsection!!
} }
override fun getSubsectionOrNull(path: String): JSONConfig? { override fun getSubsectionOrNull(path: String): JSONConfig? {

View File

@@ -1,18 +1,22 @@
package com.willfp.eco.internal.config.json package com.willfp.eco.internal.config.json
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.PluginLike
import com.willfp.eco.core.config.interfaces.LoadableConfig import com.willfp.eco.core.config.interfaces.LoadableConfig
import org.jetbrains.annotations.NotNull import java.io.File
import java.io.* import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.FileReader
import java.io.IOException
import java.io.OutputStream
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.StandardOpenOption import java.nio.file.StandardOpenOption
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
class EcoLoadableJSONConfig( open class EcoLoadableJSONConfig(
configName: String, configName: String,
private val plugin: EcoPlugin, private val plugin: PluginLike,
private val subDirectoryPath: String, private val subDirectoryPath: String,
private val source: Class<*> val source: Class<*>
) : EcoJSONConfigWrapper(), LoadableConfig { ) : EcoJSONConfigWrapper(), LoadableConfig {
private val configFile: File private val configFile: File
@@ -65,7 +69,7 @@ class EcoLoadableJSONConfig(
@Throws(FileNotFoundException::class) @Throws(FileNotFoundException::class)
fun init(file: File) { fun init(file: File) {
super.init(handle.fromJson(FileReader(file), Map::class.java) as @NotNull MutableMap<String, Any>) super.init(handle.fromJson(FileReader(file), Map::class.java) as MutableMap<String, Any>)
} }
override fun getName(): String { override fun getName(): String {
@@ -77,7 +81,7 @@ class EcoLoadableJSONConfig(
} }
init { init {
val directory: File = File(this.plugin.dataFolder, subDirectoryPath) val directory = File(this.plugin.dataFolder, subDirectoryPath)
if (!directory.exists()) { if (!directory.exists()) {
directory.mkdirs() directory.mkdirs()
} }

View File

@@ -0,0 +1,74 @@
package com.willfp.eco.internal.config.json
import com.willfp.eco.core.PluginLike
import org.bukkit.configuration.InvalidConfigurationException
import org.bukkit.configuration.file.YamlConfiguration
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.nio.charset.StandardCharsets
open class EcoUpdatableJSONConfig(
configName: String,
plugin: PluginLike,
subDirectoryPath: String,
source: Class<*>,
private val removeUnused: Boolean,
vararg updateBlacklist: String
) : EcoLoadableJSONConfig(configName, plugin, subDirectoryPath, source) {
private val updateBlacklist: MutableList<String> = mutableListOf(*updateBlacklist)
fun update() {
super.clearCache()
try {
this.init(configFile)
val newConfig = configInJar
if (newConfig.getKeys(true) == this.getKeys(true)) {
return
}
newConfig.getKeys(true).forEach { key: String ->
if (!this.getKeys(true).contains(key)) {
if (updateBlacklist.stream().noneMatch { s: String -> key.contains(s) }) {
this.set(key, newConfig[key])
}
}
}
if (removeUnused) {
this.getKeys(true).forEach { s ->
if (!newConfig.getKeys(true).contains(s)) {
if (updateBlacklist.stream().noneMatch(s::contains)) {
this.set(s, null)
}
}
}
}
this.save()
} catch (e: IOException) {
e.printStackTrace()
} catch (e: InvalidConfigurationException) {
e.printStackTrace()
}
}
private val configInJar: YamlConfiguration
get() {
val newIn = this.source.getResourceAsStream(resourcePath) ?: throw NullPointerException("$name is null?")
val reader = BufferedReader(InputStreamReader(newIn, StandardCharsets.UTF_8))
val newConfig = YamlConfiguration()
try {
newConfig.load(reader)
} catch (e: IOException) {
e.printStackTrace()
} catch (e: InvalidConfigurationException) {
e.printStackTrace()
}
return newConfig
}
init {
this.updateBlacklist.removeIf { obj: String -> obj.isEmpty() }
plugin.configHandler.addConfig(this)
update()
}
}

View File

@@ -5,12 +5,12 @@ import com.willfp.eco.core.config.interfaces.LoadableConfig
import com.willfp.eco.core.config.updating.ConfigHandler import com.willfp.eco.core.config.updating.ConfigHandler
import com.willfp.eco.core.config.updating.ConfigUpdater import com.willfp.eco.core.config.updating.ConfigUpdater
import com.willfp.eco.internal.config.json.EcoLoadableJSONConfig import com.willfp.eco.internal.config.json.EcoLoadableJSONConfig
import com.willfp.eco.internal.config.json.EcoUpdatableJSONConfig
import com.willfp.eco.internal.config.updating.exceptions.InvalidUpdateMethodException import com.willfp.eco.internal.config.updating.exceptions.InvalidUpdateMethodException
import com.willfp.eco.internal.config.yaml.EcoLoadableYamlConfig import com.willfp.eco.internal.config.yaml.EcoLoadableYamlConfig
import com.willfp.eco.internal.config.yaml.EcoUpdatableYamlConfig import com.willfp.eco.internal.config.yaml.EcoUpdatableYamlConfig
import org.reflections.Reflections import org.reflections.Reflections
import org.reflections.scanners.MethodAnnotationsScanner import org.reflections.scanners.MethodAnnotationsScanner
import java.lang.reflect.Modifier
class EcoConfigHandler( class EcoConfigHandler(
private val plugin: EcoPlugin private val plugin: EcoPlugin
@@ -24,10 +24,6 @@ class EcoConfigHandler(
override fun callUpdate() { override fun callUpdate() {
for (method in reflections.getMethodsAnnotatedWith(ConfigUpdater::class.java)) { for (method in reflections.getMethodsAnnotatedWith(ConfigUpdater::class.java)) {
if (!Modifier.isStatic(method.modifiers)) {
throw InvalidUpdateMethodException("Update method in ${method.declaringClass.name} must be static.")
}
try { try {
when (method.parameterCount) { when (method.parameterCount) {
0 -> method.invoke(null) 0 -> method.invoke(null)
@@ -55,6 +51,7 @@ class EcoConfigHandler(
for (config in configs) { for (config in configs) {
when (config) { when (config) {
is EcoUpdatableYamlConfig -> config.update() is EcoUpdatableYamlConfig -> config.update()
is EcoUpdatableJSONConfig -> config.update()
is EcoLoadableYamlConfig -> config.reloadFromFile() is EcoLoadableYamlConfig -> config.reloadFromFile()
is EcoLoadableJSONConfig -> config.reloadFromFile() is EcoLoadableJSONConfig -> config.reloadFromFile()
} }

View File

@@ -1,6 +1,6 @@
package com.willfp.eco.internal.config.yaml package com.willfp.eco.internal.config.yaml
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.PluginLike
import com.willfp.eco.core.config.interfaces.LoadableConfig import com.willfp.eco.core.config.interfaces.LoadableConfig
import com.willfp.eco.core.config.interfaces.WrappedYamlConfiguration import com.willfp.eco.core.config.interfaces.WrappedYamlConfiguration
import org.bukkit.configuration.InvalidConfigurationException import org.bukkit.configuration.InvalidConfigurationException
@@ -12,7 +12,7 @@ import java.io.OutputStream
open class EcoLoadableYamlConfig( open class EcoLoadableYamlConfig(
configName: String, configName: String,
private val plugin: EcoPlugin, private val plugin: PluginLike,
private val subDirectoryPath: String, private val subDirectoryPath: String,
val source: Class<*> val source: Class<*>
) : EcoYamlConfigWrapper<YamlConfiguration>(), WrappedYamlConfiguration, LoadableConfig { ) : EcoYamlConfigWrapper<YamlConfiguration>(), WrappedYamlConfiguration, LoadableConfig {

View File

@@ -1,6 +1,6 @@
package com.willfp.eco.internal.config.yaml package com.willfp.eco.internal.config.yaml
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.PluginLike
import org.bukkit.configuration.InvalidConfigurationException import org.bukkit.configuration.InvalidConfigurationException
import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.configuration.file.YamlConfiguration
import java.io.BufferedReader import java.io.BufferedReader
@@ -10,7 +10,7 @@ import java.nio.charset.StandardCharsets
class EcoUpdatableYamlConfig( class EcoUpdatableYamlConfig(
configName: String, configName: String,
plugin: EcoPlugin, plugin: PluginLike,
subDirectoryPath: String, subDirectoryPath: String,
source: Class<*>, source: Class<*>,
private val removeUnused: Boolean, private val removeUnused: Boolean,
@@ -27,9 +27,9 @@ class EcoUpdatableYamlConfig(
if (newConfig.getKeys(true) == this.handle.getKeys(true)) { if (newConfig.getKeys(true) == this.handle.getKeys(true)) {
return return
} }
newConfig.getKeys(true).forEach { key: String -> newConfig.getKeys(true).forEach { key ->
if (!this.handle.getKeys(true).contains(key)) { if (!this.handle.getKeys(true).contains(key)) {
if (updateBlacklist.stream().noneMatch { s: String -> key.contains(s) }) { if (updateBlacklist.stream().noneMatch { key.contains(it) }) {
this.handle.set(key, newConfig[key]) this.handle.set(key, newConfig[key])
} }
} }
@@ -67,7 +67,7 @@ class EcoUpdatableYamlConfig(
} }
init { init {
this.updateBlacklist.removeIf { obj: String -> obj.isEmpty() } this.updateBlacklist.removeIf { it.isEmpty() }
plugin.configHandler.addConfig(this) plugin.configHandler.addConfig(this)
update() update()
} }

View File

@@ -2,15 +2,15 @@ package com.willfp.eco.internal.config.yaml
import com.willfp.eco.core.config.interfaces.Config import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.util.StringUtils import com.willfp.eco.util.StringUtils
import org.apache.commons.lang.Validate
import org.bukkit.configuration.ConfigurationSection import org.bukkit.configuration.ConfigurationSection
import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.configuration.file.YamlConfiguration
import java.io.StringReader import java.io.StringReader
import java.util.concurrent.ConcurrentHashMap
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config { open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
lateinit var handle: T lateinit var handle: T
private val cache = mutableMapOf<String, Any?>() private val cache = ConcurrentHashMap<String, Any?>()
protected fun init(config: T): Config { protected fun init(config: T): Config {
handle = config handle = config
@@ -51,8 +51,7 @@ open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
override fun getSubsection(path: String): Config { override fun getSubsection(path: String): Config {
val subsection = getSubsectionOrNull(path) val subsection = getSubsectionOrNull(path)
Validate.notNull(subsection) return subsection ?: EcoYamlConfigSection(YamlConfiguration())
return subsection!!
} }
override fun getSubsectionOrNull(path: String): Config? { override fun getSubsectionOrNull(path: String): Config? {

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.internal.data
import com.willfp.eco.core.data.PlayerProfile
import com.willfp.eco.core.data.keys.PersistentDataKey
class EcoPlayerProfile(
val data: MutableMap<PersistentDataKey<*>, Any>
) : PlayerProfile {
override fun <T : Any> write(key: PersistentDataKey<T>, value: T) {
this.data[key] = value
}
override fun <T : Any> read(key: PersistentDataKey<T>): T {
@Suppress("UNCHECKED_CAST")
return this.data[key] as T? ?: key.defaultValue
}
}

View File

@@ -0,0 +1,115 @@
package com.willfp.eco.internal.display
import com.google.common.util.concurrent.ThreadFactoryBuilder
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.display.Display
import com.willfp.eco.core.display.DisplayHandler
import com.willfp.eco.core.display.DisplayModule
import com.willfp.eco.core.display.DisplayPriority
import com.willfp.eco.core.fast.FastItemStack
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.persistence.PersistentDataType
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class EcoDisplayHandler(plugin: EcoPlugin) : DisplayHandler {
private val registeredModules = mutableMapOf<DisplayPriority, MutableList<DisplayModule>>()
private val finalizeKey: NamespacedKey = plugin.namespacedKeyFactory.create("finalized")
init {
for (priority in DisplayPriority.values()) {
registeredModules[priority] = mutableListOf()
}
}
override fun registerDisplayModule(module: DisplayModule) {
val modules = registeredModules[module.priority] ?: return
modules.removeIf { module1: DisplayModule ->
module1.pluginName.equals(module.pluginName, ignoreCase = true)
}
modules.add(module)
registeredModules[module.priority] = modules
}
override fun display(itemStack: ItemStack, player: Player?): ItemStack {
val pluginVarArgs = mutableMapOf<String, Array<Any>>()
for (priority in DisplayPriority.values()) {
val modules = registeredModules[priority] ?: continue
for (module in modules) {
pluginVarArgs[module.pluginName] = module.generateVarArgs(itemStack)
}
}
Display.revert(itemStack)
itemStack.itemMeta ?: return itemStack
for (priority in DisplayPriority.values()) {
val modules = registeredModules[priority] ?: continue
for (module in modules) {
val varargs = pluginVarArgs[module.pluginName] ?: continue
Display.callDisplayModule(module, itemStack, player, *varargs)
}
}
return itemStack
}
override fun revert(itemStack: ItemStack): ItemStack {
if (Display.isFinalized(itemStack)) {
Display.unfinalize(itemStack)
}
val fast = FastItemStack.wrap(itemStack)
val lore = fast.lore
if (lore.isNotEmpty() && lore.removeIf { line: String ->
line.startsWith(
Display.PREFIX
)
}) { // Only modify lore if needed.
fast.lore = lore
}
for (priority in DisplayPriority.values()) {
val modules = registeredModules[priority] ?: continue
for (module in modules) {
module.revert(itemStack)
}
}
return itemStack
}
override fun finalize(itemStack: ItemStack): ItemStack {
if (itemStack.type.maxStackSize > 1) {
return itemStack
}
val meta = itemStack.itemMeta ?: return itemStack
val container = meta.persistentDataContainer
container.set(finalizeKey, PersistentDataType.INTEGER, 1)
itemStack.itemMeta = meta
return itemStack
}
override fun unfinalize(itemStack: ItemStack): ItemStack {
val meta = itemStack.itemMeta ?: return itemStack
val container = meta.persistentDataContainer
container.remove(finalizeKey)
itemStack.itemMeta = meta
return itemStack
}
override fun isFinalized(itemStack: ItemStack): Boolean {
val meta = itemStack.itemMeta ?: return false
val container = meta.persistentDataContainer
return container.has(finalizeKey, PersistentDataType.INTEGER)
}
}

View File

@@ -12,10 +12,9 @@ import org.bukkit.event.player.PlayerExpChangeEvent
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import org.bukkit.util.Vector import org.bukkit.util.Vector
open class EcoDropQueue(player: Player) : InternalDropQueue { open class EcoDropQueue(val player: Player) : InternalDropQueue {
val items = mutableListOf<ItemStack>() val items = mutableListOf<ItemStack>()
var xp: Int = 0 var xp: Int = 0
val player: Player
var loc: Location var loc: Location
var hasTelekinesis = false var hasTelekinesis = false
@@ -79,7 +78,6 @@ open class EcoDropQueue(player: Player) : InternalDropQueue {
} }
init { init {
this.player = player
loc = player.location loc = player.location
} }
} }

View File

@@ -6,7 +6,7 @@ import org.bukkit.Bukkit
import org.bukkit.event.HandlerList import org.bukkit.event.HandlerList
import org.bukkit.event.Listener import org.bukkit.event.Listener
class EcoEventManager constructor(private val plugin: EcoPlugin) : EventManager { class EcoEventManager (private val plugin: EcoPlugin) : EventManager {
override fun registerListener(listener: Listener) { override fun registerListener(listener: Listener) {
Bukkit.getPluginManager().registerEvents(listener, plugin) Bukkit.getPluginManager().registerEvents(listener, plugin)
} }

View File

@@ -22,11 +22,11 @@ class EcoMenu(
): Menu { ): Menu {
override fun getSlot(row: Int, column: Int): Slot { override fun getSlot(row: Int, column: Int): Slot {
if (row < 1 || row > this.rows) { if (row < 1 || row > this.rows) {
throw IllegalArgumentException("Invalid row number!") return slots[0][0]
} }
if (column < 1 || column > 9) { if (column < 1 || column > 9) {
throw IllegalArgumentException("Invalid column number!") return slots[0][0]
} }
return slots[row - 1][column - 1] return slots[row - 1][column - 1]

View File

@@ -18,9 +18,7 @@ class ExtendedInventory(
fun refresh(player: Player) { fun refresh(player: Player) {
captiveItems.clear() captiveItems.clear()
for (i in 0 until inventory.size) { for (i in 0 until inventory.size) {
val pair = MenuUtils.convertSlotToRowColumn(i) val (row, column) = MenuUtils.convertSlotToRowColumn(i)
val row = pair.first!!
val column = pair.second!!
val slot = menu.getSlot(row, column) val slot = menu.getSlot(row, column)
if (slot is EcoCaptivatorSlot) { if (slot is EcoCaptivatorSlot) {
val defaultItem = slot.getItemStack(player) val defaultItem = slot.getItemStack(player)

View File

@@ -2,10 +2,11 @@ package com.willfp.eco.internal.gui.menu
import com.willfp.eco.core.gui.menu.Menu import com.willfp.eco.core.gui.menu.Menu
import org.bukkit.inventory.Inventory import org.bukkit.inventory.Inventory
import java.util.*
object MenuHandler { object MenuHandler {
private val menus = mutableMapOf<ExtendedInventory, EcoMenu>() private val menus = WeakHashMap<ExtendedInventory, EcoMenu>()
private val inventories = mutableMapOf<Inventory, ExtendedInventory>() private val inventories = WeakHashMap<Inventory, ExtendedInventory>()
fun registerMenu( fun registerMenu(
inventory: Inventory, inventory: Inventory,

View File

@@ -15,7 +15,7 @@ class EcoCaptivatorSlot : EcoSlot(
{ _, _, _ -> } { _, _, _ -> }
) { ) {
companion object { companion object {
val plugin = Eco.getHandler().ecoPlugin!! val plugin = Eco.getHandler().ecoPlugin
val allowMovingItem = SlotHandler { event, _, _ -> val allowMovingItem = SlotHandler { event, _, _ ->
event.isCancelled = false event.isCancelled = false

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.internal.requirement
import com.willfp.eco.core.requirement.Requirement
import com.willfp.eco.core.requirement.RequirementFactory
import com.willfp.eco.internal.requirement.requirements.*
class EcoRequirementFactory: RequirementFactory {
override fun create(name: String): Requirement {
return when (name.lowercase()) {
"has-permission" -> RequirementHasPermission()
"placeholder-equals" -> RequirementPlaceholderEquals()
"placeholder-greater-than" -> RequirementPlaceholderGreaterThan()
"placeholder-less-than" -> RequirementPlaceholderLessThan()
else -> RequirementTrue()
}
}
}

View File

@@ -0,0 +1,18 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementHasPermission : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.isEmpty()) {
return false
}
val permission = args[0]
return player.hasPermission(permission)
}
}

View File

@@ -0,0 +1,20 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementPlaceholderEquals : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1]
return PlaceholderManager.translatePlaceholders(placeholder, player).equals(equals, ignoreCase = true)
}
}

View File

@@ -0,0 +1,20 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementPlaceholderGreaterThan : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1].toDoubleOrNull() ?: return false
return PlaceholderManager.translatePlaceholders(placeholder, player).toDoubleOrNull() ?: 0.0 >= equals
}
}

View File

@@ -0,0 +1,20 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementPlaceholderLessThan : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1].toDoubleOrNull() ?: return false
return PlaceholderManager.translatePlaceholders(placeholder, player).toDoubleOrNull() ?: 0.0 < equals
}
}

View File

@@ -0,0 +1,13 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementTrue : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
return true
}
}

View File

@@ -3,4 +3,6 @@ version rootProject.version
dependencies { dependencies {
compileOnly 'org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT' compileOnly 'org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT'
compileOnly 'net.kyori:adventure-api:4.9.1'
compileOnly 'net.kyori:adventure-text-serializer-gson:4.8.1'
} }

View File

@@ -1,118 +0,0 @@
package com.willfp.eco.proxy.v1_16_R3;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.willfp.eco.core.display.Display;
import com.willfp.eco.proxy.ChatComponentProxy;
import net.minecraft.server.v1_16_R3.ChatBaseComponent;
import net.minecraft.server.v1_16_R3.ChatHoverable;
import net.minecraft.server.v1_16_R3.ChatMessage;
import net.minecraft.server.v1_16_R3.ChatModifier;
import net.minecraft.server.v1_16_R3.IChatBaseComponent;
import net.minecraft.server.v1_16_R3.MojangsonParser;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public final class ChatComponent implements ChatComponentProxy {
@Override
public Object modifyComponent(@NotNull final Object obj,
@NotNull final Player player) {
if (!(obj instanceof IChatBaseComponent chatComponent)) {
return obj;
}
for (IChatBaseComponent iChatBaseComponent : chatComponent) {
if (iChatBaseComponent == null) {
continue;
}
modifyBaseComponent(iChatBaseComponent, player);
}
return chatComponent;
}
private void modifyBaseComponent(@NotNull final IChatBaseComponent component,
@NotNull final Player player) {
for (IChatBaseComponent sibling : component.getSiblings()) {
if (sibling == null) {
continue;
}
modifyBaseComponent(sibling, player);
}
if (component instanceof ChatMessage) {
Arrays.stream(((ChatMessage) component).getArgs())
.filter(o -> o instanceof IChatBaseComponent)
.map(o -> (IChatBaseComponent) o)
.forEach(o -> this.modifyBaseComponent(o, player));
}
ChatHoverable hoverable = component.getChatModifier().getHoverEvent();
if (hoverable == null) {
return;
}
JsonObject jsonObject = hoverable.b();
JsonElement json = hoverable.b().get("contents");
if (json.getAsJsonObject().get("id") == null) {
return;
}
if (json.getAsJsonObject().get("tag") == null) {
return;
}
String id = json.getAsJsonObject().get("id").toString();
String tag = json.getAsJsonObject().get("tag").toString();
ItemStack itemStack = getFromTag(tag, id);
Display.displayAndFinalize(itemStack, player);
json.getAsJsonObject().remove("tag");
String newTag = toJson(itemStack);
json.getAsJsonObject().add("tag", new JsonPrimitive(newTag));
jsonObject.remove("contents");
jsonObject.add("contents", json);
ChatHoverable newHoverable = ChatHoverable.a(jsonObject);
ChatModifier modifier = component.getChatModifier();
modifier = modifier.setChatHoverable(newHoverable);
((ChatBaseComponent) component).setChatModifier(modifier);
}
private static ItemStack getFromTag(@NotNull final String jsonTag,
@NotNull final String id) {
String processedId = id;
String processedJsonTag = jsonTag;
processedId = processedId.replace("minecraft:", "");
processedId = processedId.toUpperCase();
processedId = processedId.replace("\"", "");
processedJsonTag = processedJsonTag.substring(1, processedJsonTag.length() - 1);
processedJsonTag = processedJsonTag.replace("id:", "\"id\":");
processedJsonTag = processedJsonTag.replace("\\", "");
Material material = Material.getMaterial(processedId);
assert material != null;
ItemStack itemStack = new ItemStack(material);
net.minecraft.server.v1_16_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
try {
nmsStack.setTag(MojangsonParser.parse(processedJsonTag));
} catch (CommandSyntaxException e) {
e.printStackTrace();
}
return CraftItemStack.asBukkitCopy(nmsStack);
}
private static String toJson(@NotNull final ItemStack itemStack) {
return CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString();
}
}

View File

@@ -1,43 +0,0 @@
package com.willfp.eco.proxy.v1_16_R3;
import org.bukkit.craftbukkit.libs.org.apache.commons.lang3.Validate;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
public class FastItemStackUtils {
private static final Field FIELD;
public static net.minecraft.server.v1_16_R3.ItemStack getNMSStack(@NotNull final ItemStack itemStack) {
if (!(itemStack instanceof CraftItemStack)) {
return CraftItemStack.asNMSCopy(itemStack);
} else {
try {
net.minecraft.server.v1_16_R3.ItemStack nms = (net.minecraft.server.v1_16_R3.ItemStack) FIELD.get(itemStack);
return nms == null ? CraftItemStack.asNMSCopy(itemStack) : nms;
} catch (ReflectiveOperationException e) {
e.printStackTrace();
return net.minecraft.server.v1_16_R3.ItemStack.b;
}
}
}
static {
Field temp = null;
try {
Field handleField = CraftItemStack.class.getDeclaredField("handle");
handleField.setAccessible(true);
temp = handleField;
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
assert temp != null;
Validate.notNull(temp, "Error occurred in initialization!");
FIELD = temp;
}
}

View File

@@ -0,0 +1,93 @@
package com.willfp.eco.proxy.v1_16_R3
import com.willfp.eco.core.display.Display
import com.willfp.eco.proxy.ChatComponentProxy
import net.kyori.adventure.nbt.api.BinaryTagHolder
import net.kyori.adventure.text.BuildableComponent
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.TranslatableComponent
import net.kyori.adventure.text.event.HoverEvent
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
import net.minecraft.server.v1_16_R3.IChatBaseComponent
import net.minecraft.server.v1_16_R3.MojangsonParser
import org.bukkit.Material
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack
import org.bukkit.entity.Player
@Suppress("UNCHECKED_CAST")
class ChatComponent : ChatComponentProxy {
private val gsonComponentSerializer = GsonComponentSerializer.gson()
override fun modifyComponent(obj: Any, player: Player): Any {
if (obj !is IChatBaseComponent) {
return obj
}
val component = gsonComponentSerializer.deserialize(
IChatBaseComponent.ChatSerializer.a(
obj
)
).asComponent() as BuildableComponent<*, *>
val newComponent = modifyBaseComponent(component, player)
return IChatBaseComponent.ChatSerializer.a(
gsonComponentSerializer.serialize(newComponent.asComponent())
) ?: obj
}
private fun modifyBaseComponent(baseComponent: Component, player: Player): Component {
var component = baseComponent
if (component is TranslatableComponent) {
val args = mutableListOf<Component>()
for (arg in component.args()) {
args.add(modifyBaseComponent(arg, player))
}
component = component.args(args)
}
val children = mutableListOf<Component>()
for (child in component.children()) {
children.add(modifyBaseComponent(child, player))
}
component = component.children(children)
val hoverEvent: HoverEvent<Any> = component.style().hoverEvent() as HoverEvent<Any>? ?: return component
val showItem = hoverEvent.value()
if (showItem !is HoverEvent.ShowItem) {
return component
}
val newShowItem = showItem.nbt(
BinaryTagHolder.of(
CraftItemStack.asNMSCopy(
Display.display(
CraftItemStack.asBukkitCopy(
CraftItemStack.asNMSCopy(
org.bukkit.inventory.ItemStack(
Material.matchMaterial(
showItem.item()
.toString()
) ?: return component,
showItem.count()
)
).apply {
this.tag = MojangsonParser.parse(
showItem.nbt()?.string() ?: return component
) ?: return component
}
),
player
)
).orCreateTag.toString()
)
)
val newHover = hoverEvent.value(newShowItem)
val style = component.style().hoverEvent(newHover)
return component.style(style)
}
}

View File

@@ -1,19 +1,21 @@
package com.willfp.eco.proxy.v1_16_R3 package com.willfp.eco.proxy.v1_16_R3
import com.mojang.authlib.GameProfile import com.mojang.authlib.GameProfile
import com.mojang.authlib.properties.Property import com.mojang.authlib.properties.Property
import org.bukkit.inventory.meta.SkullMeta
import com.willfp.eco.proxy.SkullProxy import com.willfp.eco.proxy.SkullProxy
import org.bukkit.inventory.meta.SkullMeta
import java.lang.reflect.Field
import java.lang.reflect.Method import java.lang.reflect.Method
import java.util.* import java.util.*
class Skull : SkullProxy { class Skull : SkullProxy {
private lateinit var setProfile: Method private lateinit var setProfile: Method
private lateinit var profile: Field
override fun setSkullTexture( override fun setSkullTexture(
meta: SkullMeta, meta: SkullMeta,
base64: String base64: String
) { ) {
try {
if (!this::setProfile.isInitialized) { if (!this::setProfile.isInitialized) {
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java) setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
setProfile.isAccessible = true setProfile.isAccessible = true
@@ -25,8 +27,18 @@ class Skull : SkullProxy {
val profile = GameProfile(uuid, "eco") val profile = GameProfile(uuid, "eco")
profile.properties.put("textures", Property("textures", base64)) profile.properties.put("textures", Property("textures", base64))
setProfile.invoke(meta, profile) setProfile.invoke(meta, profile)
} catch (e: ReflectiveOperationException) { }
e.printStackTrace()
} override fun getSkullTexture(
meta: SkullMeta
): String? {
if (!this::profile.isInitialized) {
profile = meta.javaClass.getDeclaredField("profile")
profile.isAccessible = true
}
val profile = profile[meta] as GameProfile? ?: return null
val properties = profile.properties ?: return null
val prop = properties["textures"] ?: return null
return prop.toMutableList().firstOrNull()?.name
} }
} }

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