Compare commits

..

120 Commits

Author SHA1 Message Date
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
87 changed files with 1890 additions and 934 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

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

View File

@@ -51,23 +51,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 +84,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.1'
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.8.1'
// Other
compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT'
compileOnly 'org.apache.maven:maven-artifact:3.0.3'
compileOnly 'com.comphenix.protocol:ProtocolLib:4.7.1-SNAPSHOT'
compileOnly 'com.google.code.gson:gson:2.8.7'
} }
java { java {

View File

@@ -54,7 +54,7 @@ import java.util.stream.Collectors;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public abstract class EcoPlugin extends JavaPlugin { public abstract class EcoPlugin extends JavaPlugin {
/** /**
* 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

@@ -13,7 +13,9 @@ 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.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -194,4 +196,20 @@ 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();
} }

View File

@@ -0,0 +1,54 @@
package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull;
/**
* Config implementation for configs present in the plugin's base directory (eg config.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 EcoPlugin 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 EcoPlugin plugin) {
super(
Eco.getHandler().getConfigFactory().createUpdatableJSONConfig(
configName,
plugin,
"",
plugin.getClass(),
removeUnused
)
);
}
}

View File

@@ -0,0 +1,44 @@
package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull;
/**
* Config implementation for configs present in one of two places:
* <ul>
* <li>Plugin base directory (eg config.yml, lang.yml)</li>
* <li>Other extension's configs</li>
* </ul>
* <p>
* Automatically updates.
*/
public abstract class 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 EcoPlugin plugin,
@NotNull final Class<?> source,
@NotNull final String subDirectoryPath,
@NotNull final String... updateBlacklist) {
super(
Eco.getHandler().getConfigFactory().createUpdatableJSONConfig(
configName,
plugin,
subDirectoryPath,
source,
removeUnused,
updateBlacklist
)
);
}
}

View File

@@ -30,6 +30,24 @@ public interface ConfigFactory {
boolean removeUnused, boolean removeUnused,
@NotNull String... updateBlacklist); @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 EcoPlugin plugin,
@NotNull String subDirectoryPath,
@NotNull Class<?> source,
boolean removeUnused,
@NotNull String... updateBlacklist);
/** /**
* JSON loadable config. * JSON loadable config.
* *

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<>(); public 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,61 @@ 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);
} }
} }
} }

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 final ItemStack itemStack,
@Nullable final Player player);
/**
* Revert on ItemStacks.
*
* @param itemStack The item.
* @return The ItemStack.
*/
ItemStack revert(@NotNull final ItemStack itemStack);
/**
* Finalize an ItemStacks.
*
* @param itemStack The item.
* @return The ItemStack.
*/
ItemStack finalize(@NotNull final ItemStack itemStack);
/**
* Unfinalize an ItemStacks.
*
* @param itemStack The item.
* @return The ItemStack.
*/
ItemStack unfinalize(@NotNull final ItemStack itemStack);
/**
* If an item is finalized.
*
* @param itemStack The item.
* @return If finalized.
*/
boolean isFinalized(@NotNull final ItemStack itemStack);
}

View File

@@ -36,8 +36,8 @@ 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,9 +48,9 @@ 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

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

View File

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

View File

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

@@ -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 final String key);
}

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

@@ -31,7 +31,9 @@ public class UpdateChecker extends PluginDependent<EcoPlugin> {
public void getVersion(@NotNull final Consumer<? super String> consumer) { public void getVersion(@NotNull final Consumer<? super String> consumer) {
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()) {

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

@@ -0,0 +1,66 @@
package com.willfp.eco.util;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.Prerequisite;
import lombok.experimental.UtilityClass;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Utilities / API methods for players.
*/
@UtilityClass
public class PlayerUtils {
/**
* 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);
}
}
}
}

View File

@@ -1,10 +1,13 @@
package com.willfp.eco.util; package com.willfp.eco.util;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
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;
@@ -12,7 +15,7 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.awt.Color; import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -34,6 +37,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();
@@ -166,6 +171,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 +248,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 = translateGradients(processedMessage);
processedMessage = translateHexColorCodes(processedMessage); processedMessage = translateHexColorCodes(processedMessage);
processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage); processedMessage = ChatColor.translateAlternateColorCodes('&', 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) {
@@ -255,6 +329,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 +411,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 +436,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,9 @@ 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'
} }

View File

@@ -6,6 +6,7 @@ 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
@@ -30,6 +31,24 @@ class EcoConfigFactory : ConfigFactory {
) )
} }
override fun createUpdatableJSONConfig(
configName: String,
plugin: EcoPlugin,
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: EcoPlugin,

View File

@@ -6,14 +6,15 @@ 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 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()

View File

@@ -8,11 +8,11 @@ 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: EcoPlugin,
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 +65,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 {

View File

@@ -0,0 +1,74 @@
package com.willfp.eco.internal.config.json
import com.willfp.eco.core.EcoPlugin
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: EcoPlugin,
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

@@ -6,11 +6,12 @@ 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

View File

@@ -0,0 +1,119 @@
package com.willfp.eco.internal.display
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
class EcoDisplayHandler(plugin: EcoPlugin) : DisplayHandler {
/**
* All registered display modules.
*/
private val registeredModules = mutableMapOf<DisplayPriority, MutableList<DisplayModule>>()
/**
* NamespacedKey for finalizing.
*/
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

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

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

@@ -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,33 @@ version rootProject.version
dependencies { dependencies {
implementation 'org.bstats:bstats-bukkit:1.7' implementation 'org.bstats:bstats-bukkit:1.7'
implementation('net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT') {
exclude group: 'net.kyori', module: 'adventure-api'
}
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
compileOnly 'net.kyori:adventure-api:4.9.1'
compileOnly 'net.kyori:adventure-text-serializer-gson:4.9.2'
compileOnly 'net.kyori:adventure-text-serializer-legacy:4.8.1'
compileOnly 'org.apache.maven:maven-artifact:3.0.3' compileOnly 'org.apache.maven:maven-artifact:3.0.3'
compileOnly 'com.google.code.gson:gson:2.8.7' compileOnly 'com.google.code.gson:gson:2.8.7'
compileOnly 'org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT' 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.10.14'
compileOnly 'com.github.TownyAdvanced:Towny:0.96.2.0' compileOnly 'com.github.TownyAdvanced:Towny:0.97.2.5'
compileOnly 'com.github.angeschossen:LandsAPI:4.7.3' compileOnly 'com.github.angeschossen:LandsAPI:4.7.3'
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.willfp:Oraxen:e1f4003d8d'
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'
// 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);
}
}

View File

@@ -1,187 +0,0 @@
package com.willfp.eco.spigot.eventlisteners;
import com.willfp.eco.core.events.ArmorEquipEvent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemBreakEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("deprecation")
public class ArmorListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public final void inventoryClick(@NotNull final InventoryClickEvent event) {
boolean shift = false;
boolean numberkey = false;
if (event.isCancelled()) {
return;
}
if (event.getAction() == InventoryAction.NOTHING) {
return;
}
if (event.getClick().equals(ClickType.SHIFT_LEFT) || event.getClick().equals(ClickType.SHIFT_RIGHT)) {
shift = true;
}
if (event.getClick().equals(ClickType.NUMBER_KEY)) {
numberkey = true;
}
if (event.getSlotType() != SlotType.ARMOR && event.getSlotType() != SlotType.QUICKBAR && event.getSlotType() != SlotType.CONTAINER) {
return;
}
if (event.getClickedInventory() != null && !event.getClickedInventory().getType().equals(InventoryType.PLAYER)) {
return;
}
if (!event.getInventory().getType().equals(InventoryType.CRAFTING) && !event.getInventory().getType().equals(InventoryType.PLAYER)) {
return;
}
if (!(event.getWhoClicked() instanceof Player)) {
return;
}
ArmorType newArmorType = ArmorType.matchType(shift ? event.getCurrentItem() : event.getCursor());
if (!shift && newArmorType != null && event.getRawSlot() != newArmorType.getSlot()) {
// Used for drag and drop checking to make sure you aren't trying to place a helmet in the boots slot.
return;
}
if (shift) {
newArmorType = ArmorType.matchType(event.getCurrentItem());
if (newArmorType != null) {
boolean equipping = true;
if (event.getRawSlot() == newArmorType.getSlot()) {
equipping = false;
}
if (newArmorType.equals(ArmorType.HELMET)
&& (equipping == isAirOrNull(event.getWhoClicked().getInventory().getHelmet()))
|| newArmorType.equals(ArmorType.CHESTPLATE)
&& (equipping == isAirOrNull(event.getWhoClicked().getInventory().getChestplate()))
|| newArmorType.equals(ArmorType.LEGGINGS)
&& (equipping == isAirOrNull(event.getWhoClicked().getInventory().getLeggings()))
|| newArmorType.equals(ArmorType.BOOTS)
&& (equipping == isAirOrNull(event.getWhoClicked().getInventory().getBoots()))) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(
(Player) event.getWhoClicked()
);
Bukkit.getPluginManager().callEvent(armorEquipEvent);
}
}
} else {
if (numberkey) {
if (event.getClickedInventory().getType().equals(InventoryType.PLAYER)) {
ItemStack hotbarItem = event.getClickedInventory().getItem(event.getHotbarButton());
if (!isAirOrNull(hotbarItem)) {
newArmorType = ArmorType.matchType(hotbarItem);
} else {
newArmorType = ArmorType.matchType(!isAirOrNull(event.getCurrentItem()) ? event.getCurrentItem() : event.getCursor());
}
}
} else {
if (isAirOrNull(event.getCursor()) && !isAirOrNull(event.getCurrentItem())) {
newArmorType = ArmorType.matchType(event.getCurrentItem());
}
}
if (newArmorType != null && event.getRawSlot() == newArmorType.getSlot()) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) event.getWhoClicked());
Bukkit.getPluginManager().callEvent(armorEquipEvent);
}
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void playerInteractEvent(@NotNull final PlayerInteractEvent e) {
if (e.useItemInHand().equals(Result.DENY)) {
return;
}
if (e.getAction() == Action.PHYSICAL) {
return;
}
if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
Player player = e.getPlayer();
if (!e.useInteractedBlock().equals(Result.DENY)) {
if (e.getClickedBlock() != null && e.getAction() == Action.RIGHT_CLICK_BLOCK && !player.isSneaking()) {
Material mat = e.getClickedBlock().getType();
}
}
ArmorType newArmorType = ArmorType.matchType(e.getItem());
if (newArmorType != null) {
if (newArmorType.equals(ArmorType.HELMET)
&& isAirOrNull(e.getPlayer().getInventory().getHelmet())
|| newArmorType.equals(ArmorType.CHESTPLATE)
&& isAirOrNull(e.getPlayer().getInventory().getChestplate())
|| newArmorType.equals(ArmorType.LEGGINGS)
&& isAirOrNull(e.getPlayer().getInventory().getLeggings())
|| newArmorType.equals(ArmorType.BOOTS)
&& isAirOrNull(e.getPlayer().getInventory().getBoots())) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(e.getPlayer());
Bukkit.getPluginManager().callEvent(armorEquipEvent);
}
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void inventoryDrag(@NotNull final InventoryDragEvent event) {
ArmorType type = ArmorType.matchType(event.getOldCursor());
if (event.getRawSlots().isEmpty()) {
return;
}
if (type != null && type.getSlot() == event.getRawSlots().stream().findFirst().orElse(0)) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) event.getWhoClicked());
Bukkit.getPluginManager().callEvent(armorEquipEvent);
}
}
@EventHandler
public void playerJoinEvent(@NotNull final PlayerJoinEvent event) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(event.getPlayer());
Bukkit.getPluginManager().callEvent(armorEquipEvent);
}
@EventHandler
public void playerRespawnEvent(@NotNull final PlayerRespawnEvent event) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(event.getPlayer());
Bukkit.getPluginManager().callEvent(armorEquipEvent);
}
@EventHandler
public void itemBreakEvent(@NotNull final PlayerItemBreakEvent event) {
ArmorType type = ArmorType.matchType(event.getBrokenItem());
if (type != null) {
Player p = event.getPlayer();
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p);
Bukkit.getPluginManager().callEvent(armorEquipEvent);
}
}
@EventHandler
public void playerDeathEvent(@NotNull final PlayerDeathEvent event) {
Player p = event.getEntity();
if (event.getKeepInventory()) {
return;
}
for (ItemStack i : p.getInventory().getArmorContents()) {
if (!isAirOrNull(i)) {
Bukkit.getPluginManager().callEvent(new ArmorEquipEvent(p));
}
}
}
public static boolean isAirOrNull(@Nullable final ItemStack item) {
return item == null || item.getType().equals(Material.AIR);
}
}

View File

@@ -1,38 +0,0 @@
package com.willfp.eco.spigot.eventlisteners;
import org.bukkit.inventory.ItemStack;
public enum ArmorType {
HELMET(5),
CHESTPLATE(6),
LEGGINGS(7),
BOOTS(8);
private final int slot;
ArmorType(final int slot) {
this.slot = slot;
}
public static ArmorType matchType(final ItemStack itemStack) {
if (ArmorListener.isAirOrNull(itemStack)) {
return null;
}
String type = itemStack.getType().name();
if (type.endsWith("_HELMET") || type.endsWith("_SKULL") || type.endsWith("PLAYER_HEAD")) {
return HELMET;
} else if (type.endsWith("_CHESTPLATE") || type.endsWith("ELYTRA")) {
return CHESTPLATE;
} else if (type.endsWith("_LEGGINGS")) {
return LEGGINGS;
} else if (type.endsWith("_BOOTS")) {
return BOOTS;
} else {
return null;
}
}
public int getSlot() {
return slot;
}
}

View File

@@ -1,21 +0,0 @@
package com.willfp.eco.spigot.eventlisteners;
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.event.block.BlockDispenseArmorEvent;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("deprecation")
public class DispenserArmorListener implements Listener {
@EventHandler
public void dispenseArmorEvent(@NotNull final BlockDispenseArmorEvent event) {
ArmorType type = ArmorType.matchType(event.getItem());
if (type != null && event.getTargetEntity() instanceof Player p) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p);
Bukkit.getPluginManager().callEvent(armorEquipEvent);
}
}
}

View File

@@ -15,6 +15,7 @@ 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 com.willfp.eco.internal.EcoCleaner import com.willfp.eco.internal.EcoCleaner
import com.willfp.eco.internal.Plugins import com.willfp.eco.internal.Plugins
@@ -30,15 +31,19 @@ import com.willfp.eco.internal.gui.EcoGUIFactory
import com.willfp.eco.internal.integrations.PlaceholderIntegrationPAPI import com.willfp.eco.internal.integrations.PlaceholderIntegrationPAPI
import com.willfp.eco.internal.logging.EcoLogger import com.willfp.eco.internal.logging.EcoLogger
import com.willfp.eco.internal.proxy.EcoProxyFactory import com.willfp.eco.internal.proxy.EcoProxyFactory
import com.willfp.eco.internal.requirement.EcoRequirementFactory
import com.willfp.eco.internal.scheduling.EcoScheduler import com.willfp.eco.internal.scheduling.EcoScheduler
import com.willfp.eco.proxy.FastItemStackFactoryProxy import com.willfp.eco.proxy.FastItemStackFactoryProxy
import com.willfp.eco.spigot.integrations.bstats.MetricHandler import com.willfp.eco.spigot.integrations.bstats.MetricHandler
import net.kyori.adventure.platform.bukkit.BukkitAudiences
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.util.logging.Logger import java.util.logging.Logger
@Suppress("UNUSED") @Suppress("UNUSED")
class EcoHandler : EcoSpigotPlugin(), Handler { class EcoHandler : EcoSpigotPlugin(), Handler {
private val cleaner = EcoCleaner() private val cleaner = EcoCleaner()
private val requirementFactory = EcoRequirementFactory()
private var adventure: BukkitAudiences? = null
override fun createScheduler(plugin: EcoPlugin): Scheduler { override fun createScheduler(plugin: EcoPlugin): Scheduler {
return EcoScheduler(plugin) return EcoScheduler(plugin)
@@ -119,4 +124,16 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
override fun registerBStats(plugin: EcoPlugin) { override fun registerBStats(plugin: EcoPlugin) {
MetricHandler.createMetrics(plugin, this.ecoPlugin) MetricHandler.createMetrics(plugin, this.ecoPlugin)
} }
override fun getRequirementFactory(): RequirementFactory {
return requirementFactory
}
override fun getAdventure(): BukkitAudiences? {
return adventure
}
fun setAdventure(adventure: BukkitAudiences) {
this.adventure = adventure
}
} }

View File

@@ -1,7 +1,9 @@
package com.willfp.eco.spigot package com.willfp.eco.spigot
import com.willfp.eco.core.AbstractPacketAdapter import com.willfp.eco.core.AbstractPacketAdapter
import com.willfp.eco.core.Eco
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.Prerequisite
import com.willfp.eco.core.display.Display import com.willfp.eco.core.display.Display
import com.willfp.eco.core.integrations.IntegrationLoader import com.willfp.eco.core.integrations.IntegrationLoader
import com.willfp.eco.core.integrations.anticheat.AnticheatManager import com.willfp.eco.core.integrations.anticheat.AnticheatManager
@@ -12,6 +14,7 @@ import com.willfp.eco.core.integrations.shop.ShopManager
import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.Items
import com.willfp.eco.core.items.args.EnchantmentArgParser import com.willfp.eco.core.items.args.EnchantmentArgParser
import com.willfp.eco.core.items.args.TextureArgParser import com.willfp.eco.core.items.args.TextureArgParser
import com.willfp.eco.internal.display.EcoDisplayHandler
import com.willfp.eco.internal.drops.DropManager import com.willfp.eco.internal.drops.DropManager
import com.willfp.eco.proxy.BlockBreakProxy import com.willfp.eco.proxy.BlockBreakProxy
import com.willfp.eco.proxy.FastItemStackFactoryProxy import com.willfp.eco.proxy.FastItemStackFactoryProxy
@@ -19,7 +22,11 @@ import com.willfp.eco.proxy.SkullProxy
import com.willfp.eco.spigot.arrows.ArrowDataListener import com.willfp.eco.spigot.arrows.ArrowDataListener
import com.willfp.eco.spigot.display.* import com.willfp.eco.spigot.display.*
import com.willfp.eco.spigot.drops.CollatedRunnable import com.willfp.eco.spigot.drops.CollatedRunnable
import com.willfp.eco.spigot.eventlisteners.* import com.willfp.eco.spigot.eventlisteners.EntityDeathByEntityListeners
import com.willfp.eco.spigot.eventlisteners.NaturalExpGainListeners
import com.willfp.eco.spigot.eventlisteners.PlayerJumpListeners
import com.willfp.eco.spigot.eventlisteners.armor.ArmorChangeEventListeners
import com.willfp.eco.spigot.eventlisteners.armor.ArmorListener
import com.willfp.eco.spigot.gui.GUIListener import com.willfp.eco.spigot.gui.GUIListener
import com.willfp.eco.spigot.integrations.anticheat.* import com.willfp.eco.spigot.integrations.anticheat.*
import com.willfp.eco.spigot.integrations.antigrief.* import com.willfp.eco.spigot.integrations.antigrief.*
@@ -31,6 +38,7 @@ import com.willfp.eco.spigot.integrations.shop.ShopShopGuiPlus
import com.willfp.eco.spigot.recipes.ShapedRecipeListener import com.willfp.eco.spigot.recipes.ShapedRecipeListener
import com.willfp.eco.util.BlockUtils import com.willfp.eco.util.BlockUtils
import com.willfp.eco.util.SkullUtils import com.willfp.eco.util.SkullUtils
import net.kyori.adventure.platform.bukkit.BukkitAudiences
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.block.Block import org.bukkit.block.Block
@@ -40,14 +48,12 @@ import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.SkullMeta import org.bukkit.inventory.meta.SkullMeta
abstract class EcoSpigotPlugin : EcoPlugin( abstract class EcoSpigotPlugin : EcoPlugin(
87955, 773,
10043, 10043,
"com.willfp.eco.proxy", "com.willfp.eco.proxy",
"&a" "&a"
) { ) {
init { init {
Display.setFinalizeKey(namespacedKeyFactory.create("finalized"))
Items.registerArgParser(EnchantmentArgParser()) Items.registerArgParser(EnchantmentArgParser())
Items.registerArgParser(TextureArgParser()) Items.registerArgParser(TextureArgParser())
@@ -59,11 +65,21 @@ abstract class EcoSpigotPlugin : EcoPlugin(
val blockBreakProxy = getProxy(BlockBreakProxy::class.java) val blockBreakProxy = getProxy(BlockBreakProxy::class.java)
BlockUtils.initialize { player: Player, block: Block -> blockBreakProxy.breakBlock(player, block) } BlockUtils.initialize { player: Player, block: Block -> blockBreakProxy.breakBlock(player, block) }
postInit()
}
private fun postInit() {
Display.handler = EcoDisplayHandler(this)
} }
override fun handleEnable() { override fun handleEnable() {
CollatedRunnable(this) CollatedRunnable(this)
if (!Prerequisite.HAS_PAPER.isMet) {
(Eco.getHandler() as EcoHandler).setAdventure(BukkitAudiences.create(this))
}
this.logger.info("Ignore messages about deprecated events!") this.logger.info("Ignore messages about deprecated events!")
if (!this.configYml.getBool("enable-bstats")) { if (!this.configYml.getBool("enable-bstats")) {
@@ -83,6 +99,10 @@ abstract class EcoSpigotPlugin : EcoPlugin(
this.getProxy(FastItemStackFactoryProxy::class.java).create(ItemStack(Material.AIR)).unwrap() this.getProxy(FastItemStackFactoryProxy::class.java).create(ItemStack(Material.AIR)).unwrap()
} }
override fun handleDisable() {
Eco.getHandler().adventure?.close()
}
override fun handleReload() { override fun handleReload() {
CollatedRunnable(this) CollatedRunnable(this)
DropManager.update(this) DropManager.update(this)
@@ -90,6 +110,7 @@ abstract class EcoSpigotPlugin : EcoPlugin(
override fun handleAfterLoad() { override fun handleAfterLoad() {
CustomItemsManager.registerAllItems() CustomItemsManager.registerAllItems()
ShopManager.registerEcoProvider()
} }
override fun loadIntegrationLoaders(): List<IntegrationLoader> { override fun loadIntegrationLoaders(): List<IntegrationLoader> {
@@ -122,11 +143,11 @@ abstract class EcoSpigotPlugin : EcoPlugin(
// Custom Items // Custom Items
IntegrationLoader("Oraxen") { CustomItemsManager.register(CustomItemsOraxen()) }, IntegrationLoader("Oraxen") { CustomItemsManager.register(CustomItemsOraxen()) },
IntegrationLoader("ItemsAdder") { CustomItemsManager.register(CustomItemsItemsAdder(this)) }, IntegrationLoader("ItemsAdder") { CustomItemsManager.register(CustomItemsItemsAdder()) },
IntegrationLoader("HeadDatabase") { CustomItemsManager.register(CustomItemsHeadDatabase()) }, IntegrationLoader("HeadDatabase") { CustomItemsManager.register(CustomItemsHeadDatabase(this)) },
// Shop // Shop
IntegrationLoader("ShopGuiPlus") { ShopManager.register(ShopShopGuiPlus()) }, IntegrationLoader("ShopGUIPlus") { ShopManager.register(ShopShopGuiPlus()) },
// Misc // Misc
IntegrationLoader("mcMMO") { McmmoManager.register(McmmoIntegrationImpl()) } IntegrationLoader("mcMMO") { McmmoManager.register(McmmoIntegrationImpl()) }
@@ -148,7 +169,6 @@ abstract class EcoSpigotPlugin : EcoPlugin(
return listOf( return listOf(
NaturalExpGainListeners(), NaturalExpGainListeners(),
ArmorListener(), ArmorListener(),
DispenserArmorListener(),
EntityDeathByEntityListeners(this), EntityDeathByEntityListeners(this),
ShapedRecipeListener(this), ShapedRecipeListener(this),
PlayerJumpListeners(), PlayerJumpListeners(),

View File

@@ -11,7 +11,10 @@ import com.willfp.eco.proxy.ChatComponentProxy
import org.bukkit.entity.Player import org.bukkit.entity.Player
class PacketChat(plugin: EcoPlugin) : class PacketChat(plugin: EcoPlugin) :
AbstractPacketAdapter(plugin, PacketType.Play.Server.CHAT, ListenerPriority.MONITOR, true) { AbstractPacketAdapter(plugin,
PacketType.Play.Server.CHAT,
if (plugin.configYml.getBool("use-lower-protocollib-priority")) ListenerPriority.NORMAL else ListenerPriority.HIGHEST,
true) {
override fun onSend( override fun onSend(
packet: PacketContainer, packet: PacketContainer,
player: Player, player: Player,

View File

@@ -13,7 +13,10 @@ import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.MerchantRecipe import org.bukkit.inventory.MerchantRecipe
class PacketOpenWindowMerchant(plugin: EcoPlugin) : class PacketOpenWindowMerchant(plugin: EcoPlugin) :
AbstractPacketAdapter(plugin, PacketType.Play.Server.OPEN_WINDOW_MERCHANT, ListenerPriority.MONITOR, true) { AbstractPacketAdapter(plugin,
PacketType.Play.Server.OPEN_WINDOW_MERCHANT,
if (plugin.configYml.getBool("use-lower-protocollib-priority")) ListenerPriority.NORMAL else ListenerPriority.MONITOR,
true) {
override fun onSend( override fun onSend(
packet: PacketContainer, packet: PacketContainer,
player: Player, player: Player,

View File

@@ -6,9 +6,11 @@ import com.comphenix.protocol.events.PacketEvent
import com.willfp.eco.core.AbstractPacketAdapter import com.willfp.eco.core.AbstractPacketAdapter
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.display.Display import com.willfp.eco.core.display.Display
import com.willfp.eco.core.fast.FastItemStack
import com.willfp.eco.spigot.display.frame.DisplayFrame
import com.willfp.eco.spigot.display.frame.lastDisplayFrame
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.util.function.Consumer
class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, PacketType.Play.Server.WINDOW_ITEMS, false) { class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, PacketType.Play.Server.WINDOW_ITEMS, false) {
override fun onSend( override fun onSend(
@@ -20,11 +22,21 @@ class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packe
if (itemStacks == null) { if (itemStacks == null) {
return@modify null return@modify null
} }
itemStacks.forEach(Consumer { item: ItemStack -> val frameMap = mutableMapOf<Byte, Int>()
Display.display(
item, player for (index in itemStacks.indices) {
) frameMap[index.toByte()] = FastItemStack.wrap(itemStacks[index]).hashCode()
}) }
val newFrame = DisplayFrame(frameMap)
val changes = player.lastDisplayFrame.getChangedSlots(newFrame)
player.lastDisplayFrame = newFrame
for (index in changes) {
Display.display(itemStacks[index.toInt()], player)
}
itemStacks itemStacks
} }
} }

View File

@@ -0,0 +1,28 @@
package com.willfp.eco.spigot.display.frame
import org.bukkit.entity.Player
import java.util.*
data class DisplayFrame(val items: Map<Byte, Int>) {
fun getChangedSlots(newFrame: DisplayFrame): List<Byte> {
val changes = mutableListOf<Byte>()
for ((slot, hash) in newFrame.items) {
if (items[slot] != hash) {
changes.add(slot)
}
}
return changes
}
}
private val frames = mutableMapOf<UUID, DisplayFrame>()
var Player.lastDisplayFrame: DisplayFrame
get() {
return frames[this.uniqueId] ?: DisplayFrame(emptyMap())
}
set(value) {
frames[this.uniqueId] = value
}

View File

@@ -0,0 +1,33 @@
package com.willfp.eco.spigot.eventlisteners.armor
import com.willfp.eco.core.EcoPlugin
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.event.block.BlockDispenseArmorEvent
class ArmorChangeEventListeners(
private val plugin: EcoPlugin
) : Listener {
@EventHandler
fun onArmorChange(event: ArmorEquipEvent) {
val player = event.player
val before = player.inventory.armorContents.toMutableList()
plugin.scheduler.run {
val after = player.inventory.armorContents.toMutableList()
val armorChangeEvent = ArmorChangeEvent(player, before, after)
Bukkit.getPluginManager().callEvent(armorChangeEvent)
}
}
@EventHandler
fun dispenseArmorEvent(event: BlockDispenseArmorEvent) {
val type = ArmorType.matchType(event.item)
if (type != null && event.targetEntity is Player) {
Bukkit.getPluginManager().callEvent(ArmorEquipEvent(event.targetEntity as Player))
}
}
}

View File

@@ -0,0 +1,175 @@
package com.willfp.eco.spigot.eventlisteners.armor
import com.willfp.eco.core.events.ArmorEquipEvent
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.Event
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
import org.bukkit.event.block.Action
import org.bukkit.event.entity.PlayerDeathEvent
import org.bukkit.event.inventory.*
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerItemBreakEvent
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerRespawnEvent
import org.bukkit.inventory.ItemStack
class ArmorListener : Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
fun inventoryClick(event: InventoryClickEvent) {
var shift = false
var numberkey = false
if (event.isCancelled) {
return
}
if (event.action == InventoryAction.NOTHING) {
return
}
if (event.click == ClickType.SHIFT_LEFT || event.click == ClickType.SHIFT_RIGHT) {
shift = true
}
if (event.click == ClickType.NUMBER_KEY) {
numberkey = true
}
if (event.slotType != InventoryType.SlotType.ARMOR && event.slotType != InventoryType.SlotType.QUICKBAR && event.slotType != InventoryType.SlotType.CONTAINER) {
return
}
if (event.clickedInventory != null && event.clickedInventory!!.type != InventoryType.PLAYER) {
return
}
if (event.inventory.type != InventoryType.CRAFTING && event.inventory.type != InventoryType.PLAYER) {
return
}
if (event.whoClicked !is Player) {
return
}
var newArmorType = ArmorType.matchType(if (shift) event.currentItem else event.cursor)
if (!shift && newArmorType != null && event.rawSlot != newArmorType.slot) {
// Used for drag and drop checking to make sure you aren't trying to place a helmet in the boots slot.
return
}
if (shift) {
newArmorType = ArmorType.matchType(event.currentItem)
if (newArmorType != null) {
var equipping = true
if (event.rawSlot == newArmorType.slot) {
equipping = false
}
if (newArmorType == ArmorType.HELMET && equipping == isAirOrNull(event.whoClicked.inventory.helmet) || newArmorType == ArmorType.CHESTPLATE && equipping == isAirOrNull(
event.whoClicked.inventory.chestplate
) || newArmorType == ArmorType.LEGGINGS && equipping == isAirOrNull(event.whoClicked.inventory.leggings) || newArmorType == ArmorType.BOOTS && equipping == isAirOrNull(
event.whoClicked.inventory.boots
)
) {
val armorEquipEvent = ArmorEquipEvent(
(event.whoClicked as Player)
)
Bukkit.getPluginManager().callEvent(armorEquipEvent)
}
}
} else {
if (numberkey) {
if (event.clickedInventory!!.type == InventoryType.PLAYER) {
val hotbarItem = event.clickedInventory!!.getItem(event.hotbarButton)
newArmorType = if (!isAirOrNull(hotbarItem)) {
ArmorType.matchType(hotbarItem)
} else {
ArmorType.matchType(if (!isAirOrNull(event.currentItem)) event.currentItem else event.cursor)
}
}
} else {
if (isAirOrNull(event.cursor) && !isAirOrNull(event.currentItem)) {
newArmorType = ArmorType.matchType(event.currentItem)
}
}
if (newArmorType != null && event.rawSlot == newArmorType.slot) {
val armorEquipEvent = ArmorEquipEvent(
(event.whoClicked as Player)
)
Bukkit.getPluginManager().callEvent(armorEquipEvent)
}
}
}
@EventHandler(priority = EventPriority.HIGHEST)
fun playerInteractEvent(e: PlayerInteractEvent) {
if (e.useItemInHand() == Event.Result.DENY) {
return
}
if (e.action == Action.PHYSICAL) {
return
}
if (e.action == Action.RIGHT_CLICK_AIR || e.action == Action.RIGHT_CLICK_BLOCK) {
val newArmorType = ArmorType.matchType(e.item)
if (newArmorType != null) {
if (newArmorType == ArmorType.HELMET && isAirOrNull(e.player.inventory.helmet) || newArmorType == ArmorType.CHESTPLATE && isAirOrNull(
e.player.inventory.chestplate
) || newArmorType == ArmorType.LEGGINGS && isAirOrNull(e.player.inventory.leggings) || newArmorType == ArmorType.BOOTS && isAirOrNull(
e.player.inventory.boots
)
) {
val armorEquipEvent = ArmorEquipEvent(e.player)
Bukkit.getPluginManager().callEvent(armorEquipEvent)
}
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
fun inventoryDrag(event: InventoryDragEvent) {
val type = ArmorType.matchType(event.oldCursor)
if (event.rawSlots.isEmpty()) {
return
}
if (type != null && type.slot == event.rawSlots.stream().findFirst().orElse(0)) {
val armorEquipEvent = ArmorEquipEvent(
(event.whoClicked as Player)
)
Bukkit.getPluginManager().callEvent(armorEquipEvent)
}
}
@EventHandler
fun playerJoinEvent(event: PlayerJoinEvent) {
val armorEquipEvent = ArmorEquipEvent(event.player)
Bukkit.getPluginManager().callEvent(armorEquipEvent)
}
@EventHandler
fun playerRespawnEvent(event: PlayerRespawnEvent) {
val armorEquipEvent = ArmorEquipEvent(event.player)
Bukkit.getPluginManager().callEvent(armorEquipEvent)
}
@EventHandler
fun itemBreakEvent(event: PlayerItemBreakEvent) {
val type = ArmorType.matchType(event.brokenItem)
if (type != null) {
val p = event.player
val armorEquipEvent = ArmorEquipEvent(p)
Bukkit.getPluginManager().callEvent(armorEquipEvent)
}
}
@EventHandler
fun playerDeathEvent(event: PlayerDeathEvent) {
val p = event.entity
if (event.keepInventory) {
return
}
for (i in p.inventory.armorContents) {
if (!isAirOrNull(i)) {
Bukkit.getPluginManager().callEvent(ArmorEquipEvent(p))
}
}
}
companion object {
fun isAirOrNull(item: ItemStack?): Boolean {
return item == null || item.type == Material.AIR
}
}
}

View File

@@ -0,0 +1,27 @@
package com.willfp.eco.spigot.eventlisteners.armor
import org.bukkit.inventory.ItemStack
enum class ArmorType(val slot: Int) {
HELMET(5), CHESTPLATE(6), LEGGINGS(7), BOOTS(8);
companion object {
fun matchType(itemStack: ItemStack?): ArmorType? {
if (ArmorListener.isAirOrNull(itemStack)) {
return null
}
itemStack ?: return null
val type = itemStack.type.name
return if (type.endsWith("_HELMET") || type.endsWith("_SKULL") || type.endsWith("PLAYER_HEAD")) {
HELMET
} else if (type.endsWith("_CHESTPLATE") || type.endsWith("ELYTRA")) {
CHESTPLATE
} else if (type.endsWith("_LEGGINGS")) {
LEGGINGS
} else if (type.endsWith("_BOOTS")) {
BOOTS
} else {
null
}
}
}
}

View File

@@ -23,9 +23,7 @@ class GUIListener(private val plugin: EcoPlugin) : Listener {
return return
} }
val menu = MenuHandler.getMenu(event.clickedInventory ?: return) ?: return val menu = MenuHandler.getMenu(event.clickedInventory ?: return) ?: return
val rowColumn = MenuUtils.convertSlotToRowColumn(event.slot) val (row, column) = MenuUtils.convertSlotToRowColumn(event.slot)
val row = rowColumn.first!!
val column = rowColumn.second!!
val slot = menu.getSlot(row, column) val slot = menu.getSlot(row, column)
Validate.isTrue(slot is EcoSlot, "Slot not instance of EcoSlot!") Validate.isTrue(slot is EcoSlot, "Slot not instance of EcoSlot!")
val ecoSlot = menu.getSlot(row, column) as EcoSlot val ecoSlot = menu.getSlot(row, column) as EcoSlot
@@ -73,9 +71,7 @@ class GUIListener(private val plugin: EcoPlugin) : Listener {
val menu = MenuHandler.getMenu(inv) ?: return val menu = MenuHandler.getMenu(inv) ?: return
val rowColumn = MenuUtils.convertSlotToRowColumn(inv.firstEmpty()) val (row, column) = MenuUtils.convertSlotToRowColumn(inv.firstEmpty())
val row = rowColumn.first!!
val column = rowColumn.second!!
val slot = menu.getSlot(row, column) val slot = menu.getSlot(row, column)
if (!slot.isCaptive) { if (!slot.isCaptive) {

View File

@@ -59,4 +59,15 @@ class AntigriefCombatLogXV10 : AntigriefWrapper {
return "CombatLogX" return "CombatLogX"
} }
override fun equals(other: Any?): Boolean {
if (other !is AntigriefWrapper) {
return false
}
return other.pluginName == this.pluginName
}
override fun hashCode(): Int {
return this.pluginName.hashCode()
}
} }

View File

@@ -62,4 +62,15 @@ class AntigriefCombatLogXV11 : AntigriefWrapper {
return "CombatLogX" return "CombatLogX"
} }
override fun equals(other: Any?): Boolean {
if (other !is AntigriefWrapper) {
return false
}
return other.pluginName == this.pluginName
}
override fun hashCode(): Int {
return this.pluginName.hashCode()
}
} }

View File

@@ -64,4 +64,16 @@ class AntigriefFactionsUUID : AntigriefWrapper {
override fun getPluginName(): String { override fun getPluginName(): String {
return "FactionsUUID" return "FactionsUUID"
} }
override fun equals(other: Any?): Boolean {
if (other !is AntigriefWrapper) {
return false
}
return other.pluginName == this.pluginName
}
override fun hashCode(): Int {
return this.pluginName.hashCode()
}
} }

View File

@@ -54,4 +54,16 @@ class AntigriefGriefPrevention : AntigriefWrapper {
override fun getPluginName(): String { override fun getPluginName(): String {
return "GriefPrevention" return "GriefPrevention"
} }
override fun equals(other: Any?): Boolean {
if (other !is AntigriefWrapper) {
return false
}
return other.pluginName == this.pluginName
}
override fun hashCode(): Int {
return this.pluginName.hashCode()
}
} }

View File

@@ -68,4 +68,16 @@ class AntigriefKingdoms : AntigriefWrapper {
override fun getPluginName(): String { override fun getPluginName(): String {
return "Kingdoms" return "Kingdoms"
} }
override fun equals(other: Any?): Boolean {
if (other !is AntigriefWrapper) {
return false
}
return other.pluginName == this.pluginName
}
override fun hashCode(): Int {
return this.pluginName.hashCode()
}
} }

View File

@@ -55,4 +55,16 @@ class AntigriefLands(private val plugin: EcoPlugin) : AntigriefWrapper {
override fun getPluginName(): String { override fun getPluginName(): String {
return "Lands" return "Lands"
} }
override fun equals(other: Any?): Boolean {
if (other !is AntigriefWrapper) {
return false
}
return other.pluginName == this.pluginName
}
override fun hashCode(): Int {
return this.pluginName.hashCode()
}
} }

View File

@@ -2,9 +2,7 @@ package com.willfp.eco.spigot.integrations.antigrief
import com.palmergames.bukkit.towny.TownyAPI import com.palmergames.bukkit.towny.TownyAPI
import com.palmergames.bukkit.towny.TownyUniverse import com.palmergames.bukkit.towny.TownyUniverse
import com.palmergames.bukkit.towny.`object`.Town
import com.palmergames.bukkit.towny.`object`.TownyPermission import com.palmergames.bukkit.towny.`object`.TownyPermission
import com.palmergames.bukkit.towny.`object`.WorldCoord
import com.palmergames.bukkit.towny.utils.PlayerCacheUtil import com.palmergames.bukkit.towny.utils.PlayerCacheUtil
import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper
import org.bukkit.Location import org.bukkit.Location
@@ -67,25 +65,23 @@ class AntigriefTowny : AntigriefWrapper {
true true
} }
} }
if (victim is Player) { val townBlock = TownyAPI.getInstance().getTownBlock(victim.location) ?: return true
try { return townBlock.permissions.pvp
val town: Town = WorldCoord.parseWorldCoord(victim.getLocation()).townBlock.town
return town.isPVP
} catch (ignored: Exception) {
// If exception, no town was found, thus return true.
}
} else {
try {
val town: Town = WorldCoord.parseWorldCoord(victim.location).townBlock.town
return town.hasMobs()
} catch (ignored: Exception) {
// If exception, no town was found, thus return true.
}
}
return true
} }
override fun getPluginName(): String { override fun getPluginName(): String {
return "Towny" return "Towny"
} }
override fun equals(other: Any?): Boolean {
if (other !is AntigriefWrapper) {
return false
}
return other.pluginName == this.pluginName
}
override fun hashCode(): Int {
return this.pluginName.hashCode()
}
} }

View File

@@ -11,7 +11,9 @@ import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper
import org.apache.commons.lang.Validate import org.apache.commons.lang.Validate
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.block.Block import org.bukkit.block.Block
import org.bukkit.entity.Animals
import org.bukkit.entity.LivingEntity import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Monster
import org.bukkit.entity.Player import org.bukkit.entity.Player
class AntigriefWorldGuard : AntigriefWrapper { class AntigriefWorldGuard : AntigriefWrapper {
@@ -79,25 +81,36 @@ class AntigriefWorldGuard : AntigriefWrapper {
val localPlayer: LocalPlayer = WorldGuardPlugin.inst().wrapPlayer(player) val localPlayer: LocalPlayer = WorldGuardPlugin.inst().wrapPlayer(player)
val container: RegionContainer = WorldGuard.getInstance().platform.regionContainer val container: RegionContainer = WorldGuard.getInstance().platform.regionContainer
val query: RegionQuery = container.createQuery() val query: RegionQuery = container.createQuery()
if (victim is Player) { val flag = when(victim) {
if (!query.testBuild(BukkitAdapter.adapt(victim.getLocation()), localPlayer, Flags.PVP)) { is Player -> Flags.PVP
return WorldGuard.getInstance().platform.sessionManager.hasBypass( is Monster -> Flags.MOB_DAMAGE
localPlayer, is Animals -> Flags.DAMAGE_ANIMALS
BukkitAdapter.adapt(player.world) else -> return true
) }
}
} else { return if (!query.testBuild(BukkitAdapter.adapt(victim.location), localPlayer, flag)) {
if (!query.testBuild(BukkitAdapter.adapt(victim.location), localPlayer, Flags.DAMAGE_ANIMALS)) { WorldGuard.getInstance().platform.sessionManager.hasBypass(
return WorldGuard.getInstance().platform.sessionManager.hasBypass( localPlayer,
localPlayer, BukkitAdapter.adapt(player.world)
BukkitAdapter.adapt(player.world) )
) } else {
} true
} }
return true
} }
override fun getPluginName(): String { override fun getPluginName(): String {
return "WorldGuard" return "WorldGuard"
} }
override fun equals(other: Any?): Boolean {
if (other !is AntigriefWrapper) {
return false
}
return other.pluginName == this.pluginName
}
override fun hashCode(): Int {
return this.pluginName.hashCode()
}
} }

View File

@@ -1,34 +1,58 @@
package com.willfp.eco.spigot.integrations.customitems package com.willfp.eco.spigot.integrations.customitems
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.integrations.customitems.CustomItemsWrapper import com.willfp.eco.core.integrations.customitems.CustomItemsWrapper
import com.willfp.eco.core.items.CustomItem import com.willfp.eco.core.items.CustomItem
import com.willfp.eco.core.items.Items
import com.willfp.eco.core.items.TestableItem
import com.willfp.eco.core.items.provider.ItemProvider
import com.willfp.eco.util.NamespacedKeyUtils import com.willfp.eco.util.NamespacedKeyUtils
import me.arcaniax.hdb.api.DatabaseLoadEvent
import me.arcaniax.hdb.api.HeadDatabaseAPI import me.arcaniax.hdb.api.HeadDatabaseAPI
import me.arcaniax.hdb.enums.CategoryEnum import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.inventory.ItemStack
import java.util.function.Predicate import java.util.function.Predicate
class CustomItemsHeadDatabase : CustomItemsWrapper { class CustomItemsHeadDatabase(
private val api = HeadDatabaseAPI() plugin: EcoPlugin
) : CustomItemsWrapper {
private val provider = HeadDBProvider()
init {
plugin.eventManager.registerListener(provider)
}
override fun registerAllItems() { override fun registerAllItems() {
for (categoryEnum in CategoryEnum.values()) { Items.registerItemProvider(HeadDBProvider())
for (head in api.getHeads(categoryEnum).toList()) {
val stack = head.head
val id = head.id
val key = NamespacedKeyUtils.create("headdb", id.lowercase());
CustomItem(
key,
Predicate { test ->
val headId = api.getItemID(test) ?: return@Predicate false
headId.equals(id, ignoreCase = true)
},
stack
).register()
}
}
} }
override fun getPluginName(): String { override fun getPluginName(): String {
return "HeadDatabase" return "HeadDatabase"
} }
private inner class HeadDBProvider : ItemProvider("headdb"), Listener {
private lateinit var api: HeadDatabaseAPI
override fun provideForKey(key: String): TestableItem? {
if (this::api.isInitialized) {
return null
}
val head = api.getItemHead(key) ?: return null
val namespacedKey = NamespacedKeyUtils.create("headdb", key)
return CustomItem(
namespacedKey,
Predicate { test: ItemStack ->
val found = api.getItemID(test) ?: return@Predicate false
found == key
},
head
)
}
@EventHandler
fun onLoad(@Suppress("UNUSED_PARAMETER") event: DatabaseLoadEvent) {
api = HeadDatabaseAPI()
}
}
} }

View File

@@ -1,36 +1,39 @@
package com.willfp.eco.spigot.integrations.customitems package com.willfp.eco.spigot.integrations.customitems
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.integrations.customitems.CustomItemsWrapper import com.willfp.eco.core.integrations.customitems.CustomItemsWrapper
import com.willfp.eco.core.items.CustomItem import com.willfp.eco.core.items.CustomItem
import com.willfp.eco.core.items.Items
import com.willfp.eco.core.items.TestableItem
import com.willfp.eco.core.items.provider.ItemProvider
import com.willfp.eco.util.NamespacedKeyUtils import com.willfp.eco.util.NamespacedKeyUtils
import dev.lone.itemsadder.api.CustomStack import dev.lone.itemsadder.api.CustomStack
import dev.lone.itemsadder.api.ItemsAdder
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.util.function.Predicate import java.util.function.Predicate
class CustomItemsItemsAdder( class CustomItemsItemsAdder : CustomItemsWrapper {
private val plugin: EcoPlugin
) : CustomItemsWrapper {
override fun registerAllItems() { override fun registerAllItems() {
plugin.scheduler.runLater({ Items.registerItemProvider(ItemsAdderProvider())
for (item in ItemsAdder.getAllItems()) {
val stack = item.itemStack
val id = item.id
val key = NamespacedKeyUtils.create("itemsadder", id.lowercase())
CustomItem(
key,
Predicate { test: ItemStack ->
val customStack = CustomStack.byItemStack(test) ?: return@Predicate false
customStack.id.equals(id, ignoreCase = true)
},
stack
).register()
}
}, 2)
} }
override fun getPluginName(): String { override fun getPluginName(): String {
return "ItemsAdder" return "ItemsAdder"
} }
private class ItemsAdderProvider : ItemProvider("itemsadder") {
override fun provideForKey(key: String): TestableItem? {
val item = CustomStack.getInstance("itemsadder:$key") ?: return null
val id = item.id
val namespacedKey = NamespacedKeyUtils.create("itemsadder", key)
val stack = item.itemStack
return CustomItem(
namespacedKey,
Predicate { test: ItemStack ->
val customStack = CustomStack.byItemStack(test) ?: return@Predicate false
customStack.id.equals(id, ignoreCase = true)
},
stack
)
}
}
} }

View File

@@ -6,13 +6,17 @@ import com.willfp.eco.util.NamespacedKeyUtils
import io.th0rgal.oraxen.items.OraxenItems import io.th0rgal.oraxen.items.OraxenItems
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.util.*
import java.util.function.Predicate import java.util.function.Predicate
class CustomItemsOraxen : CustomItemsWrapper { class CustomItemsOraxen : CustomItemsWrapper {
override fun registerAllItems() { override fun registerAllItems() {
for (item in OraxenItems.getItems()) { for (item in OraxenItems.getItems()) {
val stack = item.build() val stack = item.build()
val id: String = OraxenItems.getIdByItem(item) val id: String = Objects.requireNonNullElse(OraxenItems.getIdByItem(item), "")
if (id.isEmpty()) {
continue
}
val key: NamespacedKey = NamespacedKeyUtils.create("oraxen", id.lowercase()) val key: NamespacedKey = NamespacedKeyUtils.create("oraxen", id.lowercase())
CustomItem( CustomItem(
key, Predicate { test: ItemStack -> key, Predicate { test: ItemStack ->

View File

@@ -28,4 +28,8 @@ class ShopShopGuiPlus : ShopWrapper {
return Items.getCustomItem(itemStack1)?.key == Items.getCustomItem(itemStack2)?.key return Items.getCustomItem(itemStack1)?.key == Items.getCustomItem(itemStack2)?.key
} }
} }
override fun getPluginName(): String {
return "ShopGUIPlus"
}
} }

View File

@@ -14,4 +14,9 @@ use-fast-collated-drops: true
# bStats is important and you should keep it enabled. # bStats is important and you should keep it enabled.
# This option is only here because of compliance with data protection laws. # This option is only here because of compliance with data protection laws.
enable-bstats: true enable-bstats: true
# Some plugins use their own item display systems (eg Triton)
# And must be ran after eco. Don't enable this unless you run a conflicting plugin
# and have been told to enable it.
use-lower-protocollib-priority: false

View File

@@ -21,13 +21,15 @@ softdepend:
- PlaceholderAPI - PlaceholderAPI
- mcMMO - mcMMO
- CombatLogX - CombatLogX
- ShopGuiPlus - ShopGUIPlus
- ItemsAdder - ItemsAdder
- Oraxen - Oraxen
- HeadDatabase - HeadDatabase
libraries: libraries:
- org.reflections:reflections:0.9.12 - 'org.reflections:reflections:0.9.12'
- org.apache.maven:maven-artifact:3.0.3 - 'org.apache.maven:maven-artifact:3.0.3'
- net.kyori:adventure-text-serializer-gson:4.8.1 - 'org.jetbrains.kotlin:kotlin-stdlib:1.5.31'
- net.kyori:adventure-text-serializer-legacy:4.8.1 - 'net.kyori:adventure-platform-bukkit:4.0.0'
- org.jetbrains.kotlin:kotlin-stdlib:1.5.21 - 'net.kyori:adventure-api:4.9.1'
- 'net.kyori:adventure-text-serializer-gson:4.9.2'
- 'net.kyori:adventure-text-serializer-legacy:4.8.1'

View File

@@ -2,5 +2,5 @@ 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'
} }

View File

@@ -7,5 +7,5 @@ interface ChatComponentProxy : AbstractProxy {
fun modifyComponent( fun modifyComponent(
obj: Any, obj: Any,
player: Player player: Player
): Any? ): Any
} }

View File

@@ -1,2 +1,2 @@
version = 6.7.2 version = 6.10.0
plugin-name = eco plugin-name = eco