Compare commits

..

70 Commits

Author SHA1 Message Date
Auxilor
2eb350977c Updated to 6.11.2 2021-10-26 19:51:21 +01:00
Auxilor
8a89a63c5f PacketSetCreativeSlot and PacketSetSlot now clear frames 2021-10-26 19:51:06 +01:00
Auxilor
5c26e6e782 DisplayFrames now include the ItemStacks as well as the hashes: larger memory footprint should be fine with ttl and frequent clearing 2021-10-26 19:49:49 +01:00
Auxilor
f88b914fa6 Fixed gradient modifier issues 2021-10-26 19:41:38 +01:00
Auxilor
15ff6b3ea3 Merge branch 'master' into develop 2021-10-26 19:28:37 +01:00
Auxilor
b14eed696c Added alice anticheat support 2021-10-26 19:21:34 +01:00
Auxilor
cffae33c87 StringUtils change 2021-10-26 19:11:01 +01:00
Auxilor
adf6d1c800 Updated to 6.11.1 2021-10-15 10:27:58 +01:00
Auxilor
2b7c8962e7 Merge remote-tracking branch 'origin/master' 2021-10-15 10:27:51 +01:00
Auxilor
b60cbfce2c Fixed unpredicatable config behaviour 2021-10-15 10:27:44 +01:00
Auxilor
910ad18703 Updated towny 2021-10-15 10:25:32 +01:00
Auxilor
8a4a71ebc1 Updated lands integration 2021-10-15 10:24:18 +01:00
Will FP
2e748b1723 Update README.md 2021-10-12 20:12:09 +01:00
Auxilor
cb28726bc3 Cleaned up Multiverse-Inventories integration 2021-10-12 12:04:52 +01:00
Auxilor
c0c20d63bb Merge remote-tracking branch 'origin/master' into develop 2021-10-12 11:59:26 +01:00
Will FP
3b11610c45 Merge pull request #44
Multiverse-Inventories integration
2021-10-12 11:58:41 +01:00
Auxilor
232048022e Added extra config constructors 2021-10-12 11:51:22 +01:00
Auxilor
9abfe0ab01 Updated to 6.11.0 2021-10-12 11:36:07 +01:00
Auxilor
e7ac05278c Added lots of display frame options 2021-10-12 11:31:02 +01:00
Auxilor
85ba40c279 Added PluginLike, allowing extensions to have their own configs 2021-10-12 11:17:58 +01:00
_OfTeN_
1acf86492e Added Multiverse-Inventories integration (additional ArmorChangeEvent call for all effect to reapply for new players inventory. 2021-10-12 11:09:09 +03:00
Auxilor
4609d38389 Updated to 6.10.1 2021-10-08 10:50:57 +01:00
Auxilor
2d6836cc93 Moved frames to only affect player inventories 2021-10-08 10:50:47 +01:00
Auxilor
8e21617345 Finished up ChatComponent 2021-10-07 20:50:15 +01:00
Auxilor
2f99a17d02 TODO: Finish Components 2021-10-07 16:16:07 +01:00
Auxilor
34edf1d7b4 Switched mapChildrenDeep to mapChildren 2021-10-07 16:01:49 +01:00
Auxilor
be85ba5706 Fixed Stack Overflow 2021-10-07 15:44:59 +01:00
Auxilor
b817b00ca4 Updated ChatComponent to include siblings 2021-10-07 15:37:35 +01:00
Auxilor
ee02528abc Downgraded Reflections 2021-10-07 15:07:24 +01:00
Auxilor
794948c8f9 Altered Reflections constructor (again) 2021-10-07 15:01:35 +01:00
Auxilor
7c70dec2e7 Added AntigriefManager#unregister 2021-10-07 15:00:54 +01:00
Auxilor
d1f20b7111 Updated Reflections constructor 2021-10-07 14:49:52 +01:00
Auxilor
595751a094 Fixed build warnings 2021-10-07 14:45:42 +01:00
Auxilor
8231afdcbf Fixed dependency-related issues (Reflections) 2021-10-07 14:39:44 +01:00
Auxilor
4f55d66096 Updated to 6.10.0 2021-10-07 14:36:03 +01:00
Auxilor
d350febbdc Minor change 2021-10-07 14:35:52 +01:00
Auxilor
78755b0e9a (Hopefully) massively optimized display (PacketWindowItems) with DisplayFrame.kt 2021-10-07 14:34:40 +01:00
Auxilor
63d7bdab6b Re-Added Head Database integration 2021-10-07 13:58:42 +01:00
Auxilor
344032b7e3 Added ItemProvider 2021-10-07 13:45:45 +01:00
Auxilor
3ae5c8a72c Moved ArmorEquipEvent code to kotlin, finally 2021-10-07 13:13:33 +01:00
Auxilor
e4f2bc2e39 Finally recoded remaining java in NMS to kotlin 2021-10-07 13:03:19 +01:00
Auxilor
90ba0a0391 Updated dependencies 2021-10-07 12:50:53 +01:00
Auxilor
801a3cd4f9 Merge remote-tracking branch 'origin/master' 2021-10-07 12:48:44 +01:00
Will FP
ce9cada75a Merge pull request #35
Bump ProtocolLib from 4.6.0-SNAPSHOT to 4.7.1-SNAPSHOT
2021-10-07 12:48:24 +01:00
Will FP
ae551dd0f7 Merge pull request #36
Bump junit-jupiter-engine from 5.3.1 to 5.8.1
2021-10-07 12:47:38 +01:00
Will FP
1b3dd53fb8 Merge pull request #37
Bump reflections from 0.9.12 to 0.10.1
2021-10-07 12:47:29 +01:00
Will FP
dda4224e6e Merge pull request #38
Bump lombok from 1.18.20 to 1.18.22
2021-10-07 12:47:19 +01:00
dependabot[bot]
6e14265655 Bump lombok from 1.18.20 to 1.18.22
Bumps [lombok](https://github.com/projectlombok/lombok) from 1.18.20 to 1.18.22.
- [Release notes](https://github.com/projectlombok/lombok/releases)
- [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown)
- [Commits](https://github.com/projectlombok/lombok/compare/v1.18.20...v1.18.22)

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

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

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

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

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

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

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

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

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

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-04 21:34:25 +00:00
Auxilor
a018a1fca5 Cleaned up dependencies 2021-10-03 18:57:52 +01:00
Auxilor
8a7b8f2b03 Cleaned up dependencies 2021-10-03 18:56:56 +01:00
Auxilor
abf3dc1e9e Updated to 6.9.4 2021-10-03 18:56:27 +01:00
Auxilor
e92cc41be6 Fixed BukkitAudiences bug on outdated versions of paper 2021-10-03 17:37:45 +01:00
Auxilor
49570c841b Reverted publication changes 2021-10-03 13:00:01 +01:00
Auxilor
9aa465844d Finally fixed Adventure + MiniMessage shading / Dependency issues 2021-10-03 12:54:38 +01:00
Auxilor
a692fbee01 Moved Adventure to api implementation, Removed GriefDefender 2021-10-03 11:51:55 +01:00
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
77 changed files with 1266 additions and 869 deletions

View File

@@ -1,6 +1,6 @@
<h1 align="center"> <h1 align="center">
<br> <br>
<img src="https://i.imgur.com/p5uR2Qp.png" alt="eco logo" width="256"> <img src="https://i.imgur.com/kU3ejCt.png" alt="eco logo" width="256">
<br> <br>
</h1> </h1>

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,8 +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.adventure.minimessage') relocate('net.kyori.adventure.text.minimessage', 'com.willfp.eco.shaded.minimessage')
relocate('net.kyori.adventure.platform', 'com.willfp.eco.shaded.adventure.platform')
} }
jar { jar {

View File

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

View File

@@ -52,7 +52,7 @@ import java.util.stream.Collectors;
* be cancelled.</b> * be cancelled.</b>
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public abstract class EcoPlugin extends JavaPlugin { public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
/** /**
* The polymart resource ID of the plugin. * The polymart resource ID of the plugin.
*/ */

View File

@@ -210,6 +210,6 @@ public interface Handler {
* *
* @return The audiences. * @return The audiences.
*/ */
@NotNull @Nullable
BukkitAudiences getAdventure(); BukkitAudiences getAdventure();
} }

View File

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

View File

@@ -2,8 +2,8 @@ package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper; import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
@@ -20,7 +20,7 @@ public abstract class JSONBaseConfig extends LoadableJSONConfigWrapper {
*/ */
protected JSONBaseConfig(@NotNull final String configName, protected JSONBaseConfig(@NotNull final String configName,
final boolean removeUnused, final boolean removeUnused,
@NotNull final EcoPlugin plugin, @NotNull final PluginLike plugin,
@NotNull final String... updateBlacklist) { @NotNull final String... updateBlacklist) {
super( super(
Eco.getHandler().getConfigFactory().createUpdatableJSONConfig( Eco.getHandler().getConfigFactory().createUpdatableJSONConfig(
@@ -40,7 +40,7 @@ public abstract class JSONBaseConfig extends LoadableJSONConfigWrapper {
*/ */
protected JSONBaseConfig(@NotNull final String configName, protected JSONBaseConfig(@NotNull final String configName,
final boolean removeUnused, final boolean removeUnused,
@NotNull final EcoPlugin plugin) { @NotNull final PluginLike plugin) {
super( super(
Eco.getHandler().getConfigFactory().createUpdatableJSONConfig( Eco.getHandler().getConfigFactory().createUpdatableJSONConfig(
configName, configName,
@@ -51,4 +51,28 @@ 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) {
this(configName, removeUnused, (PluginLike) plugin, updateBlacklist);
}
/**
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
*/
protected JSONBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin) {
this(configName, removeUnused, (PluginLike) plugin);
}
} }

View File

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

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper; import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -18,7 +19,20 @@ public abstract class JSONStaticBaseConfig extends LoadableJSONConfigWrapper {
* @param plugin The plugin. * @param plugin The plugin.
*/ */
protected JSONStaticBaseConfig(@NotNull final String configName, protected JSONStaticBaseConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin) { @NotNull final PluginLike plugin) {
super(Eco.getHandler().getConfigFactory().createLoadableJSONConfig(configName, plugin, "", plugin.getClass())); super(Eco.getHandler().getConfigFactory().createLoadableJSONConfig(configName, plugin, "", plugin.getClass()));
} }
/**
* Config implementation for configs present in the plugin's base directory (eg config.json, lang.json).
* <p>
* Does not automatically update.
*
* @param configName The name of the config
* @param plugin The plugin.
*/
protected JSONStaticBaseConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin) {
this(configName, (PluginLike) plugin);
}
} }

View File

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

View File

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

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.config.yaml;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper; import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -19,7 +20,7 @@ public abstract class YamlBaseConfig extends LoadableYamlConfigWrapper {
*/ */
protected YamlBaseConfig(@NotNull final String configName, protected YamlBaseConfig(@NotNull final String configName,
final boolean removeUnused, final boolean removeUnused,
@NotNull final EcoPlugin plugin, @NotNull final PluginLike plugin,
@NotNull final String... updateBlacklist) { @NotNull final String... updateBlacklist) {
super( super(
Eco.getHandler().getConfigFactory().createUpdatableYamlConfig( Eco.getHandler().getConfigFactory().createUpdatableYamlConfig(
@@ -39,7 +40,7 @@ public abstract class YamlBaseConfig extends LoadableYamlConfigWrapper {
*/ */
protected YamlBaseConfig(@NotNull final String configName, protected YamlBaseConfig(@NotNull final String configName,
final boolean removeUnused, final boolean removeUnused,
@NotNull final EcoPlugin plugin) { @NotNull final PluginLike plugin) {
super( super(
Eco.getHandler().getConfigFactory().createUpdatableYamlConfig( Eco.getHandler().getConfigFactory().createUpdatableYamlConfig(
configName, configName,
@@ -50,4 +51,28 @@ public abstract class YamlBaseConfig extends LoadableYamlConfigWrapper {
) )
); );
} }
/**
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
* @param updateBlacklist Substring of keys to not add/remove keys for.
*/
protected YamlBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin,
@NotNull final String... updateBlacklist) {
this(configName, removeUnused, (PluginLike) plugin, updateBlacklist);
}
/**
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
*/
protected YamlBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin) {
this(configName, removeUnused, (PluginLike) plugin);
}
} }

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.config.yaml;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper; import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -25,7 +26,7 @@ public abstract class YamlExtendableConfig extends LoadableYamlConfigWrapper {
*/ */
protected YamlExtendableConfig(@NotNull final String configName, protected YamlExtendableConfig(@NotNull final String configName,
final boolean removeUnused, final boolean removeUnused,
@NotNull final EcoPlugin plugin, @NotNull final PluginLike plugin,
@NotNull final Class<?> source, @NotNull final Class<?> source,
@NotNull final String subDirectoryPath, @NotNull final String subDirectoryPath,
@NotNull final String... updateBlacklist) { @NotNull final String... updateBlacklist) {
@@ -40,4 +41,20 @@ public abstract class YamlExtendableConfig extends LoadableYamlConfigWrapper {
) )
); );
} }
/**
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
* @param updateBlacklist Substring of keys to not add/remove keys for.
* @param subDirectoryPath The subdirectory path.
* @param source The class that owns the resource.
*/
protected YamlExtendableConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin,
@NotNull final Class<?> source,
@NotNull final String subDirectoryPath,
@NotNull final String... updateBlacklist) {
this(configName, removeUnused, (PluginLike) plugin, source, subDirectoryPath, updateBlacklist);
}
} }

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.config.yaml;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginLike;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper; import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -18,7 +19,20 @@ public abstract class YamlStaticBaseConfig extends LoadableYamlConfigWrapper {
* @param plugin The plugin. * @param plugin The plugin.
*/ */
protected YamlStaticBaseConfig(@NotNull final String configName, protected YamlStaticBaseConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin) { @NotNull final PluginLike plugin) {
super(Eco.getHandler().getConfigFactory().createLoadableYamlConfig(configName, plugin, "", plugin.getClass())); super(Eco.getHandler().getConfigFactory().createLoadableYamlConfig(configName, plugin, "", plugin.getClass()));
} }
/**
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
* <p>
* Does not automatically update.
*
* @param configName The name of the config
* @param plugin The plugin.
*/
protected YamlStaticBaseConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin) {
this(configName, (PluginLike) plugin);
}
} }

View File

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

View File

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

@@ -1,8 +1,10 @@
package com.willfp.eco.util; package com.willfp.eco.util;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.Prerequisite;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -20,7 +22,21 @@ public class PlayerUtils {
*/ */
@NotNull @NotNull
public Audience getAudience(@NotNull final Player player) { public Audience getAudience(@NotNull final Player player) {
return Eco.getHandler().getAdventure().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);
}
}
} }
/** /**
@@ -31,6 +47,20 @@ public class PlayerUtils {
*/ */
@NotNull @NotNull
public Audience getAudience(@NotNull final CommandSender sender) { public Audience getAudience(@NotNull final CommandSender sender) {
return Eco.getHandler().getAdventure().sender(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,6 +1,8 @@
package com.willfp.eco.util; package com.willfp.eco.util;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.willfp.eco.core.Prerequisite;
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager; import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@@ -18,11 +20,17 @@ 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;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static net.md_5.bungee.api.ChatColor.BOLD;
import static net.md_5.bungee.api.ChatColor.COLOR_CHAR; import static net.md_5.bungee.api.ChatColor.COLOR_CHAR;
import static net.md_5.bungee.api.ChatColor.ITALIC;
import static net.md_5.bungee.api.ChatColor.MAGIC;
import static net.md_5.bungee.api.ChatColor.STRIKETHROUGH;
import static net.md_5.bungee.api.ChatColor.UNDERLINE;
/** /**
* Utilities / API methods for strings. * Utilities / API methods for strings.
@@ -60,6 +68,22 @@ public class StringUtils {
.hexColors() .hexColors()
.build(); .build();
/**
* Color map.
*/
private static final Map<String, ChatColor> COLOR_MAP = new ImmutableMap.Builder<String, ChatColor>()
.put("&l", BOLD)
.put("&o", ITALIC)
.put("&n", UNDERLINE)
.put("&m", STRIKETHROUGH)
.put("&k", MAGIC)
.put("§l", BOLD)
.put("§o", ITALIC)
.put("§n", UNDERLINE)
.put("§m", STRIKETHROUGH)
.put("§k", MAGIC)
.build();
/** /**
* Format a list of strings. * Format a list of strings.
* <p> * <p>
@@ -250,10 +274,12 @@ public class StringUtils {
if (option == FormatOption.WITH_PLACEHOLDERS) { if (option == FormatOption.WITH_PLACEHOLDERS) {
processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, player); processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, player);
} }
processedMessage = translateGradients(processedMessage);
processedMessage = translateMiniMessage(processedMessage);
processedMessage = translateHexColorCodes(processedMessage);
processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage); processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage);
processedMessage = translateGradients(processedMessage);
processedMessage = translateHexColorCodes(processedMessage);
if (Prerequisite.HAS_PAPER.isMet()) {
processedMessage = translateMiniMessage(processedMessage);
}
return processedMessage; return processedMessage;
} }
@@ -290,26 +316,12 @@ public class StringUtils {
@NotNull final Color end) { @NotNull final Color end) {
String processedString = string; String processedString = string;
List<ChatColor> modifiers = new ArrayList<>(); List<ChatColor> modifiers = new ArrayList<>();
if (processedString.contains("&l")) { for (Map.Entry<String, ChatColor> entry : COLOR_MAP.entrySet()) {
modifiers.add(ChatColor.BOLD); if (processedString.contains(entry.getKey())) {
modifiers.add(entry.getValue());
}
processedString = processedString.replace(entry.getKey(), "");
} }
if (processedString.contains("&o")) {
modifiers.add(ChatColor.ITALIC);
}
if (processedString.contains("&n")) {
modifiers.add(ChatColor.UNDERLINE);
}
if (processedString.contains("&m")) {
modifiers.add(ChatColor.STRIKETHROUGH);
}
if (processedString.contains("&k")) {
modifiers.add(ChatColor.MAGIC);
}
processedString = processedString.replace("&l", "");
processedString = processedString.replace("&o", "");
processedString = processedString.replace("&n", "");
processedString = processedString.replace("&k", "");
processedString = processedString.replace("&m", "");
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
ChatColor[] colors = getGradientColors(start, end, processedString.length()); ChatColor[] colors = getGradientColors(start, end, processedString.length());

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"
} }
} }
@@ -18,4 +18,12 @@ subprojects {
compileOnly project(":eco-api") compileOnly project(":eco-api")
compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.5.31' compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.5.31'
} }
compileKotlin {
kotlinOptions {
jvmTarget = "16"
}
targetCompatibility = JavaVersion.VERSION_16
sourceCompatibility = JavaVersion.VERSION_16
}
} }

View File

@@ -1,6 +1,7 @@
package com.willfp.eco.internal.config package com.willfp.eco.internal.config
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.PluginLike
import com.willfp.eco.core.config.interfaces.Config import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.core.config.interfaces.JSONConfig import com.willfp.eco.core.config.interfaces.JSONConfig
import com.willfp.eco.core.config.wrapper.ConfigFactory import com.willfp.eco.core.config.wrapper.ConfigFactory
@@ -15,7 +16,7 @@ import org.bukkit.configuration.file.YamlConfiguration
class EcoConfigFactory : ConfigFactory { class EcoConfigFactory : ConfigFactory {
override fun createUpdatableYamlConfig( override fun createUpdatableYamlConfig(
configName: String, configName: String,
plugin: EcoPlugin, plugin: PluginLike,
subDirectoryPath: String, subDirectoryPath: String,
source: Class<*>, source: Class<*>,
removeUnused: Boolean, removeUnused: Boolean,
@@ -33,7 +34,7 @@ class EcoConfigFactory : ConfigFactory {
override fun createUpdatableJSONConfig( override fun createUpdatableJSONConfig(
configName: String, configName: String,
plugin: EcoPlugin, plugin: PluginLike,
subDirectoryPath: String, subDirectoryPath: String,
source: Class<*>, source: Class<*>,
removeUnused: Boolean, removeUnused: Boolean,
@@ -51,7 +52,7 @@ class EcoConfigFactory : ConfigFactory {
override fun createLoadableJSONConfig( override fun createLoadableJSONConfig(
configName: String, configName: String,
plugin: EcoPlugin, plugin: PluginLike,
subDirectoryPath: String, subDirectoryPath: String,
source: Class<*> source: Class<*>
): JSONConfig { ): JSONConfig {
@@ -65,7 +66,7 @@ class EcoConfigFactory : ConfigFactory {
override fun createLoadableYamlConfig( override fun createLoadableYamlConfig(
configName: String, configName: String,
plugin: EcoPlugin, plugin: PluginLike,
subDirectoryPath: String, subDirectoryPath: String,
source: Class<*> source: Class<*>
): Config { ): Config {

View File

@@ -4,7 +4,6 @@ import com.google.gson.Gson
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.willfp.eco.core.config.interfaces.JSONConfig import com.willfp.eco.core.config.interfaces.JSONConfig
import com.willfp.eco.util.StringUtils import com.willfp.eco.util.StringUtils
import org.apache.commons.lang.Validate
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@@ -124,8 +123,7 @@ open class EcoJSONConfigWrapper : JSONConfig {
override fun getSubsection(path: String): JSONConfig { override fun getSubsection(path: String): JSONConfig {
val subsection = getSubsectionOrNull(path) val subsection = getSubsectionOrNull(path)
Validate.notNull(subsection) return subsection ?: EcoJSONConfigSection(emptyMap())
return subsection!!
} }
override fun getSubsectionOrNull(path: String): JSONConfig? { override fun getSubsectionOrNull(path: String): JSONConfig? {

View File

@@ -1,8 +1,7 @@
package com.willfp.eco.internal.config.json package com.willfp.eco.internal.config.json
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.PluginLike
import com.willfp.eco.core.config.interfaces.LoadableConfig import com.willfp.eco.core.config.interfaces.LoadableConfig
import org.jetbrains.annotations.NotNull
import java.io.* import java.io.*
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.StandardOpenOption import java.nio.file.StandardOpenOption
@@ -10,7 +9,7 @@ import java.nio.file.StandardOpenOption
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
open class EcoLoadableJSONConfig( open class EcoLoadableJSONConfig(
configName: String, configName: String,
private val plugin: EcoPlugin, private val plugin: PluginLike,
private val subDirectoryPath: String, private val subDirectoryPath: String,
val source: Class<*> val source: Class<*>
) : EcoJSONConfigWrapper(), LoadableConfig { ) : EcoJSONConfigWrapper(), LoadableConfig {

View File

@@ -1,6 +1,6 @@
package com.willfp.eco.internal.config.json package com.willfp.eco.internal.config.json
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.PluginLike
import org.bukkit.configuration.InvalidConfigurationException import org.bukkit.configuration.InvalidConfigurationException
import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.configuration.file.YamlConfiguration
import java.io.BufferedReader import java.io.BufferedReader
@@ -10,7 +10,7 @@ import java.nio.charset.StandardCharsets
open class EcoUpdatableJSONConfig( open class EcoUpdatableJSONConfig(
configName: String, configName: String,
plugin: EcoPlugin, plugin: PluginLike,
subDirectoryPath: String, subDirectoryPath: String,
source: Class<*>, source: Class<*>,
private val removeUnused: Boolean, private val removeUnused: Boolean,

View File

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

View File

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

View File

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

View File

@@ -2,7 +2,6 @@ package com.willfp.eco.internal.config.yaml
import com.willfp.eco.core.config.interfaces.Config import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.util.StringUtils import com.willfp.eco.util.StringUtils
import org.apache.commons.lang.Validate
import org.bukkit.configuration.ConfigurationSection import org.bukkit.configuration.ConfigurationSection
import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.configuration.file.YamlConfiguration
import java.io.StringReader import java.io.StringReader
@@ -52,8 +51,7 @@ open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
override fun getSubsection(path: String): Config { override fun getSubsection(path: String): Config {
val subsection = getSubsectionOrNull(path) val subsection = getSubsectionOrNull(path)
Validate.notNull(subsection) return subsection ?: EcoYamlConfigSection(YamlConfiguration())
return subsection!!
} }
override fun getSubsectionOrNull(path: String): Config? { override fun getSubsectionOrNull(path: String): Config? {

View File

@@ -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,31 +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' implementation('net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT') {
implementation 'net.kyori:adventure-platform-bukkit:4.0.0' 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-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'
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.1-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.17.1' 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.97.1.0' compileOnly 'com.github.TownyAdvanced:Towny:0.97.2.6'
compileOnly 'com.github.angeschossen:LandsAPI:4.7.3' compileOnly 'com.github.angeschossen:LandsAPI:5.15.2'
compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT' compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT'
compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd' compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd'
compileOnly 'com.gmail.nossr50.mcMMO:mcMMO:2.1.157' compileOnly 'com.gmail.nossr50.mcMMO:mcMMO:2.1.202'
compileOnly 'me.clip:placeholderapi:2.10.10' compileOnly 'me.clip:placeholderapi:2.10.10'
compileOnly 'com.willfp:Oraxen:e1f4003d8d' compileOnly 'com.github.oraxen:oraxen:bd81ace154'
compileOnly 'com.github.brcdev-minecraft:shopgui-api:2.2.0' compileOnly 'com.github.brcdev-minecraft:shopgui-api:2.2.0'
compileOnly 'com.github.LoneDev6:API-ItemsAdder:2.4.7' compileOnly 'com.github.LoneDev6:API-ItemsAdder:2.4.7'
compileOnly 'me.arcaniax:HeadDatabase-API:1.2.0' compileOnly 'com.arcaniax:HeadDatabase-API:1.3.0'
// 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

@@ -43,7 +43,7 @@ import java.util.logging.Logger
class EcoHandler : EcoSpigotPlugin(), Handler { class EcoHandler : EcoSpigotPlugin(), Handler {
private val cleaner = EcoCleaner() private val cleaner = EcoCleaner()
private val requirementFactory = EcoRequirementFactory() private val requirementFactory = EcoRequirementFactory()
private lateinit var adventure: BukkitAudiences private var adventure: BukkitAudiences? = null
override fun createScheduler(plugin: EcoPlugin): Scheduler { override fun createScheduler(plugin: EcoPlugin): Scheduler {
return EcoScheduler(plugin) return EcoScheduler(plugin)
@@ -129,7 +129,7 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
return requirementFactory return requirementFactory
} }
override fun getAdventure(): BukkitAudiences { override fun getAdventure(): BukkitAudiences? {
return adventure return adventure
} }

View File

@@ -3,6 +3,7 @@ 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.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
@@ -20,14 +21,21 @@ import com.willfp.eco.proxy.FastItemStackFactoryProxy
import com.willfp.eco.proxy.SkullProxy 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.display.frame.clearFrames
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.*
import com.willfp.eco.spigot.integrations.customitems.CustomItemsHeadDatabase
import com.willfp.eco.spigot.integrations.customitems.CustomItemsItemsAdder import com.willfp.eco.spigot.integrations.customitems.CustomItemsItemsAdder
import com.willfp.eco.spigot.integrations.customitems.CustomItemsOraxen import com.willfp.eco.spigot.integrations.customitems.CustomItemsOraxen
import com.willfp.eco.spigot.integrations.mcmmo.McmmoIntegrationImpl import com.willfp.eco.spigot.integrations.mcmmo.McmmoIntegrationImpl
import com.willfp.eco.spigot.integrations.multiverseinventories.MultiverseInventoriesIntegration
import com.willfp.eco.spigot.integrations.shop.ShopShopGuiPlus 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
@@ -69,7 +77,10 @@ abstract class EcoSpigotPlugin : EcoPlugin(
override fun handleEnable() { override fun handleEnable() {
CollatedRunnable(this) CollatedRunnable(this)
(Eco.getHandler() as EcoHandler).adventure = BukkitAudiences.create(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!")
@@ -91,12 +102,17 @@ abstract class EcoSpigotPlugin : EcoPlugin(
} }
override fun handleDisable() { override fun handleDisable() {
Eco.getHandler().adventure.close() Eco.getHandler().adventure?.close()
} }
override fun handleReload() { override fun handleReload() {
CollatedRunnable(this) CollatedRunnable(this)
DropManager.update(this) DropManager.update(this)
this.scheduler.runTimer(
{ clearFrames() },
this.configYml.getInt("display-frame-ttl").toLong(),
this.configYml.getInt("display-frame-ttl").toLong()
)
} }
override fun handleAfterLoad() { override fun handleAfterLoad() {
@@ -109,7 +125,6 @@ abstract class EcoSpigotPlugin : EcoPlugin(
// AntiGrief // AntiGrief
IntegrationLoader("WorldGuard") { AntigriefManager.register(AntigriefWorldGuard()) }, IntegrationLoader("WorldGuard") { AntigriefManager.register(AntigriefWorldGuard()) },
IntegrationLoader("GriefPrevention") { AntigriefManager.register(AntigriefGriefPrevention()) }, IntegrationLoader("GriefPrevention") { AntigriefManager.register(AntigriefGriefPrevention()) },
IntegrationLoader("GriefDefender") { AntigriefManager.register(AntigriefGriefDefender()) },
IntegrationLoader("FactionsUUID") { AntigriefManager.register(AntigriefFactionsUUID()) }, IntegrationLoader("FactionsUUID") { AntigriefManager.register(AntigriefFactionsUUID()) },
IntegrationLoader("Towny") { AntigriefManager.register(AntigriefTowny()) }, IntegrationLoader("Towny") { AntigriefManager.register(AntigriefTowny()) },
IntegrationLoader("Lands") { AntigriefManager.register(AntigriefLands(this)) }, IntegrationLoader("Lands") { AntigriefManager.register(AntigriefLands(this)) },
@@ -132,16 +147,19 @@ abstract class EcoSpigotPlugin : EcoPlugin(
IntegrationLoader("NoCheatPlus") { AnticheatManager.register(this, AnticheatNCP()) }, IntegrationLoader("NoCheatPlus") { AnticheatManager.register(this, AnticheatNCP()) },
IntegrationLoader("Spartan") { AnticheatManager.register(this, AnticheatSpartan()) }, IntegrationLoader("Spartan") { AnticheatManager.register(this, AnticheatSpartan()) },
IntegrationLoader("Vulcan") { AnticheatManager.register(this, AnticheatVulcan()) }, IntegrationLoader("Vulcan") { AnticheatManager.register(this, AnticheatVulcan()) },
IntegrationLoader("Alice") { AnticheatManager.register(this, AnticheatAlice()) },
// 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(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()) },
IntegrationLoader("Multiverse-Inventories") { this.eventManager.registerListener(MultiverseInventoriesIntegration(this)) }
) )
} }
@@ -160,7 +178,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

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

View File

@@ -6,6 +6,8 @@ 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.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
@@ -21,5 +23,7 @@ class PacketSetCreativeSlot(plugin: EcoPlugin) :
itemStack!! itemStack!!
) )
} }
player.lastDisplayFrame = DisplayFrame.EMPTY
} }
} }

View File

@@ -6,6 +6,8 @@ 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.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
@@ -20,5 +22,7 @@ class PacketSetSlot(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, PacketTyp
item!!, player item!!, player
) )
} }
player.lastDisplayFrame = DisplayFrame.EMPTY
} }
} }

View File

@@ -6,9 +6,12 @@ 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.HashedItem
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(
@@ -16,15 +19,43 @@ class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packe
player: Player, player: Player,
event: PacketEvent event: PacketEvent
) { ) {
packet.itemListModifier.modify(0) { itemStacks: List<ItemStack>? -> val windowId = packet.integers.read(0)
if (windowId != 0) {
player.lastDisplayFrame = DisplayFrame.EMPTY
}
packet.itemListModifier.modify(0) { itemStacks: MutableList<ItemStack>? ->
if (itemStacks == null) { if (itemStacks == null) {
return@modify null return@modify null
} }
itemStacks.forEach(Consumer { item: ItemStack ->
Display.display( if (this.getPlugin().configYml.getBool("use-display-frame") && windowId == 0) {
item, player val frameMap = mutableMapOf<Byte, HashedItem>()
)
}) for (index in itemStacks.indices) {
frameMap[index.toByte()] =
HashedItem(FastItemStack.wrap(itemStacks[index]).hashCode(), itemStacks[index])
}
val newFrame = DisplayFrame(frameMap)
val lastFrame = player.lastDisplayFrame
player.lastDisplayFrame = newFrame
val changes = lastFrame.getChangedSlots(newFrame)
for (index in changes) {
Display.display(itemStacks[index.toInt()], player)
}
for (index in (itemStacks.indices subtract changes)) {
itemStacks[index.toInt()] = lastFrame.getItem(index.toByte()) ?: itemStacks[index.toInt()]
}
} else {
itemStacks.forEach { Display.display(it, player) }
}
itemStacks itemStacks
} }
} }

View File

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

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

@@ -0,0 +1,33 @@
package com.willfp.eco.spigot.integrations.anticheat
import com.willfp.eco.core.integrations.anticheat.AnticheatWrapper
import me.nik.alice.api.events.AliceViolationEvent
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
import java.util.*
class AnticheatAlice : AnticheatWrapper, Listener {
private val exempt: MutableSet<UUID> = HashSet()
override fun getPluginName(): String {
return "Alice"
}
override fun exempt(player: Player) {
exempt.add(player.uniqueId)
}
override fun unexempt(player: Player) {
exempt.remove(player.uniqueId)
}
@EventHandler(priority = EventPriority.LOWEST)
private fun onViolate(event: AliceViolationEvent) {
if (!exempt.contains(event.player.uniqueId)) {
return
}
event.isCancelled = true
}
}

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

@@ -1,81 +0,0 @@
package com.willfp.eco.spigot.integrations.antigrief
import com.flowpowered.math.vector.Vector3i
import com.griefdefender.api.GriefDefender
import com.griefdefender.api.data.PlayerData
import com.griefdefender.api.permission.flag.Flags
import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper
import org.bukkit.Location
import org.bukkit.block.Block
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player
import java.util.*
class AntigriefGriefDefender : AntigriefWrapper {
override fun canBreakBlock(player: Player, block: Block): Boolean {
val data = GriefDefender.getCore().getPlayerData(player.world.uid, player.uniqueId) ?: return true
val claim = GriefDefender.getCore().getClaimAt(Vector3i(block.location.x, block.location.y, block.location.z))
?: return true
return if (data.canIgnoreClaim(claim)) {
true
} else {
claim.getActiveFlagPermissionValue(Flags.BLOCK_BREAK, data.user, Collections.emptySet(), true).asBoolean()
}
}
override fun canCreateExplosion(player: Player, location: Location): Boolean {
val data = GriefDefender.getCore().getPlayerData(player.world.uid, player.uniqueId) ?: return true
val claim = GriefDefender.getCore().getClaimAt(Vector3i(location.x, location.y, location.z)) ?: return true
return if (data.canIgnoreClaim(claim)) {
true
} else {
claim.getActiveFlagPermissionValue(Flags.EXPLOSION_BLOCK, data.user, Collections.emptySet(), true)
.asBoolean()
}
}
override fun canPlaceBlock(player: Player, block: Block): Boolean {
val data: PlayerData = GriefDefender.getCore().getPlayerData(player.world.uid, player.uniqueId) ?: return true
val claim =
GriefDefender.getCore().getClaimAt(Vector3i(block.location.x, block.location.y, block.location.z))
?: return true
return if (data.canIgnoreClaim(claim)) {
true
} else {
claim.getActiveFlagPermissionValue(Flags.BLOCK_PLACE, data.user, Collections.emptySet(), true)
.asBoolean()
}
}
override fun canInjure(player: Player, victim: LivingEntity): Boolean {
val data = GriefDefender.getCore().getPlayerData(player.world.uid, player.uniqueId) ?: return true
if (data.canIgnoreClaim(data.currentClaim)) {
return true
}
return if (victim is Player) {
val vicData = GriefDefender.getCore().getPlayerData(victim.world.uid, victim.uniqueId)
if (vicData != null) {
data.canPvp(data.currentClaim) && data.canPvp(vicData.currentClaim)
} else data.canPvp(data.currentClaim)
} else {
val claim =
GriefDefender.getCore().getClaimAt(Vector3i(victim.location.x, victim.location.y, victim.location.z))
claim?.getActiveFlagPermissionValue(Flags.ENTITY_DAMAGE, data.user, Collections.emptySet(), true)
?.asBoolean() ?: true
}
}
override fun getPluginName(): String {
return "GriefDefender"
}
}

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

@@ -3,7 +3,6 @@ package com.willfp.eco.spigot.integrations.antigrief
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper
import me.angeschossen.lands.api.integration.LandsIntegration import me.angeschossen.lands.api.integration.LandsIntegration
import me.angeschossen.lands.api.role.enums.RoleSetting
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.block.Block import org.bukkit.block.Block
import org.bukkit.entity.LivingEntity import org.bukkit.entity.LivingEntity
@@ -15,44 +14,47 @@ class AntigriefLands(private val plugin: EcoPlugin) : AntigriefWrapper {
player: Player, player: Player,
block: Block block: Block
): Boolean { ): Boolean {
val area = landsIntegration.getAreaByLoc(block.location) val area = landsIntegration.getAreaByLoc(block.location) ?: return true
return area?.canSetting(player, RoleSetting.BLOCK_BREAK, false) ?: true return area.isTrusted(player.uniqueId)
} }
override fun canCreateExplosion( override fun canCreateExplosion(
player: Player, player: Player,
location: Location location: Location
): Boolean { ): Boolean {
val area = landsIntegration.getAreaByLoc(location) val area = landsIntegration.getAreaByLoc(location) ?: return true
return area?.canSetting(player, RoleSetting.BLOCK_IGNITE, false) ?: true return area.isTrusted(player.uniqueId)
} }
override fun canPlaceBlock( override fun canPlaceBlock(
player: Player, player: Player,
block: Block block: Block
): Boolean { ): Boolean {
val area = landsIntegration.getAreaByLoc(block.location) val area = landsIntegration.getAreaByLoc(block.location) ?: return true
return area?.canSetting(player, RoleSetting.BLOCK_PLACE, false) ?: true return area.isTrusted(player.uniqueId)
} }
override fun canInjure( override fun canInjure(
player: Player, player: Player,
victim: LivingEntity victim: LivingEntity
): Boolean { ): Boolean {
val area = landsIntegration.getAreaByLoc(victim.location) val area = landsIntegration.getAreaByLoc(victim.location) ?: return true
if (victim is Player) { return area.isTrusted(player.uniqueId)
if (area != null) {
return area.canSetting(player, RoleSetting.ATTACK_PLAYER, false)
}
} else {
if (area != null) {
return area.canSetting(player, RoleSetting.ATTACK_ANIMAL, false)
}
}
return true
} }
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

@@ -72,4 +72,16 @@ class AntigriefTowny : AntigriefWrapper {
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

@@ -101,4 +101,16 @@ class AntigriefWorldGuard : AntigriefWrapper {
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

@@ -0,0 +1,58 @@
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.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 me.arcaniax.hdb.api.DatabaseLoadEvent
import me.arcaniax.hdb.api.HeadDatabaseAPI
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.inventory.ItemStack
import java.util.function.Predicate
class CustomItemsHeadDatabase(
plugin: EcoPlugin
) : CustomItemsWrapper {
private val provider = HeadDBProvider()
init {
plugin.eventManager.registerListener(provider)
}
override fun registerAllItems() {
Items.registerItemProvider(HeadDBProvider())
}
override fun getPluginName(): String {
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

@@ -14,7 +14,9 @@ class CustomItemsOraxen : CustomItemsWrapper {
for (item in OraxenItems.getItems()) { for (item in OraxenItems.getItems()) {
val stack = item.build() val stack = item.build()
val id: String = Objects.requireNonNullElse(OraxenItems.getIdByItem(item), "") val id: String = Objects.requireNonNullElse(OraxenItems.getIdByItem(item), "")
if (id.isEmpty()) continue 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

@@ -0,0 +1,21 @@
package com.willfp.eco.spigot.integrations.multiverseinventories
import com.onarandombox.multiverseinventories.event.WorldChangeShareHandlingEvent
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.events.ArmorChangeEvent
import org.bukkit.Bukkit
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
class MultiverseInventoriesIntegration(
private val plugin: EcoPlugin
): Listener {
@EventHandler
fun onWorldChange(event: WorldChangeShareHandlingEvent) {
val before = event.player.inventory.armorContents.toMutableList()
this.plugin.scheduler.run {
val after = event.player.inventory.armorContents.toMutableList()
Bukkit.getPluginManager().callEvent(ArmorChangeEvent(event.player, before, after))
}
}
}

View File

@@ -19,4 +19,13 @@ enable-bstats: true
# Some plugins use their own item display systems (eg Triton) # 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 must be ran after eco. Don't enable this unless you run a conflicting plugin
# and have been told to enable it. # and have been told to enable it.
use-lower-protocollib-priority: false use-lower-protocollib-priority: false
# Display frames massively optimize PacketWindowItems, however some users have
# reported display bugs by using it. If you have any problems with it, then you
# should disable this option.
use-display-frame: true
# Time to live for a display frame. In other words, this is how frequent (in ticks)
# that display frames will be cleared / deleted.
display-frame-ttl: 17

View File

@@ -25,11 +25,13 @@ softdepend:
- ItemsAdder - ItemsAdder
- Oraxen - Oraxen
- HeadDatabase - HeadDatabase
- GriefDefender - Multiverse-Inventories
- Alice
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'
- org.jetbrains.kotlin:kotlin-stdlib:1.5.31 - 'org.jetbrains.kotlin:kotlin-stdlib:1.5.31'
- net.kyori:adventure-api:4.9.1 - 'net.kyori:adventure-platform-bukkit:4.0.0'
- net.kyori:adventure-text-serializer-gson:4.8.1 - 'net.kyori:adventure-api:4.9.1'
- net.kyori:adventure-text-serializer-legacy:4.8.1 - 'net.kyori:adventure-text-serializer-gson:4.9.2'
- 'net.kyori:adventure-text-serializer-legacy:4.8.1'

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.9.2 version = 6.11.2
plugin-name = eco plugin-name = eco

Binary file not shown.

BIN
lib/alice-api-1.2.3.jar Normal file

Binary file not shown.