Compare commits

..

201 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
bbbf19c041 Added missing javadoc 2021-09-03 13:03:28 +01:00
157 changed files with 4029 additions and 1099 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/' }
@@ -51,23 +54,20 @@ allprojects {
// CombatLogX // CombatLogX
maven { url 'https://nexus.sirblobman.xyz/repository/public/' } maven { url 'https://nexus.sirblobman.xyz/repository/public/' }
// Head Database
maven { url 'https://mvn.intellectualsites.com/content/groups/public/' }
} }
dependencies { dependencies {
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) {
@@ -87,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)
@@ -357,15 +357,18 @@ public abstract class EcoPlugin extends JavaPlugin {
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();
} }

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,8 +15,11 @@ 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 org.jetbrains.annotations.Nullable;
@@ -22,8 +27,9 @@ 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.
@@ -194,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

@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
* *
* @param <T> The eco plugin type. * @param <T> The eco plugin type.
*/ */
public abstract class PluginDependent<@NotNull T extends EcoPlugin> { public abstract class PluginDependent<T extends EcoPlugin> {
/** /**
* The {@link EcoPlugin} that is stored. * The {@link EcoPlugin} that is stored.
*/ */

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

@@ -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

@@ -8,9 +8,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/** /**
* Class to handle placeholder integrations. * Class to handle placeholder integrations.

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

@@ -2,7 +2,6 @@ package com.willfp.eco.core.items;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import lombok.Getter; import lombok.Getter;
import org.apache.commons.lang.Validate;
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;
@@ -12,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>

View File

@@ -1,11 +1,13 @@
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.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;
@@ -16,12 +18,12 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate; 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.
@@ -31,7 +33,12 @@ public final class Items {
/** /**
* All recipe parts. * All recipe parts.
*/ */
private static final Map<NamespacedKey, CustomItem> REGISTRY = new ConcurrentHashMap<>(); private static final Map<NamespacedKey, TestableItem> REGISTRY = new ConcurrentHashMap<>();
/**
* All item providers.
*/
private static final Map<String, ItemProvider> PROVIDERS = new ConcurrentHashMap<>();
/** /**
* All recipe parts. * All recipe parts.
@@ -42,11 +49,20 @@ public final class Items {
* Register a new custom item. * Register a new custom item.
* *
* @param key The key of the item. * @param key The key of the item.
* @param part The item. * @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);
} }
/** /**
@@ -123,7 +139,20 @@ 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 Legacy id:amount format
@@ -146,7 +175,7 @@ public final class Items {
This has been superseded by namespace:id amount 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]));
if (part == null) { if (part == null) {
return new EmptyTestableItem(); return new EmptyTestableItem();
} }
@@ -215,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;
} }
@@ -231,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;
@@ -245,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

@@ -49,7 +49,7 @@ public class TextureArgParser implements LookupArgParser {
assert testMeta != null; assert testMeta != null;
if (testMeta instanceof SkullMeta skullMeta && finalSkullTexture != null) { if (testMeta instanceof SkullMeta skullMeta) {
return finalSkullTexture.equalsIgnoreCase(SkullUtils.getSkullTexture(skullMeta)); return finalSkullTexture.equalsIgnoreCase(SkullUtils.getSkullTexture(skullMeta));
} }

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,7 +2,6 @@ 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.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;

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

@@ -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;
@@ -92,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

@@ -5,7 +5,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; 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.
@@ -21,7 +23,7 @@ public class ListUtils {
* @return The list, filled will null objects. * @return The list, filled will null objects.
*/ */
@NotNull @NotNull
public <@Nullable T> List<List<T>> create2DList(final int rows, 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) {
@@ -34,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

@@ -1,6 +1,5 @@
package com.willfp.eco.util; package com.willfp.eco.util;
import lombok.experimental.NonFinal;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

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

@@ -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>
@@ -166,6 +194,68 @@ public class StringUtils {
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>
@@ -181,15 +271,22 @@ public class StringUtils {
@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) {
@@ -219,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());
@@ -255,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);
@@ -334,10 +420,14 @@ public class StringUtils {
* @return The JSON String. * @return The JSON String.
*/ */
@NotNull @NotNull
public String legacyToJson(@NotNull final String legacy) { 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)
) )
); );
} }
@@ -355,6 +445,33 @@ public class StringUtils {
); );
} }
/**
* 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

@@ -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

@@ -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

@@ -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

@@ -36,8 +36,9 @@ class Skull : SkullProxy {
profile = meta.javaClass.getDeclaredField("profile") profile = meta.javaClass.getDeclaredField("profile")
profile.isAccessible = true profile.isAccessible = true
} }
val profile = profile[meta] as GameProfile? val profile = profile[meta] as GameProfile? ?: return null
val property = profile?.properties?.get("textures") as Property? val properties = profile.properties ?: return null
return property?.value val prop = properties["textures"] ?: return null
return prop.toMutableList().firstOrNull()?.name
} }
} }

View File

@@ -0,0 +1,11 @@
package com.willfp.eco.proxy.v1_16_R3
import com.willfp.eco.proxy.TPSProxy
import org.bukkit.Bukkit
import org.bukkit.craftbukkit.v1_16_R3.CraftServer
class TPS : TPSProxy {
override fun getTPS(): Double {
return (Bukkit.getServer() as CraftServer).handle.server.recentTps[0]
}
}

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.proxy.v1_16_R3.fast
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack
import org.bukkit.inventory.ItemStack
import java.lang.reflect.Field
private val field: Field = CraftItemStack::class.java.getDeclaredField("handle").apply {
isAccessible = true
}
fun ItemStack.getNMSStack(): net.minecraft.server.v1_16_R3.ItemStack {
return if (this !is CraftItemStack) {
CraftItemStack.asNMSCopy(this)
} else {
field[this] as net.minecraft.server.v1_16_R3.ItemStack? ?: CraftItemStack.asNMSCopy(this)
}
}

View File

@@ -1,7 +1,6 @@
package com.willfp.eco.proxy.v1_16_R3.fast package com.willfp.eco.proxy.v1_16_R3.fast
import com.willfp.eco.internal.fast.EcoFastItemStack import com.willfp.eco.internal.fast.EcoFastItemStack
import com.willfp.eco.proxy.v1_16_R3.FastItemStackUtils
import com.willfp.eco.util.StringUtils import com.willfp.eco.util.StringUtils
import net.minecraft.server.v1_16_R3.* import net.minecraft.server.v1_16_R3.*
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack
@@ -12,7 +11,7 @@ import org.bukkit.inventory.ItemFlag
import kotlin.experimental.and import kotlin.experimental.and
class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemStack<ItemStack>( class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemStack<ItemStack>(
FastItemStackUtils.getNMSStack(itemStack), itemStack itemStack.getNMSStack(), itemStack
) { ) {
private var loreCache: List<String>? = null private var loreCache: List<String>? = null
override fun getEnchantmentsOnItem(checkStored: Boolean): Map<Enchantment, Int> { override fun getEnchantmentsOnItem(checkStored: Boolean): Map<Enchantment, Int> {
@@ -151,6 +150,18 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
handle.repairCost = cost handle.repairCost = cost
} }
override fun equals(other: Any?): Boolean {
if (other !is NMSFastItemStack) {
return false
}
return other.hashCode() == this.hashCode()
}
override fun hashCode(): Int {
return handle.tag.hashCode() * 31 + Item.getId(handle.item)
}
private fun apply() { private fun apply() {
if (bukkit !is CraftItemStack) { if (bukkit !is CraftItemStack) {
bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta

View File

@@ -7,6 +7,8 @@ version rootProject.version
dependencies { dependencies {
compileOnly 'org.spigotmc:spigot:1.17.1-R0.1-SNAPSHOT:remapped-mojang' compileOnly 'org.spigotmc:spigot:1.17.1-R0.1-SNAPSHOT:remapped-mojang'
compileOnly 'net.kyori:adventure-api:4.9.1'
compileOnly 'net.kyori:adventure-text-serializer-gson:4.8.1'
} }
specialGradle { specialGradle {

View File

@@ -1,118 +0,0 @@
package com.willfp.eco.proxy.v1_17_R1;
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 net.minecraft.nbt.TagParser;
import net.minecraft.network.chat.BaseComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.HoverEvent;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TranslatableComponent;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import com.willfp.eco.proxy.ChatComponentProxy;
public final class ChatComponent implements ChatComponentProxy {
@Override
public Object modifyComponent(@NotNull final Object obj,
@NotNull final Player player) {
if (!(obj instanceof Component chatComponent)) {
return obj;
}
for (Component iChatBaseComponent : chatComponent) {
if (iChatBaseComponent == null) {
continue;
}
modifyBaseComponent(iChatBaseComponent, player);
}
return chatComponent;
}
private void modifyBaseComponent(@NotNull final Component component,
@NotNull final Player player) {
for (Component sibling : component.getSiblings()) {
if (sibling == null) {
continue;
}
modifyBaseComponent(sibling, player);
}
if (component instanceof TranslatableComponent baseComponent) {
for (Object arg : baseComponent.getArgs()) {
if (arg instanceof Component) {
modifyBaseComponent((Component) arg, player);
}
}
}
HoverEvent hoverable = component.getStyle().getHoverEvent();
if (hoverable == null) {
return;
}
JsonObject jsonObject = hoverable.serialize();
JsonElement json = jsonObject.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);
HoverEvent newHoverable = HoverEvent.deserialize(jsonObject);
Style modifier = component.getStyle();
modifier = modifier.withHoverEvent(newHoverable);
((BaseComponent) component).setStyle(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.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
try {
nmsStack.setTag(TagParser.parseTag(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,45 +0,0 @@
package com.willfp.eco.proxy.v1_17_R1;
import lombok.experimental.UtilityClass;
import org.bukkit.craftbukkit.libs.org.apache.commons.lang3.Validate;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
@UtilityClass
public class FastItemStackUtils {
private static final Field FIELD;
public static net.minecraft.world.item.ItemStack getNMSStack(@NotNull final ItemStack itemStack) {
if (!(itemStack instanceof CraftItemStack)) {
return CraftItemStack.asNMSCopy(itemStack);
} else {
try {
net.minecraft.world.item.ItemStack nms = (net.minecraft.world.item.ItemStack) FIELD.get(itemStack);
return nms == null ? CraftItemStack.asNMSCopy(itemStack) : nms;
} catch (ReflectiveOperationException e) {
e.printStackTrace();
return net.minecraft.world.item.ItemStack.EMPTY;
}
}
}
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_17_R1
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.nbt.TagParser
import org.bukkit.Material
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
@Suppress("UNCHECKED_CAST")
class ChatComponent : ChatComponentProxy {
private val gsonComponentSerializer = GsonComponentSerializer.gson()
override fun modifyComponent(obj: Any, player: Player): Any {
if (obj !is net.minecraft.network.chat.Component) {
return obj
}
val component = gsonComponentSerializer.deserialize(
net.minecraft.network.chat.Component.Serializer.toJson(
obj
)
).asComponent() as BuildableComponent<*, *>
val newComponent = modifyBaseComponent(component, player)
return net.minecraft.network.chat.Component.Serializer.fromJson(
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(
ItemStack(
Material.matchMaterial(
showItem.item()
.toString()
) ?: return component,
showItem.count()
)
).apply {
this.tag = TagParser.parseTag(
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

@@ -36,8 +36,9 @@ class Skull : SkullProxy {
profile = meta.javaClass.getDeclaredField("profile") profile = meta.javaClass.getDeclaredField("profile")
profile.isAccessible = true profile.isAccessible = true
} }
val profile = profile[meta] as GameProfile? val profile = profile[meta] as GameProfile? ?: return null
val property = profile?.properties?.get("textures") as Property? val properties = profile.properties ?: return null
return property?.value val prop = properties["textures"] ?: return null
return prop.toMutableList().firstOrNull()?.name
} }
} }

View File

@@ -0,0 +1,11 @@
package com.willfp.eco.proxy.v1_17_R1
import com.willfp.eco.proxy.TPSProxy
import org.bukkit.Bukkit
import org.bukkit.craftbukkit.v1_17_R1.CraftServer
class TPS : TPSProxy {
override fun getTPS(): Double {
return (Bukkit.getServer() as CraftServer).handle.server.recentTps[0]
}
}

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.proxy.v1_17_R1.fast
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack
import org.bukkit.inventory.ItemStack
import java.lang.reflect.Field
private val field: Field = CraftItemStack::class.java.getDeclaredField("handle").apply {
isAccessible = true
}
fun ItemStack.getNMSStack(): net.minecraft.world.item.ItemStack {
return if (this !is CraftItemStack) {
CraftItemStack.asNMSCopy(this)
} else {
field[this] as net.minecraft.world.item.ItemStack? ?: CraftItemStack.asNMSCopy(this)
}
}

View File

@@ -1,12 +1,12 @@
package com.willfp.eco.proxy.v1_17_R1.fast package com.willfp.eco.proxy.v1_17_R1.fast
import com.willfp.eco.internal.fast.EcoFastItemStack import com.willfp.eco.internal.fast.EcoFastItemStack
import com.willfp.eco.proxy.v1_17_R1.FastItemStackUtils
import com.willfp.eco.util.StringUtils import com.willfp.eco.util.StringUtils
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag import net.minecraft.nbt.ListTag
import net.minecraft.nbt.StringTag import net.minecraft.nbt.StringTag
import net.minecraft.world.item.EnchantedBookItem import net.minecraft.world.item.EnchantedBookItem
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack
@@ -17,7 +17,7 @@ import org.bukkit.inventory.ItemFlag
import kotlin.experimental.and import kotlin.experimental.and
class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemStack<ItemStack>( class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemStack<ItemStack>(
FastItemStackUtils.getNMSStack(itemStack), itemStack itemStack.getNMSStack(), itemStack
) { ) {
private var loreCache: List<String>? = null private var loreCache: List<String>? = null
@@ -171,6 +171,18 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
handle.setRepairCost(cost) handle.setRepairCost(cost)
} }
override fun equals(other: Any?): Boolean {
if (other !is NMSFastItemStack) {
return false
}
return other.hashCode() == this.hashCode()
}
override fun hashCode(): Int {
return handle.tag.hashCode() * 31 + Item.getId(handle.item)
}
private fun apply() { private fun apply() {
if (bukkit !is CraftItemStack) { if (bukkit !is CraftItemStack) {
bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta

View File

@@ -3,26 +3,43 @@ version rootProject.version
dependencies { dependencies {
implementation 'org.bstats:bstats-bukkit:1.7' implementation 'org.bstats:bstats-bukkit:1.7'
compileOnly 'org.apache.maven:maven-artifact:3.0.3' implementation('net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT') {
compileOnly 'com.google.code.gson:gson:2.8.7' exclude group: 'net.kyori', module: 'adventure-api'
compileOnly 'org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT' }
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
compileOnly 'net.kyori:adventure-api:4.9.2'
compileOnly 'net.kyori:adventure-text-serializer-gson:4.9.2'
compileOnly 'net.kyori:adventure-text-serializer-legacy:4.9.2'
compileOnly 'org.apache.maven:maven-artifact:3.8.1'
compileOnly 'com.google.code.gson:gson:2.8.8'
compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT'
compileOnly project(":eco-core:core-proxy") compileOnly project(":eco-core:core-proxy")
compileOnly project(":eco-core:core-backend") compileOnly project(":eco-core:core-backend")
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT' compileOnly 'com.comphenix.protocol:ProtocolLib:4.7.1-SNAPSHOT'
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.4-SNAPSHOT' compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.7-SNAPSHOT'
compileOnly 'com.github.TechFortress:GriefPrevention:16.14.0' compileOnly 'com.github.TechFortress:GriefPrevention:16.17.1'
compileOnly 'com.massivecraft:Factions:1.6.9.5-U0.5.10' compileOnly 'com.massivecraft:Factions:1.6.9.5-U0.5.10'
compileOnly 'com.github.cryptomorin:kingdoms:1.10.14' compileOnly 'com.github.cryptomorin:kingdoms:1.11.9'
compileOnly 'com.github.TownyAdvanced:Towny:0.96.2.0' compileOnly 'com.github.TownyAdvanced:Towny:0.97.2.6'
compileOnly 'com.github.angeschossen:LandsAPI:4.7.3' compileOnly 'com.github.angeschossen:LandsAPI:5.15.2'
compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT' compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT'
compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd' compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd'
compileOnly 'com.gmail.nossr50.mcMMO:mcMMO:2.1.157' compileOnly 'com.gmail.nossr50.mcMMO:mcMMO:2.1.202'
compileOnly 'me.clip:placeholderapi:2.10.9' compileOnly 'me.clip:placeholderapi:2.10.10'
compileOnly 'com.willfp:Oraxen:e1f4003d8d' compileOnly 'com.github.oraxen:oraxen:bd81ace154'
compileOnly 'com.github.brcdev-minecraft:shopgui-api:2.2.0' compileOnly 'com.github.brcdev-minecraft:shopgui-api:2.2.0'
compileOnly 'com.github.LoneDev6:API-ItemsAdder:2.4.7' compileOnly 'com.github.LoneDev6:API-ItemsAdder:2.4.7'
compileOnly 'me.arcaniax:HeadDatabase-API:1.2.0' compileOnly 'com.arcaniax:HeadDatabase-API:1.3.0'
compileOnly 'org.jetbrains.exposed:exposed-core:0.35.1'
compileOnly 'org.jetbrains.exposed:exposed-dao:0.35.1'
compileOnly 'org.jetbrains.exposed:exposed-jdbc:0.35.1'
compileOnly 'mysql:mysql-connector-java:8.0.25'
compileOnly 'com.gmail.filoghost.holographicdisplays:holographicdisplays-api:2.4.0'
compileOnly 'net.essentialsx:EssentialsX:2.19.0'
compileOnly 'com.bgsoftware:SuperiorSkyblockAPI:latest'
compileOnly 'com.github.MilkBowl:VaultAPI:1.7'
compileOnly 'world.bentobox:bentobox:1.17.3-SNAPSHOT'
compileOnly 'com.google.guava:guava:31.0.1-jre'
// CombatLogX V10 + NewbieHelper Expansion // CombatLogX V10 + NewbieHelper Expansion
compileOnly 'com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT' compileOnly 'com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT'

View File

@@ -1,42 +0,0 @@
package com.willfp.eco.spigot.eventlisteners;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.events.ArmorChangeEvent;
import com.willfp.eco.core.events.ArmorEquipEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@SuppressWarnings("deprecation")
public class ArmorChangeEventListeners extends PluginDependent<EcoPlugin> implements Listener {
/**
* Pass an {@link EcoPlugin} in order to interface with it.
*
* @param plugin The plugin to manage.
*/
public ArmorChangeEventListeners(@NotNull final EcoPlugin plugin) {
super(plugin);
}
@EventHandler
public void onArmorChange(@NotNull final ArmorEquipEvent event) {
Player player = event.getPlayer();
List<ItemStack> before = new ArrayList<>(Arrays.asList(player.getInventory().getArmorContents()));
this.getPlugin().getScheduler().runLater(() -> {
List<ItemStack> after = new ArrayList<>(Arrays.asList(player.getInventory().getArmorContents()));
ArmorChangeEvent armorChangeEvent = new ArmorChangeEvent(player, before, after);
Bukkit.getPluginManager().callEvent(armorChangeEvent);
}, 1);
}
}

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