Compare commits

...

134 Commits
5.0.0 ... 5.7.0

Author SHA1 Message Date
Auxilor
726f4a44c4 Re-Added PluginDependent to HandledCommand 2021-07-05 17:53:28 +02:00
Auxilor
eafae209a6 Fixed bug with Handle 2021-07-05 17:43:18 +02:00
Auxilor
04c450b46a Improved subcommand system 2021-07-05 17:37:05 +02:00
Auxilor
d4e1f58f2a Updated to 5.7.0 2021-07-05 17:24:18 +02:00
Auxilor
b0806b934b Began introduction of new command system 2021-07-05 15:14:54 +02:00
Auxilor
a21ecfbdde Refactoring to use PluginDependent<T extends EcoPlugin> and updated CombatLogX 2021-07-05 11:41:26 +02:00
Auxilor
f3a6861bc6 Merge remote-tracking branch 'origin/master' 2021-07-05 11:22:08 +02:00
Auxilor
eaa295e6a3 Merge pull request #8 from SirBlobman/main 2021-07-05 11:05:33 +02:00
SirBlobman
399387eca1 Add comments. 2021-07-05 02:17:20 -04:00
SirBlobman
272f551aae Fix gradle dependencies and remove unnecessary local jar files. 2021-07-05 02:14:30 -04:00
SirBlobman
d8c5fc0959 Update plugin class to use correct CombatLogX hook based on version. 2021-07-05 02:13:49 -04:00
SirBlobman
d1ca106d01 Create CombatLogX V11 hook class. 2021-07-05 02:13:31 -04:00
SirBlobman
99f5174e28 Update CombatLogX V10 hook class. 2021-07-05 02:13:10 -04:00
Auxilor
d9f4aee384 Updated to 5.6.1 and added type parameters to PluginDependent 2021-07-04 19:00:14 +02:00
Auxilor
c2aae8c2eb Added direct download link to eco version checker 2021-07-04 00:45:37 +02:00
Auxilor
52061b7b51 Reverted proxy changes 2021-07-01 22:29:53 +01:00
Auxilor
762969c172 Fixed error with WildTP making their own Player class 2021-07-01 22:11:40 +01:00
Auxilor
62d5cf885f Fixed internals load order 2021-07-01 22:10:00 +01:00
Auxilor
1e70a9fdea Added eco version checking 2021-06-30 07:47:49 +01:00
Auxilor
ec8a65b4f8 Removed redundant suppression 2021-06-27 15:59:55 +01:00
Auxilor
a163219372 Chnaged ExtensionMetadata to record 2021-06-27 15:55:12 +01:00
Auxilor
4d6e097f8f Minor changes 2021-06-27 15:50:10 +01:00
Auxilor
497adbe7b1 Added extension unloading 2021-06-27 15:30:05 +01:00
Auxilor
78907412b2 Updated to 5.6.0 2021-06-27 14:59:14 +01:00
Auxilor
d6bec5d88b Added EcoPlugin#getProxy 2021-06-27 14:58:57 +01:00
Auxilor
aab1f31ca0 More changes to EcoPlugin 2021-06-27 14:39:29 +01:00
Auxilor
5ea586eaae Added more constructors and options to EcoPlugin 2021-06-27 14:11:47 +01:00
Auxilor
2ffc293211 Added http encoding to paste 2021-06-27 13:59:45 +01:00
Auxilor
88bedef420 Encoded strings paste 2021-06-25 11:47:24 +01:00
Auxilor
dac5ffce9a Fixed JsonConfigWrapper#clone returning internal JsonConfigWrapper rather than JSONConfig 2021-06-25 09:15:45 +01:00
Auxilor
d641adadea Fixed broken slot javadoc 2021-06-22 15:36:07 +01:00
Auxilor
46269354c6 'Cleaned up' ArrowDataListener 2021-06-22 15:34:27 +01:00
Auxilor
2d93465d1d Added Paste#getFromHastebin 2021-06-22 15:31:00 +01:00
Auxilor
484d4dde75 Renamed Internals class 2021-06-22 15:28:08 +01:00
Auxilor
5e9a408704 Refactored configs 2021-06-22 15:24:32 +01:00
Auxilor
f1b113f435 Extracted ConfigHandler interface 2021-06-22 15:23:35 +01:00
Auxilor
5d553d725c Updated to 5.5.1 2021-06-20 16:42:25 +01:00
Auxilor
a3be846083 Removed gson implementation 2021-06-20 16:42:15 +01:00
Auxilor
54e0b3f482 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	eco-api/src/main/java/com/willfp/eco/internal/arrows/ArrowDataListener.java
#	eco-api/src/main/java/com/willfp/eco/internal/items/AbstractItemStackBuilder.java
#	eco-api/src/main/java/com/willfp/eco/util/TeamUtils.java
2021-06-19 11:38:34 +01:00
Auxilor
93794fe454 Reverted 2021-06-18 11:42:49 +01:00
Auxilor
7f4a0c800e Fixed bug with empty JSON string lists 2021-06-18 09:02:17 +01:00
Auxilor
853864f6f0 Added Paste 2021-06-17 22:23:17 +01:00
Auxilor
0cb6e8f669 Added toPlaintext 2021-06-17 17:45:15 +01:00
Auxilor
d30f657eec Fixed list translation modifying by reference 2021-06-17 13:43:30 +01:00
Auxilor
d60ecdd340 Fixed SkullBuilder 2021-06-17 13:37:47 +01:00
Auxilor
07310df68a Added support for plugin parameters on update methods 2021-06-17 12:57:40 +01:00
Auxilor
5c91aa220a Added LeatherArmorBuilder 2021-06-17 11:33:22 +01:00
Auxilor
756a76057a Reduced generic abuse 2021-06-17 11:28:24 +01:00
Auxilor
b6f27ee232 Refactoring builders to be easier to use 2021-06-17 11:25:54 +01:00
Auxilor
74ca2e82ef Added suppliers to itemstackbuilder 2021-06-17 11:14:47 +01:00
Auxilor
4039439fda Added AbstractItemStackBuilder#setCustomModelData 2021-06-17 11:04:49 +01:00
Auxilor
7dac671690 Added Recipes#createAndRegisterRecipe 2021-06-17 10:56:15 +01:00
Auxilor
411d517a9a Added persistent meta writing to ItemStackBuilder 2021-06-17 10:52:36 +01:00
Auxilor
0d84141116 Updated configs to translate all strings in lists automatically 2021-06-17 10:37:37 +01:00
Auxilor
6bfd5bd153 Added TranslateList and JSON parity 2021-06-17 10:36:38 +01:00
Auxilor
b7d421e1a8 Fixed JSON int bug 2021-06-17 10:28:46 +01:00
Auxilor
2e9d811d3f Fixed deprecated reference 2021-06-17 09:41:53 +01:00
Auxilor
672b295917 Fixed Prerequisite typo 2021-06-17 09:19:42 +01:00
Auxilor
60a83478e8 J16 work 2021-06-17 08:38:18 +01:00
Auxilor
c880a476d4 Continued adding stack support to recipes 2021-06-16 22:17:23 +01:00
Auxilor
692305d595 Continued adding stack support to recipes 2021-06-16 16:54:33 +01:00
Auxilor
9d4cc2961c Fixed NPE 2021-06-16 16:08:45 +01:00
Auxilor
358b389875 Fixed NPE 2021-06-16 16:07:22 +01:00
Auxilor
7fa25c2500 Naming update 2021-06-16 16:04:54 +01:00
Auxilor
91c58c4a53 Added stack support to crafting 2021-06-16 16:03:07 +01:00
Auxilor
4ccee91c64 Added PlayerJumpEvent 2021-06-16 15:45:10 +01:00
Auxilor
eef87342a1 Switched to Java 15 pattern variables 2021-06-16 15:35:15 +01:00
Auxilor
efc70ea7a8 GUI Javadoc 2021-06-16 15:21:48 +01:00
Auxilor
de38299264 Removed test 2021-06-16 15:18:22 +01:00
Auxilor
bc94f43299 Data null safetyx 2021-06-16 13:30:36 +01:00
Auxilor
ed705cc577 Added 1.17 materials to TeamUtils 2021-06-16 11:30:23 +01:00
Auxilor
93410490c5 Javadoc 2021-06-16 11:26:43 +01:00
Auxilor
33914ac284 Added COPPER_ORE to TeamUtils 2021-06-15 21:11:06 +01:00
Auxilor
2acf2ee687 Added setPersistentKEy 2021-06-15 21:08:02 +01:00
Auxilor
0470552168 Added ItemStack builders 2021-06-15 21:04:55 +01:00
Auxilor
3e724eea18 Updated GUI system 2021-06-15 20:44:57 +01:00
Auxilor
33ba5c9d31 Reworked data to just have a call to retrieve a JSON config that can be modified 2021-06-15 15:47:25 +01:00
Auxilor
94ab094952 Cleaning up config 2021-06-15 15:25:45 +01:00
Auxilor
58f5d3f352 Added getKeys(true) 2021-06-15 14:07:55 +01:00
Auxilor
912872e791 Updated config backend 2021-06-15 12:39:10 +01:00
Auxilor
7a65e6e821 Added getSubsections to JSON Configs 2021-06-15 11:29:42 +01:00
Auxilor
3f446f6072 Added JSON support 2021-06-15 11:02:21 +01:00
Auxilor
50f57abd6c Added recursive JSON Get/Set and tests 2021-06-15 10:59:55 +01:00
Auxilor
2c5eae6c6c Removed unused imports 2021-06-15 09:35:12 +01:00
Auxilor
1e3e54b8c5 Added preliminary JSON support 2021-06-14 16:56:10 +01:00
Auxilor
0ce9119a94 Added gson as a dependency 2021-06-14 14:53:16 +01:00
Auxilor
bf76ba9f5a Fixed publication issues 2021-06-13 10:46:57 +01:00
Auxilor
8a065bf7ca Updated to 5.4.1 2021-06-13 10:26:33 +01:00
Auxilor
5f045d02a6 Fixed publishing errors 2021-06-11 12:11:19 +01:00
Auxilor
f07ef3045b Fixed gradle issues 2021-06-11 12:04:07 +01:00
Auxilor
007a579f5a Updated to 5.4.0 2021-06-11 11:37:09 +01:00
Auxilor
9b19cd412a Updated to 1.17 and Java 16 2021-06-11 11:36:58 +01:00
Auxilor
08b5cc1612 Added more null checks to fix incompatibility with paper/adventure 2021-05-18 15:41:45 +01:00
Auxilor
47aa61c7b3 Updated to 5.3.7 2021-05-18 15:34:02 +01:00
Auxilor
ef1ee84358 Added checks for null components due to problem with adventure 2021-05-18 15:33:47 +01:00
Auxilor
49a36a4e81 Updated to 5.3.6 2021-05-06 08:47:51 +01:00
Auxilor
bf76dec28e Added emerald ore in TeamUtils 2021-05-06 08:47:41 +01:00
Auxilor
a0f51d79e8 Updated to 5.3.5 2021-04-26 21:24:45 +01:00
Auxilor
9be516e511 Added villager-display-fix to force remove all hideflags 2021-04-26 21:24:28 +01:00
Auxilor
a130935c62 Fixed Villager Trades for the last time 2021-04-25 15:54:50 +01:00
Auxilor
4359bd17ae Updated to 5.3.4 2021-04-25 15:45:26 +01:00
Auxilor
07726959e9 Fixed MerchantRecipe again 2021-04-25 15:45:16 +01:00
Auxilor
13c8187b3b Updated to 5.3.3 2021-04-25 15:18:51 +01:00
Auxilor
be1267ef0c Fixed config default 2021-04-25 15:18:40 +01:00
Auxilor
e61e9bc0a8 Added disable villager display option 2021-04-24 17:05:07 +01:00
Auxilor
ec801cd776 Updated to 5.3.2 2021-04-24 17:02:23 +01:00
Auxilor
a5b5bc6b46 Fixed ChatComponent 2021-04-24 17:01:53 +01:00
Auxilor
f5efb50d71 Updated to 5.3.1 2021-04-23 21:17:13 +01:00
Auxilor
d65c04aaa7 Hopefully fixed Villager Trades again 2021-04-23 21:16:46 +01:00
Auxilor
aa69d2a1a9 Fixed deprecation still being used 2021-04-20 21:41:04 +01:00
Auxilor
685cd5f998 Deprecated finalization system 2021-04-20 21:39:25 +01:00
Auxilor
bae4b567c8 Updated to 5.3.0 2021-04-20 21:31:05 +01:00
Auxilor
0eb3315d61 Updated to 5.2.2 2021-04-20 21:29:28 +01:00
Auxilor
0a42320b78 Fixed villager trade display 2021-04-20 21:29:19 +01:00
Auxilor
6ce0de8db7 Merge remote-tracking branch 'origin/master' 2021-04-20 21:28:04 +01:00
Auxilor
345d4cd1b5 Reworked villager trade display 2021-04-20 20:21:32 +01:00
Auxilor
950c092025 Added EcoSkills to loadbefore 2021-04-17 10:25:38 +01:00
Auxilor
0c6bb8c1b7 Updated to 5.2.1 2021-04-17 10:24:39 +01:00
Auxilor
0f9cb7db7a Items in menus now translate placeholder lore with respect to a player 2021-04-17 10:24:27 +01:00
Auxilor
7d4262e0ef Finished GUIs 2021-04-16 15:32:42 +01:00
Auxilor
e543be7a13 Updated to 5.2.0 2021-04-16 14:51:47 +01:00
Auxilor
3d7027bf47 Added initial GUI system 2021-04-16 14:51:30 +01:00
Auxilor
632b42ad65 Updated to 5.1.1 2021-04-14 16:02:00 +01:00
Auxilor
bcd79e3886 Added vulcan support 2021-04-14 16:01:51 +01:00
Auxilor
8fbcf485b3 Renamed PlayerData to Data 2021-04-08 15:03:17 +01:00
Auxilor
6a64be2e25 Removed debug code 2021-04-08 15:01:57 +01:00
Auxilor
3f9f3991d8 Fixed cache on set in configs 2021-04-08 15:00:31 +01:00
Auxilor
54a8d942fa Fixed getSubsectionOrNull 2021-04-08 14:36:07 +01:00
Auxilor
6aa14be577 Updated to 5.1.0 2021-04-08 14:28:53 +01:00
Auxilor
d6db7673d8 Added data.yml 2021-04-08 14:28:19 +01:00
Auxilor
d002073124 Updated to 5.0.2 2021-04-06 18:03:03 +01:00
Auxilor
4bc98cae81 Fixed getVein 2021-04-06 18:02:50 +01:00
Auxilor
2696baf1d6 Updated to 5.0.1 2021-04-05 17:46:30 +01:00
Auxilor
3c3cc36403 Fixed fast sin and cos 2021-04-05 17:46:18 +01:00
123 changed files with 4039 additions and 454 deletions

View File

@@ -1,6 +1,6 @@
plugins { plugins {
id 'java-library' id 'java-library'
id 'com.github.johnrengelman.shadow' version '5.2.0' id 'com.github.johnrengelman.shadow' version '7.0.0'
id 'maven-publish' id 'maven-publish'
id 'java' id 'java'
} }
@@ -18,7 +18,6 @@ allprojects {
repositories { repositories {
mavenCentral() mavenCentral()
jcenter()
mavenLocal() mavenLocal()
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
@@ -54,10 +53,10 @@ allprojects {
compileOnly 'org.jetbrains:annotations:19.0.0' compileOnly 'org.jetbrains:annotations:19.0.0'
// Lombok // Lombok
compileOnly 'org.projectlombok:lombok:1.18.16' compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.16' annotationProcessor 'org.projectlombok:lombok:1.18.20'
testCompileOnly 'org.projectlombok:lombok:1.18.16' testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.16' testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
} }
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
@@ -87,6 +86,11 @@ allprojects {
onlyIf { !sourceSets.main.allSource.files.isEmpty() } onlyIf { !sourceSets.main.allSource.files.isEmpty() }
} }
java {
sourceCompatibility = JavaVersion.VERSION_16
targetCompatibility = JavaVersion.VERSION_16
}
compileJava.options.encoding = 'UTF-8' compileJava.options.encoding = 'UTF-8'
compileJava.dependsOn clean compileJava.dependsOn clean
@@ -96,4 +100,3 @@ allprojects {
group = 'com.willfp' group = 'com.willfp'
archivesBaseName = project.name archivesBaseName = project.name
version = findProperty("version") version = findProperty("version")
java.sourceCompatibility = JavaVersion.VERSION_1_8

View File

@@ -8,6 +8,8 @@
<!-- Internals don't need javadoc. --> <!-- Internals don't need javadoc. -->
<suppress files="[\\/]internal[\\/]" checks="MissingJavadocMethod"/> <suppress files="[\\/]internal[\\/]" checks="MissingJavadocMethod"/>
<suppress files="[\\/]internal[\\/]" checks="JavadocVariable"/> <suppress files="[\\/]internal[\\/]" checks="JavadocVariable"/>
<suppress files="[\\/]eco[\\/]spigot[\\/]" checks="MissingJavadocMethod"/>
<suppress files="[\\/]eco[\\/]spigot[\\/]" checks="JavadocVariable"/>
<!-- Modified version of library --> <!-- Modified version of library -->
<suppress files="ArmorEquipEvent.java" checks="JavadocVariable"/> <suppress files="ArmorEquipEvent.java" checks="JavadocVariable"/>

View File

@@ -1,12 +1,17 @@
plugins {
id 'com.github.johnrengelman.shadow'
}
group 'com.willfp' group 'com.willfp'
version rootProject.version version rootProject.version
dependencies { dependencies {
compileOnly 'org.spigotmc:spigot:1.16.4-R0.1-SNAPSHOT' compileOnly 'org.spigotmc:spigot:1.17-R0.1-SNAPSHOT'
compileOnly 'org.apache.maven:maven-artifact:3.0.3' compileOnly 'org.apache.maven:maven-artifact:3.0.3'
compileOnly 'org.bstats:bstats-bukkit:1.7' compileOnly 'org.bstats:bstats-bukkit:1.7'
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT' compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT'
compileOnly 'me.clip:placeholderapi:2.10.9' compileOnly 'me.clip:placeholderapi:2.10.9'
compileOnly 'com.google.code.gson:gson:2.8.7'
} }
compileJava.options.encoding = 'UTF-8' compileJava.options.encoding = 'UTF-8'
@@ -18,7 +23,6 @@ publishing {
publications { publications {
shadow(MavenPublication) { shadow(MavenPublication) {
from components.java from components.java
artifact shadowJar
artifactId 'eco' artifactId 'eco'
} }
} }

View File

@@ -78,6 +78,32 @@ public abstract class AbstractPacketAdapter extends PacketAdapter {
// Empty rather than abstract as implementations don't need both // Empty rather than abstract as implementations don't need both
} }
/**
* The code that should be executed once the packet has been received.
*
* @param packet The packet.
* @param player The player.
* @param event The event.
*/
public void onReceive(@NotNull final PacketContainer packet,
@NotNull final Player player,
@NotNull final PacketEvent event) {
// Empty rather than abstract as implementations don't need both
}
/**
* THe code that should be executed once the packet has been sent.
*
* @param packet The packet.
* @param player The player.
* @param event The event.
*/
public void onSend(@NotNull final PacketContainer packet,
@NotNull final Player player,
@NotNull final PacketEvent event) {
// Empty rather than abstract as implementations don't need both
}
/** /**
* Boilerplate to assert that the packet is of the specified type. * Boilerplate to assert that the packet is of the specified type.
* *
@@ -94,6 +120,7 @@ public abstract class AbstractPacketAdapter extends PacketAdapter {
} }
onReceive(event.getPacket(), event.getPlayer()); onReceive(event.getPacket(), event.getPlayer());
onReceive(event.getPacket(), event.getPlayer(), event);
} }
/** /**
@@ -112,6 +139,12 @@ public abstract class AbstractPacketAdapter extends PacketAdapter {
} }
onSend(event.getPacket(), event.getPlayer()); onSend(event.getPacket(), event.getPlayer());
onSend(event.getPacket(), event.getPlayer(), event);
}
@Override
public final EcoPlugin getPlugin() {
return (EcoPlugin) super.getPlugin();
} }
/** /**

View File

@@ -1,9 +1,10 @@
package com.willfp.eco.core; package com.willfp.eco.core;
import com.willfp.eco.core.command.AbstractCommand; import com.willfp.eco.core.command.AbstractCommand;
import com.willfp.eco.core.command.impl.PluginCommand;
import com.willfp.eco.core.config.ConfigHandler;
import com.willfp.eco.core.config.base.ConfigYml; import com.willfp.eco.core.config.base.ConfigYml;
import com.willfp.eco.core.config.base.LangYml; import com.willfp.eco.core.config.base.LangYml;
import com.willfp.eco.internal.config.updating.ConfigHandler;
import com.willfp.eco.core.display.Display; import com.willfp.eco.core.display.Display;
import com.willfp.eco.core.display.DisplayModule; import com.willfp.eco.core.display.DisplayModule;
import com.willfp.eco.core.events.EventManager; import com.willfp.eco.core.events.EventManager;
@@ -14,8 +15,10 @@ import com.willfp.eco.core.factory.RunnableFactory;
import com.willfp.eco.core.integrations.IntegrationLoader; import com.willfp.eco.core.integrations.IntegrationLoader;
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager; import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
import com.willfp.eco.core.scheduling.Scheduler; import com.willfp.eco.core.scheduling.Scheduler;
import com.willfp.eco.internal.Internals;
import com.willfp.eco.internal.UpdateChecker; import com.willfp.eco.internal.UpdateChecker;
import com.willfp.eco.internal.arrows.ArrowDataListener; import com.willfp.eco.internal.arrows.ArrowDataListener;
import com.willfp.eco.internal.config.updating.EcoConfigHandler;
import com.willfp.eco.internal.events.EcoEventManager; import com.willfp.eco.internal.events.EcoEventManager;
import com.willfp.eco.internal.extensions.EcoExtensionLoader; import com.willfp.eco.internal.extensions.EcoExtensionLoader;
import com.willfp.eco.internal.factory.EcoMetadataValueFactory; import com.willfp.eco.internal.factory.EcoMetadataValueFactory;
@@ -25,9 +28,11 @@ import com.willfp.eco.internal.integrations.PlaceholderIntegrationPAPI;
import com.willfp.eco.internal.logging.EcoLogger; import com.willfp.eco.internal.logging.EcoLogger;
import com.willfp.eco.internal.scheduling.EcoScheduler; import com.willfp.eco.internal.scheduling.EcoScheduler;
import lombok.Getter; import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@@ -42,6 +47,7 @@ import java.util.Set;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
public abstract class EcoPlugin extends JavaPlugin { public abstract class EcoPlugin extends JavaPlugin {
/** /**
* Loaded eco plugins. * Loaded eco plugins.
@@ -50,8 +56,11 @@ public abstract class EcoPlugin extends JavaPlugin {
/** /**
* The name of the plugin. * The name of the plugin.
*
* @deprecated Pointless, use getName instead.
*/ */
@Getter @Getter
@Deprecated
private final String pluginName; private final String pluginName;
/** /**
@@ -162,6 +171,100 @@ public abstract class EcoPlugin extends JavaPlugin {
@Getter @Getter
private boolean outdated = false; private boolean outdated = false;
/**
* If the plugin supports extensions.
*/
@Getter
private final boolean supportingExtensions;
/**
* Create a new plugin without a specified color, proxy support, spigot, or bStats.
*/
protected EcoPlugin() {
this("&f");
}
/**
* Create a new plugin without proxy support, spigot, or bStats.
*
* @param color The color.
*/
protected EcoPlugin(@NotNull final String color) {
this("", color);
}
/**
* Create a new plugin unlinked to spigot and bStats.
*
* @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b)
*/
protected EcoPlugin(@NotNull final String proxyPackage,
@NotNull final String color) {
this(0, 0, proxyPackage, color);
}
/**
* Create a new plugin without proxy or extension support.
*
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param color The color of the plugin (used in messages, such as &a, &b)
*/
protected EcoPlugin(final int resourceId,
final int bStatsId,
@NotNull final String color) {
this(resourceId, bStatsId, "", color);
}
/**
* Create a new plugin without proxy support.
*
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param color The color of the plugin (used in messages, such as &a, &b)
* @param supportingExtensions If the plugin supports extensions.
*/
protected EcoPlugin(final int resourceId,
final int bStatsId,
@NotNull final String color,
final boolean supportingExtensions) {
this(resourceId, bStatsId, "", color, supportingExtensions);
}
/**
* Create a new plugin without extension support.
*
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b)
*/
protected EcoPlugin(final int resourceId,
final int bStatsId,
@NotNull final String proxyPackage,
@NotNull final String color) {
this(resourceId, bStatsId, proxyPackage, color, false);
}
/**
* Create a new plugin.
*
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b)
* @param supportingExtensions If the plugin supports extensions.
*/
protected EcoPlugin(final int resourceId,
final int bStatsId,
@NotNull final String proxyPackage,
@NotNull final String color,
final boolean supportingExtensions) {
this("", resourceId, bStatsId, proxyPackage, color, supportingExtensions);
}
/** /**
* Create a new plugin. * Create a new plugin.
* *
@@ -170,17 +273,43 @@ public abstract class EcoPlugin extends JavaPlugin {
* @param bStatsId The bStats resource ID for the plugin. * @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored. * @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b) * @param color The color of the plugin (used in messages, such as &a, &b)
* @deprecated pluginName is redundant.
*/ */
@Deprecated
@SuppressWarnings("unused")
protected EcoPlugin(@NotNull final String pluginName, protected EcoPlugin(@NotNull final String pluginName,
final int resourceId, final int resourceId,
final int bStatsId, final int bStatsId,
@NotNull final String proxyPackage, @NotNull final String proxyPackage,
@NotNull final String color) { @NotNull final String color) {
this.pluginName = pluginName; this(pluginName, resourceId, bStatsId, proxyPackage, color, false);
}
/**
* Create a new plugin.
*
* @param pluginName The name of the plugin.
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b)
* @param supportingExtensions If the plugin supports extensions.
* @deprecated pluginName is redundant.
*/
@Deprecated
@SuppressWarnings("unused")
protected EcoPlugin(@NotNull final String pluginName,
final int resourceId,
final int bStatsId,
@NotNull final String proxyPackage,
@NotNull final String color,
final boolean supportingExtensions) {
this.pluginName = this.getName();
this.resourceId = resourceId; this.resourceId = resourceId;
this.bStatsId = bStatsId; this.bStatsId = bStatsId;
this.proxyPackage = proxyPackage; this.proxyPackage = proxyPackage;
this.color = color; this.color = color;
this.supportingExtensions = supportingExtensions;
this.scheduler = new EcoScheduler(this); this.scheduler = new EcoScheduler(this);
this.eventManager = new EcoEventManager(this); this.eventManager = new EcoEventManager(this);
@@ -188,7 +317,7 @@ public abstract class EcoPlugin extends JavaPlugin {
this.metadataValueFactory = new EcoMetadataValueFactory(this); this.metadataValueFactory = new EcoMetadataValueFactory(this);
this.runnableFactory = new EcoRunnableFactory(this); this.runnableFactory = new EcoRunnableFactory(this);
this.extensionLoader = new EcoExtensionLoader(this); this.extensionLoader = new EcoExtensionLoader(this);
this.configHandler = new ConfigHandler(this); this.configHandler = new EcoConfigHandler(this);
this.logger = new EcoLogger(this); this.logger = new EcoLogger(this);
this.langYml = new LangYml(this); this.langYml = new LangYml(this);
@@ -205,24 +334,38 @@ public abstract class EcoPlugin extends JavaPlugin {
super.onEnable(); super.onEnable();
this.getLogger().info(""); this.getLogger().info("");
this.getLogger().info("Loading " + this.color + this.pluginName); this.getLogger().info("Loading " + this.getColor() + this.getName());
this.getEventManager().registerListener(new ArrowDataListener(this)); this.getEventManager().registerListener(new ArrowDataListener(this));
if (this.getResourceId() != 0) {
new UpdateChecker(this).getVersion(version -> { new UpdateChecker(this).getVersion(version -> {
DefaultArtifactVersion currentVersion = new DefaultArtifactVersion(this.getDescription().getVersion()); DefaultArtifactVersion currentVersion = new DefaultArtifactVersion(this.getDescription().getVersion());
DefaultArtifactVersion mostRecentVersion = new DefaultArtifactVersion(version); DefaultArtifactVersion mostRecentVersion = new DefaultArtifactVersion(version);
if (!(currentVersion.compareTo(mostRecentVersion) > 0 || currentVersion.equals(mostRecentVersion))) { if (!(currentVersion.compareTo(mostRecentVersion) > 0 || currentVersion.equals(mostRecentVersion))) {
this.outdated = true; this.outdated = true;
this.getScheduler().runTimer(() -> { this.getScheduler().runTimer(() -> {
this.getLogger().info("&c " + this.pluginName + " is out of date! (Version " + this.getDescription().getVersion() + ")"); this.getLogger().info("&c " + this.getName() + " is out of date! (Version " + this.getDescription().getVersion() + ")");
this.getLogger().info("&cThe newest version is &f" + version); this.getLogger().info("&cThe newest version is &f" + version);
this.getLogger().info("&cDownload the new version!"); this.getLogger().info("&cDownload the new version!");
}, 0, 864000); }, 0, 864000);
} }
}); });
}
new Metrics(this, this.bStatsId); DefaultArtifactVersion runningVersion = new DefaultArtifactVersion(Internals.getInstance().getPlugin().getDescription().getVersion());
DefaultArtifactVersion requiredVersion = new DefaultArtifactVersion(this.getMinimumEcoVersion());
if (!(runningVersion.compareTo(requiredVersion) > 0 || runningVersion.equals(requiredVersion))) {
this.getLogger().severe("You are running an outdated version of eco!");
this.getLogger().severe("You must be on at least" + this.getMinimumEcoVersion());
this.getLogger().severe("Download the newest version here:");
this.getLogger().severe("https://polymart.org/download/773/recent/JSpprMspkuyecf5y1wQ2Jn8OoLQSQ_IW");
Bukkit.getPluginManager().disablePlugin(this);
}
if (this.getBStatsId() != 0) {
new Metrics(this, this.getBStatsId());
}
Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toSet()); Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toSet());
@@ -253,11 +396,23 @@ public abstract class EcoPlugin extends JavaPlugin {
this.getListeners().forEach(listener -> this.getEventManager().registerListener(listener)); this.getListeners().forEach(listener -> this.getEventManager().registerListener(listener));
this.getCommands().forEach(AbstractCommand::register); this.getCommands().forEach(AbstractCommand::register);
this.getPluginCommands().forEach(PluginCommand::register);
this.getScheduler().runLater(this::afterLoad, 1); this.getScheduler().runLater(this::afterLoad, 1);
this.updatableClasses.forEach(clazz -> this.getConfigHandler().registerUpdatableClass(clazz)); this.updatableClasses.forEach(clazz -> this.getConfigHandler().registerUpdatableClass(clazz));
if (this.isSupportingExtensions()) {
this.getExtensionLoader().loadExtensions();
if (this.getExtensionLoader().getLoadedExtensions().isEmpty()) {
this.getLogger().info("&cNo extensions found");
} else {
this.getLogger().info("Extensions Loaded:");
this.getExtensionLoader().getLoadedExtensions().forEach(extension -> this.getLogger().info("- " + extension.getName() + " v" + extension.getVersion()));
}
}
this.enable(); this.enable();
this.getLogger().info(""); this.getLogger().info("");
@@ -272,8 +427,13 @@ public abstract class EcoPlugin extends JavaPlugin {
this.getEventManager().unregisterAllListeners(); this.getEventManager().unregisterAllListeners();
this.getScheduler().cancelAll(); this.getScheduler().cancelAll();
this.getConfigHandler().saveAllConfigs();
this.disable(); this.disable();
if (this.isSupportingExtensions()) {
this.getExtensionLoader().unloadExtensions();
}
} }
/** /**
@@ -326,8 +486,7 @@ public abstract class EcoPlugin extends JavaPlugin {
* Default code to be executed on plugin reload. * Default code to be executed on plugin reload.
*/ */
public final void reload() { public final void reload() {
this.getConfigYml().update(); this.getConfigHandler().updateConfigs();
this.getLangYml().update();
this.getConfigHandler().callUpdate(); this.getConfigHandler().callUpdate();
this.getConfigHandler().callUpdate(); // Call twice to fix issues this.getConfigHandler().callUpdate(); // Call twice to fix issues
@@ -338,42 +497,79 @@ public abstract class EcoPlugin extends JavaPlugin {
/** /**
* The plugin-specific code to be executed on enable. * The plugin-specific code to be executed on enable.
* <p>
* Override when needed.
*/ */
public abstract void enable(); public void enable() {
}
/** /**
* The plugin-specific code to be executed on disable. * The plugin-specific code to be executed on disable.
* <p>
* Override when needed.
*/ */
public abstract void disable(); public void disable() {
}
/** /**
* The plugin-specific code to be executed on load. * The plugin-specific code to be executed on load.
* <p>
* This is executed before enabling.
* <p>
* Override when needed.
*/ */
public abstract void load(); public void load() {
}
/** /**
* The plugin-specific code to be executed on reload. * The plugin-specific code to be executed on reload.
* <p>
* Override when needed.
*/ */
public abstract void onReload(); public void onReload() {
}
/** /**
* The plugin-specific code to be executed after the server is up. * The plugin-specific code to be executed after the server is up.
* <p>
* Override when needed.
*/ */
public abstract void postLoad(); public void postLoad() {
}
/** /**
* The plugin-specific integrations to be tested and loaded. * The plugin-specific integrations to be tested and loaded.
* *
* @return A list of integrations. * @return A list of integrations.
*/ */
public abstract List<IntegrationLoader> getIntegrationLoaders(); public List<IntegrationLoader> getIntegrationLoaders() {
return new ArrayList<>();
}
/** /**
* The command to be registered. * The commands to be registered.
*
* @return A list of commands.
* @deprecated Use {@link this#getPluginCommands()} instead.
*/
@Deprecated
public List<AbstractCommand> getCommands() {
return new ArrayList<>();
}
/**
* The commands to be registered.
* *
* @return A list of commands. * @return A list of commands.
*/ */
public abstract List<AbstractCommand> getCommands(); public List<PluginCommand> getPluginCommands() {
return new ArrayList<>();
}
/** /**
* ProtocolLib packet adapters to be registered. * ProtocolLib packet adapters to be registered.
@@ -382,7 +578,9 @@ public abstract class EcoPlugin extends JavaPlugin {
* *
* @return A list of packet adapters. * @return A list of packet adapters.
*/ */
public abstract List<AbstractPacketAdapter> getPacketAdapters(); public List<AbstractPacketAdapter> getPacketAdapters() {
return new ArrayList<>();
}
/** /**
* All listeners to be registered. * All listeners to be registered.
@@ -396,7 +594,9 @@ public abstract class EcoPlugin extends JavaPlugin {
* *
* @return A list of all updatable classes. * @return A list of all updatable classes.
*/ */
public abstract List<Class<?>> getUpdatableClasses(); public List<Class<?>> getUpdatableClasses() {
return new ArrayList<>();
}
/** /**
* Create the display module for the plugin. * Create the display module for the plugin.
@@ -405,12 +605,86 @@ public abstract class EcoPlugin extends JavaPlugin {
*/ */
@Nullable @Nullable
protected DisplayModule createDisplayModule() { protected DisplayModule createDisplayModule() {
Validate.isTrue(
this.getDisplayModule() == null,
"Display module exists!"
);
return null; return null;
} }
/**
* Get the minimum version of eco to use the plugin.
*
* @return The version.
*/
protected String getMinimumEcoVersion() {
return "5.0.0";
}
/**
* Get the plugin's logger.
*
* @return The logger.
*/
@NotNull @NotNull
@Override @Override
public Logger getLogger() { public Logger getLogger() {
return logger; return logger;
} }
/**
* Get unwrapped config.
* Does not use eco config system, don't use.
*
* @return The bukkit config.
* @deprecated Use {@link EcoPlugin#getConfigYml()} instead.
*/
@NotNull
@Override
@Deprecated
public final FileConfiguration getConfig() {
this.getLogger().warning("Call to default config method in eco plugin!");
return this.getConfigYml().getHandle();
}
/**
* Does not use eco config system, don't use.
*
* @deprecated Use eco config system.
*/
@Override
@Deprecated
public final void saveConfig() {
this.getLogger().warning("Call to default config method in eco plugin!");
super.saveConfig();
}
/**
* Does not use eco config system, don't use.
*
* @deprecated Use eco config system.
*/
@Override
@Deprecated
public final void saveDefaultConfig() {
this.getLogger().warning("Call to default config method in eco plugin!");
super.saveDefaultConfig();
}
/**
* Does not use eco config system, don't use.
*
* @deprecated Use eco config system.
*/
@Override
@Deprecated
public final void reloadConfig() {
this.getLogger().warning("Call to default config method in eco plugin!");
super.reloadConfig();
}
} }

View File

@@ -4,19 +4,19 @@ import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public abstract class PluginDependent { public abstract class PluginDependent<T extends EcoPlugin> {
/** /**
* The {@link EcoPlugin} that is stored. * The {@link EcoPlugin} that is stored.
*/ */
@Getter(AccessLevel.PROTECTED) @Getter(AccessLevel.PROTECTED)
private final EcoPlugin plugin; private final T plugin;
/** /**
* Pass an {@link EcoPlugin} in order to interface with it. * Pass an {@link EcoPlugin} in order to interface with it.
* *
* @param plugin The plugin to manage. * @param plugin The plugin to manage.
*/ */
protected PluginDependent(@NotNull final EcoPlugin plugin) { protected PluginDependent(@NotNull final T plugin) {
this.plugin = plugin; this.plugin = plugin;
} }
} }

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core; package com.willfp.eco.core;
import com.willfp.eco.core.proxy.ProxyConstants;
import com.willfp.eco.util.ClassUtils; import com.willfp.eco.util.ClassUtils;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -14,6 +15,7 @@ public class Prerequisite {
* All existing prerequisites are registered on creation. * All existing prerequisites are registered on creation.
*/ */
private static final List<Prerequisite> VALUES = new ArrayList<>(); private static final List<Prerequisite> VALUES = new ArrayList<>();
/** /**
* Requires the server to be running an implementation of paper. * Requires the server to be running an implementation of paper.
*/ */
@@ -22,6 +24,23 @@ public class Prerequisite {
"Requires server to be running paper (or a fork)" "Requires server to be running paper (or a fork)"
); );
/**
* Requires the server to be running 1.17.
*/
@Deprecated
public static final Prerequisite v1_17 = new Prerequisite(
() -> ProxyConstants.NMS_VERSION.contains("17"),
"Requires server to be running 1.17+"
);
/**
* Requires the server to be running 1.17.
*/
public static final Prerequisite HAS_1_17 = new Prerequisite(
() -> ProxyConstants.NMS_VERSION.contains("17"),
"Requires server to be running 1.17+"
);
/** /**
* If the necessary prerequisite condition has been met. * If the necessary prerequisite condition has been met.
*/ */

View File

@@ -14,7 +14,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
public abstract class AbstractCommand extends PluginDependent implements CommandExecutor { @Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
public abstract class AbstractCommand extends PluginDependent<EcoPlugin> implements CommandExecutor {
/** /**
* The name of the command * The name of the command
* <p> * <p>

View File

@@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@Deprecated
public abstract class AbstractTabCompleter implements TabCompleter { public abstract class AbstractTabCompleter implements TabCompleter {
/** /**
* The {@link AbstractCommand} that is tab-completed. * The {@link AbstractCommand} that is tab-completed.

View File

@@ -0,0 +1,48 @@
package com.willfp.eco.core.command;
import org.jetbrains.annotations.NotNull;
public interface CommandBase {
/**
* Get command name.
*
* @return The name.
*/
String getName();
/**
* Get command permission.
*
* @return The permission.
*/
String getPermission();
/**
* If only players can execute the command.
*
* @return If true.
*/
boolean isPlayersOnly();
/**
* Add a subcommand to the command.
*
* @param command The subcommand.
* @return The parent command.
*/
CommandBase addSubcommand(@NotNull CommandBase command);
/**
* Get the handler.
*
* @return The handler.
*/
CommandHandler getHandler();
/**
* Get the tab completer.
*
* @return The tab completer.
*/
TabCompleteHandler getTabCompleter();
}

View File

@@ -0,0 +1,18 @@
package com.willfp.eco.core.command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@FunctionalInterface
public interface CommandHandler {
/**
* The code to be called on execution.
*
* @param sender The sender.
* @param args The arguments.
*/
void onExecute(@NotNull CommandSender sender,
@NotNull List<String> args);
}

View File

@@ -0,0 +1,19 @@
package com.willfp.eco.core.command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@FunctionalInterface
public interface TabCompleteHandler {
/**
* Handle Tab Completion.
*
* @param sender The sender.
* @param args The arguments.
* @return The tab completion results.
*/
List<String> tabComplete(@NotNull CommandSender sender,
@NotNull List<String> args);
}

View File

@@ -0,0 +1,92 @@
package com.willfp.eco.core.command.impl;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.internal.commands.HandledCommand;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public abstract class PluginCommand extends HandledCommand implements CommandExecutor, TabCompleter {
/**
* Create a new command.
* <p>
* The command will not be registered until {@link this#register()} is called.
* <p>
* The name cannot be the same as an existing command as this will conflict.
*
* @param plugin The plugin.
* @param name The name used in execution.
* @param permission The permission required to execute the command.
* @param playersOnly If only players should be able to execute this command.
*/
protected PluginCommand(@NotNull final EcoPlugin plugin,
@NotNull final String name,
@NotNull final String permission,
final boolean playersOnly) {
super(plugin, name, permission, playersOnly);
}
/**
* Registers the command with the server,
* <p>
* Requires the command name to exist, defined in plugin.yml.
*/
public final void register() {
org.bukkit.command.PluginCommand command = Bukkit.getPluginCommand(this.getName());
assert command != null;
command.setExecutor(this);
command.setTabCompleter(this);
}
/**
* Internal implementation used to clean up boilerplate.
* Used for parity with {@link CommandExecutor#onCommand(CommandSender, Command, String, String[])}.
*
* @param sender The executor of the command.
* @param command The bukkit command.
* @param label The name of the executed command.
* @param args The arguments of the command (anything after the physical command name)
* @return If the command was processed by the linked {@link EcoPlugin}
*/
@Override
public final boolean onCommand(@NotNull final CommandSender sender,
@NotNull final Command command,
@NotNull final String label,
@NotNull final String[] args) {
if (!command.getName().equalsIgnoreCase(this.getName())) {
return false;
}
this.handle(sender, args);
return true;
}
/**
* Internal implementation used to clean up boilerplate.
* Used for parity with {@link TabCompleter#onTabComplete(CommandSender, Command, String, String[])}.
*
* @param sender The executor of the command.
* @param command The bukkit command.
* @param label The name of the executed command.
* @param args The arguments of the command (anything after the physical command name).
* @return The list of tab-completions.
*/
@Override
public @Nullable List<String> onTabComplete(@NotNull final CommandSender sender,
@NotNull final Command command,
@NotNull final String label,
@NotNull final String[] args) {
if (!command.getName().equalsIgnoreCase(this.getName())) {
return null;
}
return this.handleTabCompletion(sender, args);
}
}

View File

@@ -0,0 +1,36 @@
package com.willfp.eco.core.command.impl;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.command.CommandBase;
import com.willfp.eco.internal.commands.HandledCommand;
import org.jetbrains.annotations.NotNull;
public abstract class Subcommand extends HandledCommand {
/**
* Create subcommand.
*
* @param plugin The plugin.
* @param name The subcommand name.
* @param permission The subcommand permission.
* @param playersOnly If the subcommand only works on players.
*/
protected Subcommand(@NotNull final EcoPlugin plugin,
@NotNull final String name,
@NotNull final String permission,
final boolean playersOnly) {
super(plugin, name, permission, playersOnly);
}
/**
* Create subcommand.
*
* @param plugin The plugin.
* @param name The name of the subcommand.
* @param parent The parent command.
*/
protected Subcommand(@NotNull final EcoPlugin plugin,
@NotNull final String name,
@NotNull final CommandBase parent) {
super(plugin, name, parent.getPermission(), parent.isPlayersOnly());
}
}

View File

@@ -1,6 +1,6 @@
package com.willfp.eco.core.config; package com.willfp.eco.core.config;
import com.willfp.eco.internal.config.UpdatableYamlConfig; import com.willfp.eco.internal.config.yaml.UpdatableYamlConfig;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@@ -11,6 +11,13 @@ public interface Config {
*/ */
void clearCache(); void clearCache();
/**
* Convert the config into readable text.
*
* @return The plaintext.
*/
String toPlaintext();
/** /**
* Get if the config contains a key. * Get if the config contains a key.
* *

View File

@@ -0,0 +1,35 @@
package com.willfp.eco.core.config;
import com.willfp.eco.internal.config.LoadableConfig;
import org.jetbrains.annotations.NotNull;
public interface ConfigHandler {
/**
* Invoke all update methods.
*/
void callUpdate();
/**
* Register an updatable class.
*
* @param updatableClass The class with an update method.
*/
void registerUpdatableClass(@NotNull Class<?> updatableClass);
/**
* Save all configs.
*/
void saveAllConfigs();
/**
* Update all updatable configs.
*/
void updateConfigs();
/**
* Add new config to be saved.
*
* @param config The config.
*/
void addConfig(@NotNull LoadableConfig config);
}

View File

@@ -1,6 +1,6 @@
package com.willfp.eco.core.config; package com.willfp.eco.core.config;
import com.willfp.eco.internal.config.UpdatableYamlConfig; import com.willfp.eco.internal.config.yaml.UpdatableYamlConfig;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@@ -0,0 +1,26 @@
package com.willfp.eco.core.config;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface JSONConfig extends Config {
/**
* Get a list of subsections from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
List<JSONConfig> getSubsections(@NotNull String path);
/**
* Get a list of subsections from config.
*
* @param path The key to fetch the value from.
* @return The found value, or null if not found.
*/
@Nullable
List<JSONConfig> getSubsectionsOrNull(@NotNull String path);
}

View File

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

View File

@@ -1,6 +1,6 @@
package com.willfp.eco.core.config; package com.willfp.eco.core.config;
import com.willfp.eco.internal.config.LoadableYamlConfig; import com.willfp.eco.internal.config.yaml.LoadableYamlConfig;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@@ -1,10 +1,10 @@
package com.willfp.eco.core.config; package com.willfp.eco.core.config;
import com.willfp.eco.internal.config.ConfigWrapper; import com.willfp.eco.internal.config.yaml.YamlConfigWrapper;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public abstract class YamlConfig extends ConfigWrapper<YamlConfiguration> { public abstract class YamlConfig extends YamlConfigWrapper<YamlConfiguration> {
/** /**
* Config implementation for passing YamlConfigurations. * Config implementation for passing YamlConfigurations.
* <p> * <p>

View File

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

View File

@@ -6,7 +6,7 @@ import lombok.Getter;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public abstract class DisplayModule extends PluginDependent { public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
/** /**
* The priority of the module. * The priority of the module.
*/ */
@@ -61,6 +61,6 @@ public abstract class DisplayModule extends PluginDependent {
* @return The plugin name. * @return The plugin name.
*/ */
final String getPluginName() { final String getPluginName() {
return super.getPlugin().getPluginName(); return super.getPlugin().getName();
} }
} }

View File

@@ -0,0 +1,40 @@
package com.willfp.eco.core.events;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerMoveEvent;
import org.jetbrains.annotations.NotNull;
public class PlayerJumpEvent extends PlayerMoveEvent {
/**
* Internal bukkit.
*/
private static final HandlerList HANDLERS = new HandlerList();
/**
* Create a new PlayerJumpEvent.
*
* @param event The PlayerMoveEvent.
*/
public PlayerJumpEvent(@NotNull final PlayerMoveEvent event) {
super(event.getPlayer(), event.getFrom(), event.getTo());
}
/**
* Internal bukkit.
*
* @return The handlers.
*/
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
/**
* Internal bukkit.
*
* @return The handlers.
*/
public static @NotNull HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@@ -71,7 +71,7 @@ public abstract class Extension {
*/ */
public final String getName() { public final String getName() {
Validate.notNull(metadata, "Metadata cannot be null!"); Validate.notNull(metadata, "Metadata cannot be null!");
return this.metadata.getName(); return this.metadata.name();
} }
/** /**
@@ -81,6 +81,6 @@ public abstract class Extension {
*/ */
public final String getVersion() { public final String getVersion() {
Validate.notNull(metadata, "Metadata cannot be null!"); Validate.notNull(metadata, "Metadata cannot be null!");
return this.metadata.getVersion(); return this.metadata.version();
} }
} }

View File

@@ -4,5 +4,11 @@ import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public interface MetadataValueFactory { public interface MetadataValueFactory {
/**
* Create a metadata value for a given plugin and object.
*
* @param value The object to store in metadata.
* @return The metadata value.
*/
FixedMetadataValue create(@NotNull Object value); FixedMetadataValue create(@NotNull Object value);
} }

View File

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

View File

@@ -0,0 +1,146 @@
package com.willfp.eco.core.gui.menu;
import com.willfp.eco.core.gui.slot.Slot;
import com.willfp.eco.internal.gui.EcoMenu;
import com.willfp.eco.internal.gui.FillerSlot;
import com.willfp.eco.util.ListUtils;
import com.willfp.eco.util.StringUtils;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.function.Consumer;
public interface Menu {
/**
* Get the amount of rows.
*
* @return The amount of rows.
*/
int getRows();
/**
* Get slot at given row and column.
*
* @param row The row.
* @param column The column.
* @return The row.
*/
Slot getSlot(int row,
int column);
/**
* Get the menu title.
*
* @return The title.
*/
String getTitle();
/**
* Open the inventory for the player.
*
* @param player The player.
* @return The inventory.
*/
Inventory open(@NotNull Player player);
/**
* Create a builder with a given amount of rows.
*
* @param rows The rows.
* @return The builder.
*/
static Builder builder(final int rows) {
return new Builder(rows);
}
class Builder {
/**
* The amount of rows.
*/
private final int rows;
/**
* The title.
*/
private String title = "Menu";
/**
* The mask slots.
*/
private List<List<Slot>> maskSlots;
/**
* The slots.
*/
private final List<List<Slot>> slots;
/**
* The close event handler.
*/
private Consumer<InventoryCloseEvent> onClose = (event) -> {
};
Builder(final int rows) {
this.rows = rows;
this.slots = ListUtils.create2DList(rows, 9);
this.maskSlots = ListUtils.create2DList(rows, 9);
}
public Builder setTitle(@NotNull final String title) {
this.title = StringUtils.translate(title);
return this;
}
public Builder setSlot(final int row,
final int column,
@NotNull final Slot slot) {
if (row < 1 || row > this.rows) {
throw new IllegalArgumentException("Invalid row number!");
}
if (column < 1 || column > 9) {
throw new IllegalArgumentException("Invalid column number!");
}
slots.get(row - 1).set(column - 1, slot);
return this;
}
public Builder setMask(@NotNull final FillerMask mask) {
this.maskSlots = mask.getMask();
return this;
}
public Builder onClose(@NotNull final Consumer<InventoryCloseEvent> action) {
this.onClose = action;
return this;
}
public Menu build() {
List<List<Slot>> finalSlots = maskSlots;
for (int i = 0; i < slots.size(); i++) {
for (int j = 0; j < slots.get(i).size(); j++) {
Slot slot = slots.get(i).get(j);
if (slot != null) {
finalSlots.get(i).set(j, slot);
}
}
}
for (List<Slot> finalSlot : finalSlots) {
for (int j = 0; j < finalSlot.size(); j++) {
if (finalSlot.get(j) == null) {
finalSlot.set(j, new FillerSlot(new ItemStack(Material.AIR)));
}
}
}
return new EcoMenu(rows, finalSlots, title, onClose);
}
}
}

View File

@@ -0,0 +1,105 @@
package com.willfp.eco.core.gui.slot;
import com.willfp.eco.internal.gui.EcoSlot;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.function.BiConsumer;
import java.util.function.Function;
public interface Slot {
/**
* Get the ItemStack that would be shown to a player.
*
* @param player The player.
* @return The ItemStack.
*/
ItemStack getItemStack(@NotNull Player player);
/**
* Create a builder for an ItemStack.
*
* @param itemStack The ItemStack.
* @return The builder.
*/
static Builder builder(@NotNull final ItemStack itemStack) {
return new Builder((player) -> itemStack);
}
/**
* Create a builder for a player-specific ItemStack.
*
* @param provider The provider.
* @return The builder.
*/
static Builder builder(@NotNull final Function<Player, ItemStack> provider) {
return new Builder(provider);
}
class Builder {
/**
* Provider.
*/
private final Function<Player, ItemStack> provider;
/**
* Left click handler.
*/
private BiConsumer<InventoryClickEvent, Slot> onLeftClick = null;
/**
* Right click handler.
*/
private BiConsumer<InventoryClickEvent, Slot> onRightClick = null;
/**
* Shift-Left-Click handler.
*/
private BiConsumer<InventoryClickEvent, Slot> onShiftLeftClick = null;
/**
* Shift-Right-Click handler.
*/
private BiConsumer<InventoryClickEvent, Slot> onShiftRightClick = null;
/**
* Middle click handler.
*/
private BiConsumer<InventoryClickEvent, Slot> onMiddleClick = null;
Builder(@NotNull final Function<Player, ItemStack> provider) {
this.provider = provider;
}
public Builder onLeftClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
this.onLeftClick = action;
return this;
}
public Builder onRightClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
this.onRightClick = action;
return this;
}
public Builder onShiftLeftClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
this.onShiftLeftClick = action;
return this;
}
public Builder onShiftRightClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
this.onShiftRightClick = action;
return this;
}
public Builder onMiddleClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
this.onMiddleClick = action;
return this;
}
public Slot build() {
return new EcoSlot(provider, onLeftClick, onRightClick, onShiftLeftClick, onShiftRightClick, onMiddleClick);
}
}
}

View File

@@ -52,7 +52,7 @@ public class PlaceholderManager {
public static String getResult(@Nullable final Player player, public static String getResult(@Nullable final Player player,
@NotNull final String identifier) { @NotNull final String identifier) {
Optional<PlaceholderEntry> matching = REGISTERED_PLACEHOLDERS.stream().filter(expansion -> expansion.getIdentifier().equalsIgnoreCase(identifier)).findFirst(); Optional<PlaceholderEntry> matching = REGISTERED_PLACEHOLDERS.stream().filter(expansion -> expansion.getIdentifier().equalsIgnoreCase(identifier)).findFirst();
if (!matching.isPresent()) { if (matching.isEmpty()) {
return null; return null;
} }
PlaceholderEntry entry = matching.get(); PlaceholderEntry entry = matching.get();

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.items;
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.TestableStack;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
@@ -40,6 +41,7 @@ public final class Items {
*/ */
public TestableItem lookup(@NotNull final String key) { public TestableItem lookup(@NotNull final String key) {
String[] split = key.toLowerCase().split(":"); String[] split = key.toLowerCase().split(":");
if (split.length == 1) { if (split.length == 1) {
Material material = Material.getMaterial(key.toUpperCase()); Material material = Material.getMaterial(key.toUpperCase());
if (material == null || material == Material.AIR) { if (material == null || material == Material.AIR) {
@@ -48,8 +50,26 @@ public final class Items {
return new MaterialTestableItem(material); return new MaterialTestableItem(material);
} }
if (split.length == 2) {
CustomItem part = REGISTRY.get(new NamespacedKey(split[0], split[1])); CustomItem part = REGISTRY.get(new NamespacedKey(split[0], split[1]));
return part == null ? new EmptyTestableItem() : part;
if (part == null) {
Material material = Material.getMaterial(split[0].toUpperCase());
if (material == null || material == Material.AIR) {
return new EmptyTestableItem();
}
return new TestableStack(new MaterialTestableItem(material), Integer.parseInt(split[1]));
} else {
return part;
}
}
if (split.length == 3) {
CustomItem part = REGISTRY.get(new NamespacedKey(split[0], split[1]));
return part == null ? new EmptyTestableItem() : new TestableStack(part, Integer.parseInt(split[2]));
}
return new EmptyTestableItem();
} }
/** /**

View File

@@ -0,0 +1,29 @@
package com.willfp.eco.core.items.builder;
import com.willfp.eco.internal.items.AbstractItemStackBuilder;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.jetbrains.annotations.NotNull;
public class EnchantedBookBuilder extends AbstractItemStackBuilder<EnchantmentStorageMeta, EnchantedBookBuilder> {
/**
* Create a new EnchantedBookBuilder.
*/
public EnchantedBookBuilder() {
super(Material.ENCHANTED_BOOK);
}
/**
* Add an enchantment to the item.
*
* @param enchantment The enchantment.
* @param level The level.
* @return The builder.
*/
public EnchantedBookBuilder addStoredEnchantment(@NotNull final Enchantment enchantment,
final int level) {
this.getMeta().addStoredEnchant(enchantment, level, true);
return this;
}
}

View File

@@ -0,0 +1,181 @@
package com.willfp.eco.core.items.builder;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.function.Supplier;
public interface ItemBuilder {
/**
* Set the ItemStack amount.
*
* @param amount The amount.
* @return The builder.
*/
ItemBuilder setAmount(int amount);
/**
* Set the ItemStack amount.
*
* @param amount The amount.
* @return The builder.
*/
ItemBuilder setAmount(@NotNull Supplier<Integer> amount);
/**
* Add an enchantment to the item.
*
* @param enchantment The enchantment.
* @param level The level.
* @return The builder.r
*/
ItemBuilder addEnchantment(@NotNull Enchantment enchantment,
int level);
/**
* Add an enchantment to the item.
*
* @param enchantment The enchantment.
* @param level The level.
* @return The builder.
*/
ItemBuilder addEnchantment(@NotNull Supplier<Enchantment> enchantment,
@NotNull Supplier<Integer> level);
/**
* Set the item display name.
*
* @param name The name.
* @return The builder.
*/
ItemBuilder setDisplayName(@NotNull String name);
/**
* Set the item display name.
*
* @param name The name.
* @return The builder.
*/
ItemBuilder setDisplayName(@NotNull Supplier<String> name);
/**
* Add lore line.
*
* @param line The line.
* @return The builder.
*/
ItemBuilder addLoreLine(@NotNull String line);
/**
* Add lore line.
*
* @param line The line.
* @return The builder.
*/
ItemBuilder addLoreLine(@NotNull Supplier<String> line);
/**
* Add lore lines.
*
* @param lines The lines.
* @return The builder.
*/
ItemBuilder addLoreLines(@NotNull List<String> lines);
/**
* Add lore lines.
*
* @param lines The lines.
* @return The builder.
*/
ItemBuilder addLoreLines(@NotNull Supplier<List<String>> lines);
/**
* Add ItemFlags.
*
* @param itemFlags The flags.
* @return The builder.
*/
ItemBuilder addItemFlag(@NotNull ItemFlag... itemFlags);
/**
* Add ItemFlags.
*
* @param itemFlags The flags.
* @return The builder.
*/
ItemBuilder addItemFlag(@NotNull Supplier<ItemFlag[]> itemFlags);
/**
* Write meta key.
*
* @param key The key.
* @param type The type.
* @param value The value.
* @param <A> The type.
* @param <B> The type.
* @return The builder.
*/
<A, B> ItemBuilder writeMetaKey(@NotNull NamespacedKey key,
@NotNull PersistentDataType<A, B> type,
@NotNull B value);
/**
* Write meta key.
*
* @param key The key.
* @param type The type.
* @param value The value.
* @param <A> The type.
* @param <B> The type.
* @return The builder.
*/
<A, B> ItemBuilder writeMetaKey(@NotNull Supplier<NamespacedKey> key,
@NotNull Supplier<PersistentDataType<A, B>> type,
@NotNull Supplier<B> value);
/**
* Set unbreakable.
*
* @param unbreakable If the item should be unbreakable.
* @return The builder.
*/
ItemBuilder setUnbreakable(boolean unbreakable);
/**
* Set unbreakable.
*
* @param unbreakable If the item should be unbreakable.
* @return The builder.
*/
ItemBuilder setUnbreakable(@NotNull Supplier<Boolean> unbreakable);
/**
* Set custom model data.
*
* @param data The data.
* @return The builder.
*/
ItemBuilder setCustomModelData(@Nullable Integer data);
/**
* Set custom model data.
*
* @param data The data.
* @return The builder.
*/
ItemBuilder setCustomModelData(@NotNull Supplier<Integer> data);
/**
* Build the item.
*
* @return The item.
*/
ItemStack build();
}

View File

@@ -0,0 +1,27 @@
package com.willfp.eco.core.items.builder;
import com.willfp.eco.internal.items.AbstractItemStackBuilder;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
public class ItemStackBuilder extends AbstractItemStackBuilder<ItemMeta, ItemStackBuilder> {
/**
* Create a new ItemStackBuilder.
*
* @param material The material.
*/
public ItemStackBuilder(@NotNull final Material material) {
super(material);
}
/**
* Create a new ItemStackBuilder to modify an existing item.
*
* @param base The ItemStack to start with.
*/
public ItemStackBuilder(@NotNull final ItemStack base) {
super(base);
}
}

View File

@@ -0,0 +1,41 @@
package com.willfp.eco.core.items.builder;
import com.willfp.eco.internal.items.AbstractItemStackBuilder;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.jetbrains.annotations.NotNull;
public class LeatherArmorBuilder extends AbstractItemStackBuilder<LeatherArmorMeta, LeatherArmorBuilder> {
/**
* Create a new ItemStackBuilder.
*
* @param material The material.
*/
public LeatherArmorBuilder(@NotNull final Material material) {
super(material);
}
/**
* Create a new ItemStackBuilder to modify an existing item.
*
* @param base The ItemStack to start with.
*/
public LeatherArmorBuilder(@NotNull final ItemStack base) {
super(base);
}
/**
* Set leather color.
*
* @param color The color.
* @return The builder.
*/
public LeatherArmorBuilder setColor(@NotNull final java.awt.Color color) {
Color bukkitColor = Color.fromRGB(color.getRed(), color.getGreen(), color.getBlue());
this.getMeta().setColor(bukkitColor);
return this;
}
}

View File

@@ -0,0 +1,28 @@
package com.willfp.eco.core.items.builder;
import com.willfp.eco.internal.items.AbstractItemStackBuilder;
import com.willfp.eco.util.SkullUtils;
import org.bukkit.Material;
import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.NotNull;
public class SkullBuilder extends AbstractItemStackBuilder<SkullMeta, SkullBuilder> {
/**
* Create a new EnchantedBookBuilder.
*/
public SkullBuilder() {
super(Material.PLAYER_HEAD);
}
/**
* Set skull texture.
*
* @param texture The texture.
* @return The builder.
*/
public SkullBuilder setSkullTexture(@NotNull final String texture) {
SkullUtils.setSkullTexture(this.getMeta(), texture);
return this;
}
}

View File

@@ -2,13 +2,18 @@ package com.willfp.eco.core.recipe;
import com.google.common.collect.BiMap; import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap; import com.google.common.collect.HashBiMap;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.items.Items;
import com.willfp.eco.core.recipe.recipes.CraftingRecipe; import com.willfp.eco.core.recipe.recipes.CraftingRecipe;
import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.List;
@UtilityClass @UtilityClass
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class Recipes { public class Recipes {
@@ -59,4 +64,29 @@ public class Recipes {
return null; return null;
} }
/**
* Create and register recipe.
*
* @param plugin The plugin.
* @param key The key.
* @param output The output.
* @param recipeStrings The recipe.
* @return The recipe.
*/
public CraftingRecipe createAndRegisterRecipe(@NotNull final EcoPlugin plugin,
@NotNull final String key,
@NotNull final ItemStack output,
@NotNull final List<String> recipeStrings) {
ShapedCraftingRecipe.Builder builder = ShapedCraftingRecipe.builder(plugin, key).setOutput(output);
for (int i = 0; i < 9; i++) {
builder.setRecipePart(i, Items.lookup(recipeStrings.get(i)));
}
ShapedCraftingRecipe recipe = builder.build();
recipe.register();
return recipe;
}
} }

View File

@@ -0,0 +1,70 @@
package com.willfp.eco.core.recipe.parts;
import com.willfp.eco.core.items.TestableItem;
import com.willfp.eco.internal.Internals;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class TestableStack implements TestableItem {
/**
* The item.
*/
private final TestableItem handle;
/**
* The amount.
*/
@Getter
private final int amount;
/**
* Create a new testable stack.
*
* @param item The item.
* @param amount The amount.
*/
public TestableStack(@NotNull final TestableItem item,
final int amount) {
Validate.isTrue(!(item instanceof TestableStack));
this.handle = item;
this.amount = amount;
}
/**
* If the item matches the material.
*
* @param itemStack The item to test.
* @return If the item is of the specified material.
*/
@Override
public boolean matches(@Nullable final ItemStack itemStack) {
return itemStack != null && handle.matches(itemStack) && itemStack.getAmount() >= amount;
}
@Override
public ItemStack getItem() {
ItemStack temp = handle.getItem().clone();
ItemMeta meta = temp.getItemMeta();
assert meta != null;
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
assert lore != null;
lore.add("");
String add = Internals.getInstance().getPlugin().getLangYml().getString("multiple-in-craft");
add = add.replace("%amount%", String.valueOf(amount));
lore.add(add);
meta.setLore(lore);
temp.setItemMeta(meta);
temp.setAmount(amount);
return temp;
}
}

View File

@@ -17,8 +17,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@SuppressWarnings("deprecation") public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> implements CraftingRecipe {
public final class ShapedCraftingRecipe extends PluginDependent implements CraftingRecipe {
/** /**
* Recipe parts. * Recipe parts.
*/ */

View File

@@ -0,0 +1,100 @@
package com.willfp.eco.core.web;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class Paste {
/**
* The contents.
*/
@Getter
private final String contents;
/**
* Create a new paste.
*
* @param contents The contents.
*/
public Paste(@NotNull final String contents) {
this.contents = contents;
}
/**
* Upload to hastebin and get a token.
*
* @return The token.
*/
public String getHastebinToken() {
try {
String url = "https://hastebin.com/documents";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(URLEncoder.encode(contents, StandardCharsets.UTF_8));
wr.flush();
wr.close();
BufferedReader iny = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String output;
StringBuilder responseBuilder = new StringBuilder();
while ((output = iny.readLine()) != null) {
responseBuilder.append(output);
}
iny.close();
String responseString = responseBuilder.toString();
responseString = responseString.replace("{\"key\":\"", "");
responseString = responseString.replace("\"}", "");
return responseString;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
/**
* Get paste from hastebin.
*
* @param token The token.
* @return The paste.
*/
public static Paste getFromHastebin(@NotNull final String token) {
try {
StringBuilder result = new StringBuilder();
URL url = new URL("https://hastebin.com/raw/" + token);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
try (var reader = new BufferedReader(
new InputStreamReader(conn.getInputStream()))) {
for (String line; (line = reader.readLine()) != null;) {
result.append(line);
}
}
return new Paste(URLDecoder.decode(result.toString(), StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -0,0 +1,18 @@
package com.willfp.eco.internal;
import com.willfp.eco.core.EcoPlugin;
import org.jetbrains.annotations.NotNull;
public abstract class Internals {
private static Internals internals;
public static void setInterfacing(@NotNull final Internals internals) {
Internals.internals = internals;
}
public abstract EcoPlugin getPlugin();
public static Internals getInstance() {
return internals;
}
}

View File

@@ -10,7 +10,7 @@ import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.Scanner; import java.util.Scanner;
public class UpdateChecker extends PluginDependent { public class UpdateChecker extends PluginDependent<EcoPlugin> {
/** /**
* Create an update checker for the specified spigot resource id. * Create an update checker for the specified spigot resource id.
* *

View File

@@ -13,7 +13,7 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class ArrowDataListener extends PluginDependent implements Listener { public class ArrowDataListener extends PluginDependent<EcoPlugin> implements Listener {
/** /**
* Listener to add metadata to arrows about the enchantments on the bow that shot them. * Listener to add metadata to arrows about the enchantments on the bow that shot them.
* *
@@ -31,15 +31,13 @@ public class ArrowDataListener extends PluginDependent implements Listener {
*/ */
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onLaunch(final ProjectileLaunchEvent event) { public void onLaunch(final ProjectileLaunchEvent event) {
if (!(event.getEntity() instanceof Arrow)) { if (!(event.getEntity() instanceof Arrow arrow)) {
return;
}
if (!(event.getEntity().getShooter() instanceof LivingEntity)) {
return; return;
} }
Arrow arrow = (Arrow) event.getEntity(); if (!(arrow.getShooter() instanceof LivingEntity entity)) {
LivingEntity entity = (LivingEntity) arrow.getShooter(); return;
}
if (entity.getEquipment() == null) { if (entity.getEquipment() == null) {
return; return;

View File

@@ -0,0 +1,166 @@
package com.willfp.eco.internal.commands;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.command.CommandBase;
import com.willfp.eco.core.command.CommandHandler;
import com.willfp.eco.core.command.TabCompleteHandler;
import com.willfp.eco.internal.commands.util.CommandUtils;
import lombok.AccessLevel;
import lombok.Getter;
import org.bukkit.command.CommandSender;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public abstract class HandledCommand extends PluginDependent<EcoPlugin> implements CommandBase {
/**
* The name of the command.
*/
@Getter
private final String name;
/**
* The permission required to execute the command.
* <p>
* Written out as a string for flexibility with subclasses.
*/
@Getter
private final String permission;
/**
* Should the command only be allowed to be executed by players?
* <p>
* In other worlds, only allowed to be executed by console.
*/
@Getter
private final boolean playersOnly;
/**
* All subcommands for the command.
*/
@Getter(AccessLevel.PROTECTED)
private final List<CommandBase> subcommands;
/**
* Create a new command.
* <p>
* The name cannot be the same as an existing command as this will conflict.
*
* @param plugin Instance of a plugin.
* @param name The name used in execution.
* @param permission The permission required to execute the command.
* @param playersOnly If only players should be able to execute this command.
*/
protected HandledCommand(@NotNull final EcoPlugin plugin,
@NotNull final String name,
@NotNull final String permission,
final boolean playersOnly) {
super(plugin);
this.name = name;
this.permission = permission;
this.playersOnly = playersOnly;
this.subcommands = new ArrayList<>();
}
/**
* Add a subcommand to the command.
*
* @param subcommand The subcommand.
* @return The parent command.
*/
@Override
public final CommandBase addSubcommand(@NotNull final CommandBase subcommand) {
subcommands.add(subcommand);
return this;
}
/**
* Handle the command.
*
* @param sender The sender.
* @param args The arguments.
*/
protected final void handle(@NotNull final CommandSender sender,
@NotNull final String[] args) {
if (!CommandUtils.canExecute(sender, this, this.getPlugin())) {
return;
}
if (args.length > 0) {
for (CommandBase subcommand : this.getSubcommands()) {
if (subcommand.getName().equalsIgnoreCase(args[0])) {
if (!CommandUtils.canExecute(sender, subcommand, this.getPlugin())) {
return;
}
((HandledCommand) subcommand).handle(sender, Arrays.copyOfRange(args, 1, args.length));
return;
}
}
}
this.getHandler().onExecute(sender, Arrays.asList(args));
}
/**
* Handle the tab completion.
*
* @param sender The sender.
* @param args The arguments.
*/
protected final List<String> handleTabCompletion(@NotNull final CommandSender sender,
@NotNull final String[] args) {
if (!sender.hasPermission(this.getPermission())) {
return null;
}
if (args.length == 1) {
List<String> completions = new ArrayList<>();
StringUtil.copyPartialMatches(
args[0],
this.getSubcommands().stream().map(CommandBase::getName).collect(Collectors.toList()),
completions
);
Collections.sort(completions);
if (!completions.isEmpty()) {
return completions;
}
}
if (args.length >= 2) {
HandledCommand command = null;
for (CommandBase subcommand : this.getSubcommands()) {
if (args[0].equalsIgnoreCase(subcommand.getName())) {
command = (HandledCommand) subcommand;
}
}
if (command != null) {
return command.handleTabCompletion(sender, Arrays.copyOfRange(args, 1, args.length));
}
}
return this.getTabCompleter().tabComplete(sender, Arrays.asList(args));
}
@Override
public abstract CommandHandler getHandler();
@Override
public TabCompleteHandler getTabCompleter() {
return (sender, args) -> new ArrayList<>();
}
}

View File

@@ -0,0 +1,27 @@
package com.willfp.eco.internal.commands.util;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.command.CommandBase;
import lombok.experimental.UtilityClass;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@UtilityClass
public class CommandUtils {
public boolean canExecute(@NotNull final CommandSender sender,
@NotNull final CommandBase command,
@NotNull final EcoPlugin plugin) {
if (command.isPlayersOnly() && !(sender instanceof Player)) {
sender.sendMessage(plugin.getLangYml().getMessage("not-player"));
return false;
}
if (!sender.hasPermission(command.getPermission()) && sender instanceof Player) {
sender.sendMessage(plugin.getLangYml().getNoPermission());
return false;
}
return true;
}
}

View File

@@ -1,15 +0,0 @@
package com.willfp.eco.internal.config;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
public class ConfigSection extends ConfigWrapper<ConfigurationSection> {
/**
* Config section.
*
* @param section The section.
*/
protected ConfigSection(@NotNull final ConfigurationSection section) {
this.init(section);
}
}

View File

@@ -0,0 +1,39 @@
package com.willfp.eco.internal.config;
import java.io.File;
import java.io.IOException;
public interface LoadableConfig {
/**
* Create the file.
*/
void createFile();
/**
* Get resource path as relative to base directory.
*
* @return The resource path.
*/
String getResourcePath();
/**
* Save the config.
*
* @throws IOException If error in saving.
*/
void save() throws IOException;
/**
* Get the config file.
*
* @return The file.
*/
File getConfigFile();
/**
* Get the config name (including extension)
*
* @return The name.
*/
String getName();
}

View File

@@ -0,0 +1,16 @@
package com.willfp.eco.internal.config.json;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class JsonConfigSection extends JsonConfigWrapper {
/**
* Config section.
*
* @param values The values.
*/
public JsonConfigSection(@NotNull final Map<String, Object> values) {
this.init(values);
}
}

View File

@@ -0,0 +1,345 @@
package com.willfp.eco.internal.config.json;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.willfp.eco.core.config.Config;
import com.willfp.eco.core.config.JSONConfig;
import com.willfp.eco.util.StringUtils;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@SuppressWarnings({"unchecked", "unused"})
public abstract class JsonConfigWrapper implements JSONConfig, Cloneable {
/**
* The linked {@link ConfigurationSection} where values are physically stored.
*/
@Getter
private final Gson handle = new GsonBuilder().setPrettyPrinting().create();
/**
* All stored values.
*/
@Getter
private final Map<String, Object> values = new HashMap<>();
/**
* All cached values.
*/
@Getter
private final Map<String, Object> cache = new HashMap<>();
/**
* Abstract config.
*/
protected JsonConfigWrapper() {
}
public void init(@NotNull final Map<String, Object> values) {
this.values.clear();
this.values.putAll(values);
}
@Override
public final void clearCache() {
cache.clear();
}
@Override
public String toPlaintext() {
return this.getHandle().toJson(this.getValues());
}
@Override
public boolean has(@NotNull final String path) {
return getOfKnownType(path, Object.class) != null;
}
@Nullable
protected <T> T getOfKnownType(@NotNull final String path,
@NotNull final Class<T> clazz) {
return getOfKnownType(path, clazz, true);
}
@Nullable
protected <T> T getOfKnownType(@NotNull final String path,
@NotNull final Class<T> clazz,
final boolean isBase) {
String closestPath = path;
if (cache.containsKey(path) && isBase) {
return (T) cache.get(path);
}
if (path.contains(".")) {
String[] split = path.split("\\.");
closestPath = split[0];
}
if (values.get(closestPath) instanceof Map && !path.equals(closestPath)) {
JsonConfigSection section = new JsonConfigSection((Map<String, Object>) values.get(closestPath));
return section.getOfKnownType(path.substring(closestPath.length() + 1), clazz, false);
} else {
if (values.containsKey(closestPath)) {
return (T) values.get(closestPath);
} else {
return null;
}
}
}
@NotNull
@Override
public List<String> getKeys(final boolean deep) {
if (deep) {
return new ArrayList<>(getDeepKeys(new HashSet<>(), ""));
} else {
return new ArrayList<>(values.keySet());
}
}
protected Set<String> getDeepKeys(@NotNull final Set<String> list,
@NotNull final String root) {
for (String key : values.keySet()) {
list.add(root + key);
if (values.get(key) instanceof Map) {
JsonConfigSection section = new JsonConfigSection((Map<String, Object>) values.get(key));
list.addAll(section.getDeepKeys(list, root + key + "."));
}
}
return list;
}
@Override
@Nullable
public Object get(@NotNull final String path) {
return getOfKnownType(path, Object.class);
}
@Override
public void set(@NotNull final String path,
@Nullable final Object object) {
setRecursively(path, object, true);
clearCache();
}
protected void setRecursively(@NotNull final String path,
@Nullable final Object object,
final boolean isBase) {
String closestPath = path;
if (path.contains(".")) {
String[] split = path.split("\\.");
closestPath = split[0];
}
if (values.get(closestPath) instanceof Map && !path.equals(closestPath)) {
JsonConfigSection section = new JsonConfigSection((Map<String, Object>) values.get(closestPath));
section.setRecursively(path.substring(closestPath.length() + 1), object, false);
values.put(closestPath, section.getValues());
} else {
Object obj = object;
if (object instanceof JSONConfig) {
obj = ((JsonConfigWrapper) object).getValues();
}
values.put(path, obj);
}
}
@Override
@NotNull
public Config getSubsection(@NotNull final String path) {
Config subsection = getSubsectionOrNull(path);
Validate.notNull(subsection);
return subsection;
}
@Override
@Nullable
public Config getSubsectionOrNull(@NotNull final String path) {
if (values.containsKey(path)) {
Map<String, Object> subsection = (Map<String, Object>) values.get(path);
return new JsonConfigSection(subsection);
} else {
return null;
}
}
@Override
@NotNull
public List<JSONConfig> getSubsections(@NotNull final String path) {
List<JSONConfig> subsections = getSubsectionsOrNull(path);
Validate.notNull(subsections);
return subsections;
}
@Override
@Nullable
public List<JSONConfig> getSubsectionsOrNull(@NotNull final String path) {
List<Map<String, Object>> maps = (List<Map<String, Object>>) getOfKnownType(path, Object.class);
if (maps == null) {
return null;
}
List<JSONConfig> configs = new ArrayList<>();
for (Map<String, Object> map : maps) {
configs.add(new JsonConfigSection(map));
}
return configs;
}
@Override
public int getInt(@NotNull final String path) {
// ew
return Objects.requireNonNullElse(getOfKnownType(path, Double.class), 0D).intValue();
}
@Override
@Nullable
public Integer getIntOrNull(@NotNull final String path) {
if (has(path)) {
return getInt(path);
} else {
return null;
}
}
@Override
public int getInt(@NotNull final String path,
final int def) {
return Objects.requireNonNullElse(getOfKnownType(path, Integer.class), def);
}
@Override
@NotNull
public List<Integer> getInts(@NotNull final String path) {
return (List<Integer>) Objects.requireNonNullElse(getOfKnownType(path, Object.class), new ArrayList<>());
}
@Override
@Nullable
public List<Integer> getIntsOrNull(@NotNull final String path) {
if (has(path)) {
return getInts(path);
} else {
return null;
}
}
@Override
public boolean getBool(@NotNull final String path) {
return Objects.requireNonNullElse(getOfKnownType(path, Boolean.class), false);
}
@Override
@Nullable
public Boolean getBoolOrNull(@NotNull final String path) {
if (has(path)) {
return getBool(path);
} else {
return null;
}
}
@Override
@NotNull
public List<Boolean> getBools(@NotNull final String path) {
return (List<Boolean>) Objects.requireNonNullElse(getOfKnownType(path, Object.class), new ArrayList<>());
}
@Override
@Nullable
public List<Boolean> getBoolsOrNull(@NotNull final String path) {
if (has(path)) {
return getBools(path);
} else {
return null;
}
}
@Override
@NotNull
public String getString(@NotNull final String path) {
return StringUtils.translate(Objects.requireNonNullElse(getOfKnownType(path, String.class), ""));
}
@Override
@Nullable
public String getStringOrNull(@NotNull final String path) {
if (has(path)) {
return getString(path);
} else {
return null;
}
}
@Override
@NotNull
public List<String> getStrings(@NotNull final String path) {
return StringUtils.translateList((List<String>) Objects.requireNonNullElse(getOfKnownType(path, Object.class), new ArrayList<>()));
}
@Override
@Nullable
public List<String> getStringsOrNull(@NotNull final String path) {
if (has(path)) {
return getStrings(path);
} else {
return null;
}
}
@Override
public double getDouble(@NotNull final String path) {
return Objects.requireNonNullElse(getOfKnownType(path, Double.class), 0D);
}
@Override
@Nullable
public Double getDoubleOrNull(@NotNull final String path) {
if (has(path)) {
return getDouble(path);
} else {
return null;
}
}
@Override
@NotNull
public List<Double> getDoubles(@NotNull final String path) {
return (List<Double>) Objects.requireNonNullElse(getOfKnownType(path, Object.class), new ArrayList<>());
}
@Override
@Nullable
public List<Double> getDoublesOrNull(@NotNull final String path) {
if (has(path)) {
return getDoubles(path);
} else {
return null;
}
}
@Override
public JSONConfig clone() {
return new JsonConfigSection(new HashMap<>(this.getValues()));
}
}

View File

@@ -0,0 +1,155 @@
package com.willfp.eco.internal.config.json;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.internal.config.LoadableConfig;
import lombok.AccessLevel;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
@SuppressWarnings({"unchecked", "unused"})
public abstract class LoadableJsonConfig extends JsonConfigWrapper implements LoadableConfig {
/**
* The physical config file, as stored on disk.
*/
@Getter
private final File configFile;
/**
* Plugin handle.
*/
@Getter(AccessLevel.PROTECTED)
private final EcoPlugin plugin;
/**
* The full name of the config file (eg config.json).
*/
@Getter
private final String name;
/**
* The subdirectory path.
*/
@Getter(AccessLevel.PROTECTED)
private final String subDirectoryPath;
/**
* The provider of the config.
*/
@Getter(AccessLevel.PROTECTED)
private final Class<?> source;
/**
* Abstract config.
*
* @param configName The name of the config
* @param plugin The plugin.
* @param subDirectoryPath The subdirectory path.
* @param source The class that owns the resource.
*/
protected LoadableJsonConfig(@NotNull final String configName,
@NotNull final EcoPlugin plugin,
@NotNull final String subDirectoryPath,
@NotNull final Class<?> source) {
this.plugin = plugin;
this.name = configName + ".json";
this.source = source;
this.subDirectoryPath = subDirectoryPath;
File directory = new File(this.getPlugin().getDataFolder(), subDirectoryPath);
if (!directory.exists()) {
directory.mkdirs();
}
if (!new File(directory, this.name).exists()) {
createFile();
}
this.configFile = new File(directory, this.name);
try {
init(this.configFile);
} catch (IOException e) {
e.printStackTrace();
}
plugin.getConfigHandler().addConfig(this);
}
@Override
public void createFile() {
String resourcePath = getResourcePath();
InputStream in = source.getResourceAsStream(resourcePath);
File outFile = new File(this.getPlugin().getDataFolder(), resourcePath);
int lastIndex = resourcePath.lastIndexOf('/');
File outDir = new File(this.getPlugin().getDataFolder(), resourcePath.substring(0, Math.max(lastIndex, 0)));
if (!outDir.exists()) {
outDir.mkdirs();
}
try {
if (!outFile.exists()) {
OutputStream out = new FileOutputStream(outFile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.close();
in.close();
}
} catch (IOException ignored) {
}
}
/**
* Get resource path as relative to base directory.
*
* @return The resource path.
*/
@Override
public String getResourcePath() {
String resourcePath;
if (subDirectoryPath.isEmpty()) {
resourcePath = name;
} else {
resourcePath = subDirectoryPath + name;
}
return "/" + resourcePath;
}
/**
* Save the config.
*
* @throws IOException If error in saving.
*/
@Override
public void save() throws IOException {
configFile.delete();
Files.write(configFile.toPath(), this.toPlaintext().getBytes(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
}
/**
* Initialize the config.
*
* @param file The config file.
* @throws FileNotFoundException If the file doesn't exist.
*/
public void init(@NotNull final File file) throws FileNotFoundException {
super.init(this.getHandle().fromJson(new FileReader(file), HashMap.class));
}
}

View File

@@ -1,20 +1,31 @@
package com.willfp.eco.internal.config.updating; package com.willfp.eco.internal.config.updating;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.config.ConfigHandler;
import com.willfp.eco.core.config.ConfigUpdater; import com.willfp.eco.core.config.ConfigUpdater;
import com.willfp.eco.internal.config.LoadableConfig;
import com.willfp.eco.internal.config.updating.exceptions.InvalidUpdatableClassException; import com.willfp.eco.internal.config.updating.exceptions.InvalidUpdatableClassException;
import com.willfp.eco.internal.config.updating.exceptions.InvalidUpdateMethodException; import com.willfp.eco.internal.config.updating.exceptions.InvalidUpdateMethodException;
import com.willfp.eco.core.PluginDependent; import com.willfp.eco.internal.config.yaml.UpdatableYamlConfig;
import com.willfp.eco.core.EcoPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
public class ConfigHandler extends PluginDependent { public class EcoConfigHandler extends PluginDependent<EcoPlugin> implements ConfigHandler {
/**
* A set of all configs that can be saved.
*/
private final List<LoadableConfig> configs = new ArrayList<>();
/** /**
* A set of all classes that can be updated. * A set of all classes that can be updated.
*/ */
@@ -25,25 +36,26 @@ public class ConfigHandler extends PluginDependent {
* *
* @param plugin The plugin to manage. * @param plugin The plugin to manage.
*/ */
public ConfigHandler(@NotNull final EcoPlugin plugin) { public EcoConfigHandler(@NotNull final EcoPlugin plugin) {
super(plugin); super(plugin);
} }
/** @Override
* Invoke all update methods.
*/
public void callUpdate() { public void callUpdate() {
updatableClasses.forEach(clazz -> Arrays.stream(clazz.getDeclaredMethods()).forEach(method -> { updatableClasses.forEach(clazz -> Arrays.stream(clazz.getDeclaredMethods()).forEach(method -> {
if (method.isAnnotationPresent(ConfigUpdater.class)) { if (method.isAnnotationPresent(ConfigUpdater.class)) {
if (method.getParameterTypes().length != 0) {
throw new InvalidUpdateMethodException("Update method must not have parameters.");
}
if (!Modifier.isStatic(method.getModifiers())) { if (!Modifier.isStatic(method.getModifiers())) {
throw new InvalidUpdateMethodException("Update method must be static."); throw new InvalidUpdateMethodException("Update method must be static.");
} }
try { try {
if (method.getParameterCount() == 0) {
method.invoke(null); method.invoke(null);
} else if (method.getParameterCount() == 1) {
method.invoke(null, this.getPlugin());
} else {
throw new InvalidUpdateMethodException("Update method must have 0 parameters or a plugin parameter.");
}
} catch (IllegalAccessException | InvocationTargetException e) { } catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace(); e.printStackTrace();
throw new InvalidUpdateMethodException("Update method generated an exception."); throw new InvalidUpdateMethodException("Update method generated an exception.");
@@ -52,15 +64,11 @@ public class ConfigHandler extends PluginDependent {
})); }));
} }
/** @Override
* Register an updatable class.
*
* @param updatableClass The class with an update method.
*/
public void registerUpdatableClass(@NotNull final Class<?> updatableClass) { public void registerUpdatableClass(@NotNull final Class<?> updatableClass) {
boolean isValid = false; boolean isValid = false;
for (Method method : updatableClass.getDeclaredMethods()) { for (Method method : updatableClass.getDeclaredMethods()) {
if (Modifier.isStatic(method.getModifiers()) && method.getParameterTypes().length == 0 && method.isAnnotationPresent(ConfigUpdater.class)) { if (Modifier.isStatic(method.getModifiers()) && (method.getParameterCount() == 0 || method.getParameterCount() == 1) && method.isAnnotationPresent(ConfigUpdater.class)) {
isValid = true; isValid = true;
break; break;
} }
@@ -72,4 +80,29 @@ public class ConfigHandler extends PluginDependent {
updatableClasses.add(updatableClass); updatableClasses.add(updatableClass);
} }
@Override
public void saveAllConfigs() {
try {
for (LoadableConfig config : configs) {
config.save();
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void addConfig(@NotNull final LoadableConfig config) {
configs.add(config);
}
@Override
public void updateConfigs() {
for (LoadableConfig config : configs) {
if (config instanceof UpdatableYamlConfig updatableYamlConfig) {
updatableYamlConfig.update();
}
}
}
} }

View File

@@ -1,11 +1,11 @@
package com.willfp.eco.internal.config.updating.exceptions; package com.willfp.eco.internal.config.updating.exceptions;
import com.willfp.eco.internal.config.updating.ConfigHandler; import com.willfp.eco.internal.config.updating.EcoConfigHandler;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class InvalidUpdatableClassException extends RuntimeException { public class InvalidUpdatableClassException extends RuntimeException {
/** /**
* Called when an updatable class is registered into an {@link ConfigHandler}. * Called when an updatable class is registered into an {@link EcoConfigHandler}.
* *
* @param message The error message. * @param message The error message.
*/ */

View File

@@ -1,26 +1,23 @@
package com.willfp.eco.internal.config; package com.willfp.eco.internal.config.yaml;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.internal.config.LoadableConfig;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
public abstract class LoadableYamlConfig extends ConfigWrapper<YamlConfiguration> { public abstract class LoadableYamlConfig extends YamlConfigWrapper<YamlConfiguration> implements LoadableConfig {
/** /**
* The physical config file, as stored on disk. * The physical config file, as stored on disk.
*/ */
@Getter(AccessLevel.PROTECTED) @Getter
private final File configFile; private final File configFile;
/** /**
@@ -77,7 +74,8 @@ public abstract class LoadableYamlConfig extends ConfigWrapper<YamlConfiguration
init(YamlConfiguration.loadConfiguration(configFile)); init(YamlConfiguration.loadConfiguration(configFile));
} }
private void createFile() { @Override
public void createFile() {
String resourcePath = getResourcePath(); String resourcePath = getResourcePath();
InputStream in = source.getResourceAsStream(resourcePath); InputStream in = source.getResourceAsStream(resourcePath);
@@ -102,14 +100,12 @@ public abstract class LoadableYamlConfig extends ConfigWrapper<YamlConfiguration
} }
} catch (IOException ignored) { } catch (IOException ignored) {
} }
plugin.getConfigHandler().addConfig(this);
} }
/** @Override
* Get resource path as relative to base directory. public String getResourcePath() {
*
* @return The resource path.
*/
protected String getResourcePath() {
String resourcePath; String resourcePath;
if (subDirectoryPath.isEmpty()) { if (subDirectoryPath.isEmpty()) {
@@ -121,35 +117,7 @@ public abstract class LoadableYamlConfig extends ConfigWrapper<YamlConfiguration
return "/" + resourcePath; return "/" + resourcePath;
} }
/** @Override
* Get YamlConfiguration as found in jar.
*
* @return The YamlConfiguration.
*/
protected YamlConfiguration getConfigInJar() {
InputStream newIn = source.getResourceAsStream(getResourcePath());
if (newIn == null) {
throw new NullPointerException(name + " is null?");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(newIn, StandardCharsets.UTF_8));
YamlConfiguration newConfig = new YamlConfiguration();
try {
newConfig.load(reader);
} catch (IOException | InvalidConfigurationException e) {
e.printStackTrace();
}
return newConfig;
}
/**
* Save the config.
*
* @throws IOException If error in saving.
*/
public void save() throws IOException { public void save() throws IOException {
this.getHandle().save(this.getConfigFile()); this.getHandle().save(this.getConfigFile());
} }

View File

@@ -1,11 +1,15 @@
package com.willfp.eco.internal.config; package com.willfp.eco.internal.config.yaml;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -84,4 +88,23 @@ public abstract class UpdatableYamlConfig extends LoadableYamlConfig {
e.printStackTrace(); e.printStackTrace();
} }
} }
public YamlConfiguration getConfigInJar() {
InputStream newIn = this.getSource().getResourceAsStream(getResourcePath());
if (newIn == null) {
throw new NullPointerException(this.getName() + " is null?");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(newIn, StandardCharsets.UTF_8));
YamlConfiguration newConfig = new YamlConfiguration();
try {
newConfig.load(reader);
} catch (IOException | InvalidConfigurationException e) {
e.printStackTrace();
}
return newConfig;
}
} }

View File

@@ -0,0 +1,15 @@
package com.willfp.eco.internal.config.yaml;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
public class YamlConfigSection extends YamlConfigWrapper<ConfigurationSection> {
/**
* Config section.
*
* @param section The section.
*/
public YamlConfigSection(@NotNull final ConfigurationSection section) {
this.init(section);
}
}

View File

@@ -1,10 +1,11 @@
package com.willfp.eco.internal.config; package com.willfp.eco.internal.config.yaml;
import com.willfp.eco.util.StringUtils;
import com.willfp.eco.core.config.Config; import com.willfp.eco.core.config.Config;
import com.willfp.eco.util.StringUtils;
import lombok.Getter; import lombok.Getter;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -15,7 +16,7 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
@SuppressWarnings({"unchecked", "unused"}) @SuppressWarnings({"unchecked", "unused"})
public abstract class ConfigWrapper<T extends ConfigurationSection> implements Config { public abstract class YamlConfigWrapper<T extends ConfigurationSection> implements Config {
/** /**
* The linked {@link ConfigurationSection} where values are physically stored. * The linked {@link ConfigurationSection} where values are physically stored.
*/ */
@@ -30,7 +31,7 @@ public abstract class ConfigWrapper<T extends ConfigurationSection> implements C
/** /**
* Abstract config. * Abstract config.
*/ */
protected ConfigWrapper() { protected YamlConfigWrapper() {
} }
@@ -39,6 +40,15 @@ public abstract class ConfigWrapper<T extends ConfigurationSection> implements C
return this; return this;
} }
@Override
public String toPlaintext() {
YamlConfiguration temp = new YamlConfiguration();
for (String key : handle.getKeys(true)) {
temp.set(key, handle.get(key));
}
return temp.saveToString();
}
@Override @Override
public final void clearCache() { public final void clearCache() {
cache.clear(); cache.clear();
@@ -64,6 +74,7 @@ public abstract class ConfigWrapper<T extends ConfigurationSection> implements C
@Override @Override
public void set(@NotNull final String path, public void set(@NotNull final String path,
@Nullable final Object object) { @Nullable final Object object) {
cache.remove(path);
handle.set(path, object); handle.set(path, object);
} }
@@ -81,7 +92,12 @@ public abstract class ConfigWrapper<T extends ConfigurationSection> implements C
if (cache.containsKey(path)) { if (cache.containsKey(path)) {
return (Config) cache.get(path); return (Config) cache.get(path);
} else { } else {
cache.put(path, new ConfigSection(Objects.requireNonNull(handle.getConfigurationSection(path)))); ConfigurationSection raw = handle.getConfigurationSection(path);
if (raw == null) {
cache.put(path, null);
} else {
cache.put(path, new YamlConfigSection(raw));
}
return getSubsectionOrNull(path); return getSubsectionOrNull(path);
} }
} }
@@ -204,7 +220,7 @@ public abstract class ConfigWrapper<T extends ConfigurationSection> implements C
@NotNull @NotNull
public List<String> getStrings(@NotNull final String path) { public List<String> getStrings(@NotNull final String path) {
if (cache.containsKey(path)) { if (cache.containsKey(path)) {
return (List<String>) cache.get(path); return StringUtils.translateList((List<String>) cache.get(path));
} else { } else {
cache.put(path, has(path) ? new ArrayList<>(handle.getStringList(path)) : new ArrayList<>()); cache.put(path, has(path) ? new ArrayList<>(handle.getStringList(path)) : new ArrayList<>());
return getStrings(path); return getStrings(path);

View File

@@ -9,7 +9,7 @@ import org.bukkit.event.Listener;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class EcoEventManager extends PluginDependent implements EventManager { public class EcoEventManager extends PluginDependent<EcoPlugin> implements EventManager {
/** /**
* Manager class for event management. * Manager class for event management.
* *

View File

@@ -24,7 +24,7 @@ import java.util.Set;
/** /**
* Concrete implementation of {@link ExtensionLoader}. * Concrete implementation of {@link ExtensionLoader}.
*/ */
public class EcoExtensionLoader extends PluginDependent implements ExtensionLoader { public class EcoExtensionLoader extends PluginDependent<EcoPlugin> implements ExtensionLoader {
/** /**
* All currently loaded extensions. * All currently loaded extensions.
*/ */
@@ -110,11 +110,10 @@ public class EcoExtensionLoader extends PluginDependent implements ExtensionLoad
e.printStackTrace(); e.printStackTrace();
} }
if (!(object instanceof Extension)) { if (!(object instanceof Extension extension)) {
throw new MalformedExtensionException(extensionJar.getName() + " is invalid"); throw new MalformedExtensionException(extensionJar.getName() + " is invalid");
} }
Extension extension = (Extension) object;
extension.setMetadata(metadata); extension.setMetadata(metadata);
extension.enable(); extension.enable();
extensions.add(extension); extensions.add(extension);

View File

@@ -1,32 +1,8 @@
package com.willfp.eco.internal.extensions; package com.willfp.eco.internal.extensions;
import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class ExtensionMetadata { public record ExtensionMetadata(@NotNull String version,
/** @NotNull String name) {
* The version of the extension.
*/
@NotNull
@Getter
private final String version;
/**
* The extension's name.
*/
@NotNull
@Getter
private final String name;
/**
* Create a new extension metadata.
*
* @param version The version for the extension to be.
* @param name The name of the extension.
*/
public ExtensionMetadata(@NotNull final String version,
@NotNull final String name) {
this.version = version;
this.name = name;
}
} }

View File

@@ -6,7 +6,7 @@ import com.willfp.eco.core.factory.MetadataValueFactory;
import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class EcoMetadataValueFactory extends PluginDependent implements MetadataValueFactory { public class EcoMetadataValueFactory extends PluginDependent<EcoPlugin> implements MetadataValueFactory {
/** /**
* Factory class to produce {@link FixedMetadataValue}s associated with an {@link EcoPlugin}. * Factory class to produce {@link FixedMetadataValue}s associated with an {@link EcoPlugin}.
* *

View File

@@ -6,7 +6,7 @@ import com.willfp.eco.core.factory.NamespacedKeyFactory;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class EcoNamespacedKeyFactory extends PluginDependent implements NamespacedKeyFactory { public class EcoNamespacedKeyFactory extends PluginDependent<EcoPlugin> implements NamespacedKeyFactory {
/** /**
* Factory class to produce {@link NamespacedKey}s associated with an {@link EcoPlugin}. * Factory class to produce {@link NamespacedKey}s associated with an {@link EcoPlugin}.
* *

View File

@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer; import java.util.function.Consumer;
public class EcoRunnableFactory extends PluginDependent implements RunnableFactory { public class EcoRunnableFactory extends PluginDependent<EcoPlugin> implements RunnableFactory {
/** /**
* Factory class to produce {@link RunnableTask}s associated with an {@link EcoPlugin}. * Factory class to produce {@link RunnableTask}s associated with an {@link EcoPlugin}.
* *

View File

@@ -0,0 +1,86 @@
package com.willfp.eco.internal.gui;
import com.willfp.eco.core.gui.menu.Menu;
import com.willfp.eco.core.gui.slot.Slot;
import com.willfp.eco.util.StringUtils;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.function.Consumer;
public class EcoMenu implements Menu {
@Getter
private final int rows;
private final List<List<Slot>> slots;
@Getter
private final String title;
private final Consumer<InventoryCloseEvent> onClose;
public EcoMenu(final int rows,
@NotNull final List<List<Slot>> slots,
@NotNull final String title,
@NotNull final Consumer<InventoryCloseEvent> onClose) {
this.rows = rows;
this.slots = slots;
this.title = title;
this.onClose = onClose;
}
@Override
public Slot getSlot(final int row,
final int column) {
if (row < 1 || row > this.rows) {
throw new IllegalArgumentException("Invalid row number!");
}
if (column < 1 || column > 9) {
throw new IllegalArgumentException("Invalid column number!");
}
return slots.get(row - 1).get(column - 1);
}
@Override
public Inventory open(@NotNull final Player player) {
Inventory inventory = Bukkit.createInventory(null, rows * 9, title);
int i = 0;
for (List<Slot> row : slots) {
for (Slot item : row) {
if (i == rows * 9) {
break;
}
ItemStack slotItem = item.getItemStack(player);
ItemMeta meta = slotItem.getItemMeta();
if (meta != null) {
List<String> lore = meta.getLore();
if (lore != null) {
lore.replaceAll(s -> StringUtils.translate(s, player));
meta.setLore(lore);
}
slotItem.setItemMeta(meta);
}
inventory.setItem(i, slotItem);
i++;
}
}
player.openInventory(inventory);
MenuHandler.registerMenu(inventory, this);
return inventory;
}
public void handleClose(@NotNull final InventoryCloseEvent event) {
onClose.accept(event);
}
}

View File

@@ -0,0 +1,57 @@
package com.willfp.eco.internal.gui;
import com.willfp.eco.core.gui.slot.Slot;
import lombok.Getter;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.BiConsumer;
import java.util.function.Function;
public class EcoSlot implements Slot {
@Getter
private final Function<Player, ItemStack> provider;
private final BiConsumer<InventoryClickEvent, Slot> onLeftClick;
private final BiConsumer<InventoryClickEvent, Slot> onRightClick;
private final BiConsumer<InventoryClickEvent, Slot> onShiftLeftClick;
private final BiConsumer<InventoryClickEvent, Slot> onShiftRightClick;
private final BiConsumer<InventoryClickEvent, Slot> onMiddleClick;
public EcoSlot(@NotNull final Function<Player, ItemStack> provider,
@Nullable final BiConsumer<InventoryClickEvent, Slot> onLeftClick,
@Nullable final BiConsumer<InventoryClickEvent, Slot> onRightClick,
@Nullable final BiConsumer<InventoryClickEvent, Slot> onShiftLeftClick,
@Nullable final BiConsumer<InventoryClickEvent, Slot> onShiftRightClick,
@Nullable final BiConsumer<InventoryClickEvent, Slot> onMiddleClick) {
this.provider = provider;
this.onLeftClick = onLeftClick == null ? ((event, slot) -> { }) : onLeftClick;
this.onRightClick = onRightClick == null ? ((event, slot) -> { }) : onRightClick;
this.onShiftLeftClick = onShiftLeftClick == null ? ((event, slot) -> { }) : onShiftLeftClick;
this.onShiftRightClick = onShiftRightClick == null ? ((event, slot) -> { }) : onShiftRightClick;
this.onMiddleClick = onMiddleClick == null ? ((event, slot) -> { }) : onMiddleClick;
}
public void handleInventoryClick(@NotNull final InventoryClickEvent event) {
switch (event.getClick()) {
case LEFT -> this.onLeftClick.accept(event, this);
case RIGHT -> this.onRightClick.accept(event, this);
case SHIFT_LEFT -> this.onShiftLeftClick.accept(event, this);
case SHIFT_RIGHT -> this.onShiftRightClick.accept(event, this);
case MIDDLE -> this.onMiddleClick.accept(event, this);
default -> { }
}
}
@Override
public ItemStack getItemStack(@NotNull final Player player) {
return provider.apply(player);
}
}

View File

@@ -0,0 +1,15 @@
package com.willfp.eco.internal.gui;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class FillerSlot extends EcoSlot {
/**
* Create new filler slot.
*
* @param itemStack The ItemStack.
*/
public FillerSlot(@NotNull final ItemStack itemStack) {
super((player) -> itemStack, null, null, null, null, null);
}
}

View File

@@ -0,0 +1,29 @@
package com.willfp.eco.internal.gui;
import com.willfp.eco.core.gui.menu.Menu;
import lombok.experimental.UtilityClass;
import org.bukkit.inventory.Inventory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
@UtilityClass
public class MenuHandler {
private static final Map<Inventory, Menu> MENUS = new HashMap<>();
public void registerMenu(@NotNull final Inventory inventory,
@NotNull final Menu menu) {
MENUS.put(inventory, menu);
}
public void unregisterMenu(@NotNull final Inventory inventory) {
MENUS.remove(inventory);
}
@Nullable
public Menu getMenu(@NotNull final Inventory inventory) {
return MENUS.get(inventory);
}
}

View File

@@ -0,0 +1,194 @@
package com.willfp.eco.internal.items;
import com.willfp.eco.core.items.builder.ItemBuilder;
import com.willfp.eco.util.StringUtils;
import lombok.AccessLevel;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
@SuppressWarnings("unchecked")
public abstract class AbstractItemStackBuilder<T extends ItemMeta, U extends AbstractItemStackBuilder<T, U>> implements ItemBuilder {
/**
* The ItemMeta used while building.
*/
@Getter(AccessLevel.PROTECTED)
private final T meta;
/**
* The ItemStack.
*/
@Getter(AccessLevel.PROTECTED)
private final ItemStack base;
/**
* Create a new ItemStackBuilder.
*
* @param material The material.
*/
protected AbstractItemStackBuilder(@NotNull final Material material) {
this(new ItemStack(material));
}
/**
* Create a new ItemStackBuilder to modify an existing item.
*
* @param base The ItemStack to start with.
*/
protected AbstractItemStackBuilder(@NotNull final ItemStack base) {
this.base = base;
this.meta = (T) base.getItemMeta();
assert meta != null;
}
@Override
public U setAmount(final int amount) {
Validate.isTrue(amount >= 1 && amount <= base.getMaxStackSize());
base.setAmount(amount);
return (U) this;
}
@Override
public U setAmount(@NotNull final Supplier<Integer> amount) {
return setAmount(amount.get());
}
@Override
public U addEnchantment(@NotNull final Enchantment enchantment,
final int level) {
meta.addEnchant(enchantment, level, true);
return (U) this;
}
@Override
public U addEnchantment(@NotNull final Supplier<Enchantment> enchantment,
@NotNull final Supplier<Integer> level) {
return addEnchantment(enchantment.get(), level.get());
}
@Override
public U setDisplayName(@NotNull final String name) {
meta.setDisplayName(StringUtils.translate(name));
return (U) this;
}
@Override
public U setDisplayName(@NotNull final Supplier<String> name) {
String result = name.get();
return result == null ? (U) this : setDisplayName(name.get());
}
@Override
public U addLoreLine(@NotNull final String line) {
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
assert lore != null;
lore.add(StringUtils.translate(line));
meta.setLore(lore);
return (U) this;
}
@Override
public U addLoreLine(@NotNull final Supplier<String> line) {
String result = line.get();
return result == null ? (U) this : addLoreLine(line.get());
}
@Override
public U addLoreLines(@NotNull final List<String> lines) {
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
assert lore != null;
for (String line : lines) {
lore.add(StringUtils.translate(line));
}
meta.setLore(lore);
return (U) this;
}
@Override
public U addLoreLines(@NotNull final Supplier<List<String>> lines) {
List<String> result = lines.get();
return result == null ? (U) this : addLoreLines(lines.get());
}
@Override
public U addItemFlag(@NotNull final ItemFlag... itemFlags) {
meta.addItemFlags(itemFlags);
return (U) this;
}
@Override
public U addItemFlag(@NotNull final Supplier<ItemFlag[]> itemFlags) {
ItemFlag[] result = itemFlags.get();
return result == null ? (U) this : addItemFlag(result);
}
@Override
public <A, B> U writeMetaKey(@NotNull final NamespacedKey key,
@NotNull final PersistentDataType<A, B> type,
@NotNull final B value) {
meta.getPersistentDataContainer().set(key, type, value);
return (U) this;
}
@Override
public <A, B> U writeMetaKey(@NotNull final Supplier<NamespacedKey> key,
@NotNull final Supplier<PersistentDataType<A, B>> type,
@NotNull final Supplier<B> value) {
return writeMetaKey(key.get(), type.get(), value.get());
}
@Override
public U setUnbreakable(final boolean unbreakable) {
meta.setUnbreakable(unbreakable);
return (U) this;
}
@Override
public U setUnbreakable(@NotNull final Supplier<Boolean> unbreakable) {
Boolean result = unbreakable.get();
return result == null ? (U) this : setUnbreakable(unbreakable);
}
@Override
public U setCustomModelData(@Nullable final Integer data) {
meta.setCustomModelData(data);
return (U) this;
}
@Override
public U setCustomModelData(@NotNull final Supplier<Integer> data) {
Integer result = data.get();
return result == null ? (U) this : setCustomModelData(result);
}
@Override
public ItemStack build() {
base.setItemMeta(meta);
return base;
}
}

View File

@@ -8,7 +8,7 @@ import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class EcoScheduler extends PluginDependent implements Scheduler { public class EcoScheduler extends PluginDependent<EcoPlugin> implements Scheduler {
/** /**
* Create a scheduler to manage the tasks of an {@link EcoPlugin}. * Create a scheduler to manage the tasks of an {@link EcoPlugin}.
* *

View File

@@ -37,15 +37,6 @@ public class BlockUtils {
if (blocks.size() > limit || blocks.size() > 2500) { if (blocks.size() > limit || blocks.size() > 2500) {
return blocks; return blocks;
} }
}
}
// Running twice to get more spherical shape.
for (BlockFace face : BlockFace.values()) {
Block block = start.getRelative(face);
if (!blocks.contains(block) && allowedMaterials.contains(block.getType())) {
if (blocks.size() > limit || blocks.size() > 2500) {
return blocks;
}
blocks.addAll(getNearbyBlocks(block, allowedMaterials, blocks, limit)); blocks.addAll(getNearbyBlocks(block, allowedMaterials, blocks, limit));
} }
} }

View File

@@ -121,8 +121,7 @@ public class DurabilityUtils {
return; return;
} }
if (item.getItemMeta() instanceof Damageable) { if (item.getItemMeta() instanceof Damageable meta) {
Damageable meta = (Damageable) item.getItemMeta();
meta.setDamage(meta.getDamage() - repair); meta.setDamage(meta.getDamage() - repair);
if (meta.getDamage() < 0) { if (meta.getDamage() < 0) {

View File

@@ -0,0 +1,31 @@
package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import java.util.ArrayList;
import java.util.List;
@UtilityClass
public class ListUtils {
/**
* Initialize 2D list of a given size.
*
* @param rows The amount of rows.
* @param columns The amount of columns.
* @param <T> The type of the object stored in the list.
* @return The list, filled will null objects.
*/
public <T> List<List<T>> create2DList(final int rows,
final int columns) {
List<List<T>> list = new ArrayList<>(rows);
while (list.size() < rows) {
List<T> row = new ArrayList<>(columns);
while (row.size() < columns) {
row.add(null);
}
list.add(row);
}
return list;
}
}

View File

@@ -10,20 +10,10 @@ import java.util.concurrent.ThreadLocalRandom;
@UtilityClass @UtilityClass
public class NumberUtils { public class NumberUtils {
/**
* Precision.
*/
private static final int FAST_TRIG_PRECISION = 100;
/**
* Modulus.
*/
private static final int FAST_TRIG_MODULUS = 360 * FAST_TRIG_PRECISION;
/** /**
* Sin lookup table. * Sin lookup table.
*/ */
private static final double[] SIN_LOOKUP = new double[FAST_TRIG_MODULUS]; private static final double[] SIN_LOOKUP = new double[65536];
/** /**
* Set of roman numerals to look up. * Set of roman numerals to look up.
@@ -45,15 +35,11 @@ public class NumberUtils {
NUMERALS.put(4, "IV"); NUMERALS.put(4, "IV");
NUMERALS.put(1, "I"); NUMERALS.put(1, "I");
for (int i = 0; i < SIN_LOOKUP.length; i++) { for (int i = 0; i < 65536; ++i) {
SIN_LOOKUP[i] = Math.sin((i * Math.PI) / (FAST_TRIG_PRECISION * 180)); SIN_LOOKUP[i] = Math.sin((double) i * 3.141592653589793D * 2.0D / 65536.0D);
} }
} }
private static double sinLookup(final int a) {
return a >= 0 ? SIN_LOOKUP[a % FAST_TRIG_MODULUS] : -SIN_LOOKUP[-a % FAST_TRIG_MODULUS];
}
/** /**
* Get the sin of a number. * Get the sin of a number.
* *
@@ -61,7 +47,8 @@ public class NumberUtils {
* @return The sin. * @return The sin.
*/ */
public static double fastSin(final double a) { public static double fastSin(final double a) {
return sinLookup((int) (a * FAST_TRIG_PRECISION + 0.5f)); float f = (float) a;
return SIN_LOOKUP[(int) (f * 10430.378F) & '\uffff'];
} }
/** /**
@@ -71,7 +58,8 @@ public class NumberUtils {
* @return The cosine. * @return The cosine.
*/ */
public static double fastCos(final double a) { public static double fastCos(final double a) {
return sinLookup((int) ((a + 90f) * FAST_TRIG_PRECISION + 0.5f)); float f = (float) a;
return SIN_LOOKUP[(int) (f * 10430.378F + 16384.0F) & '\uffff'];
} }
/** /**

View File

@@ -39,6 +39,33 @@ public class StringUtils {
.add(Pattern.compile("<#" + "([A-Fa-f0-9]{6})" + ">")) .add(Pattern.compile("<#" + "([A-Fa-f0-9]{6})" + ">"))
.build(); .build();
/**
* Translate a list of strings - converts Placeholders and Color codes.
*
* @param list The messages to translate.
* @param player The player to translate placeholders with respect to.
* @return The message, translated.
*/
public List<String> translateList(@NotNull final List<String> list,
@Nullable final Player player) {
List<String> translated = new ArrayList<>();
for (String string : list) {
translated.add(translate(string, player));
}
return translated;
}
/**
* Translate a list of strings - converts Placeholders and Color codes.
*
* @param list The messages to translate.
* @return The message, translated.
*/
public List<String> translateList(@NotNull final List<String> list) {
return translateList(list, null);
}
/** /**
* Translate a string - converts Placeholders and Color codes. * Translate a string - converts Placeholders and Color codes.
* *
@@ -79,16 +106,16 @@ public class StringUtils {
@NotNull final Pattern pattern) { @NotNull final Pattern pattern) {
Matcher matcher = pattern.matcher(message); Matcher matcher = pattern.matcher(message);
StringBuffer buffer = new StringBuffer(message.length() + 4 * 8); StringBuilder builder = new StringBuilder(message.length() + 4 * 8);
while (matcher.find()) { while (matcher.find()) {
String group = matcher.group(1); String group = matcher.group(1);
matcher.appendReplacement(buffer, COLOR_CHAR + "x" matcher.appendReplacement(builder, COLOR_CHAR + "x"
+ COLOR_CHAR + group.charAt(0) + COLOR_CHAR + group.charAt(1) + COLOR_CHAR + group.charAt(0) + COLOR_CHAR + group.charAt(1)
+ COLOR_CHAR + group.charAt(2) + COLOR_CHAR + group.charAt(3) + COLOR_CHAR + group.charAt(2) + COLOR_CHAR + group.charAt(3)
+ COLOR_CHAR + group.charAt(4) + COLOR_CHAR + group.charAt(5)); + COLOR_CHAR + group.charAt(4) + COLOR_CHAR + group.charAt(5));
} }
return matcher.appendTail(buffer).toString(); return matcher.appendTail(builder).toString();
} }
/** /**
@@ -198,8 +225,7 @@ public class StringUtils {
return (String) object; return (String) object;
} else if (object instanceof Double) { } else if (object instanceof Double) {
return NumberUtils.format((Double) object); return NumberUtils.format((Double) object);
} else if (object instanceof Collection<?>) { } else if (object instanceof Collection<?> c) {
Collection<?> c = (Collection<?>) object;
return c.stream().map(StringUtils::internalToString).collect(Collectors.joining(", ")); return c.stream().map(StringUtils::internalToString).collect(Collectors.joining(", "));
} else { } else {
return String.valueOf(object); return String.valueOf(object);

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.util;
import com.google.common.collect.BiMap; import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap; import com.google.common.collect.HashBiMap;
import com.willfp.eco.core.Prerequisite;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
@@ -10,6 +11,8 @@ import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team; import org.bukkit.scoreboard.Team;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@UtilityClass @UtilityClass
@@ -17,7 +20,7 @@ public class TeamUtils {
/** /**
* Ore ChatColors. * Ore ChatColors.
*/ */
private static final BiMap<Material, ChatColor> MATERIAL_COLORS = HashBiMap.create(); private static final Map<Material, ChatColor> MATERIAL_COLORS = new HashMap<>();
/** /**
* All chat color teams. * All chat color teams.
@@ -73,12 +76,25 @@ public class TeamUtils {
fromChatColor(value); fromChatColor(value);
} }
MATERIAL_COLORS.forcePut(Material.COAL_ORE, ChatColor.BLACK); MATERIAL_COLORS.put(Material.COAL_ORE, ChatColor.BLACK);
MATERIAL_COLORS.forcePut(Material.IRON_ORE, ChatColor.GRAY); MATERIAL_COLORS.put(Material.IRON_ORE, ChatColor.GRAY);
MATERIAL_COLORS.forcePut(Material.GOLD_ORE, ChatColor.YELLOW); MATERIAL_COLORS.put(Material.GOLD_ORE, ChatColor.YELLOW);
MATERIAL_COLORS.forcePut(Material.LAPIS_ORE, ChatColor.BLUE); MATERIAL_COLORS.put(Material.LAPIS_ORE, ChatColor.BLUE);
MATERIAL_COLORS.forcePut(Material.REDSTONE_ORE, ChatColor.RED); MATERIAL_COLORS.put(Material.REDSTONE_ORE, ChatColor.RED);
MATERIAL_COLORS.forcePut(Material.DIAMOND_ORE, ChatColor.AQUA); MATERIAL_COLORS.put(Material.DIAMOND_ORE, ChatColor.AQUA);
MATERIAL_COLORS.forcePut(Material.ANCIENT_DEBRIS, ChatColor.DARK_RED); MATERIAL_COLORS.put(Material.EMERALD_ORE, ChatColor.GREEN);
MATERIAL_COLORS.put(Material.ANCIENT_DEBRIS, ChatColor.DARK_RED);
if (Prerequisite.HAS_1_17.isMet()) {
MATERIAL_COLORS.put(Material.COPPER_ORE, ChatColor.GOLD);
MATERIAL_COLORS.put(Material.DEEPSLATE_COPPER_ORE, ChatColor.GOLD);
MATERIAL_COLORS.put(Material.DEEPSLATE_COAL_ORE, ChatColor.BLACK);
MATERIAL_COLORS.put(Material.DEEPSLATE_IRON_ORE, ChatColor.GRAY);
MATERIAL_COLORS.put(Material.DEEPSLATE_GOLD_ORE, ChatColor.YELLOW);
MATERIAL_COLORS.put(Material.DEEPSLATE_LAPIS_ORE, ChatColor.BLUE);
MATERIAL_COLORS.put(Material.DEEPSLATE_REDSTONE_ORE, ChatColor.RED);
MATERIAL_COLORS.put(Material.DEEPSLATE_DIAMOND_ORE, ChatColor.AQUA);
MATERIAL_COLORS.put(Material.DEEPSLATE_EMERALD_ORE, ChatColor.GREEN);
}
} }
} }

View File

@@ -11,6 +11,10 @@ public final class BlockBreak implements BlockBreakProxy {
@Override @Override
public void breakBlock(@NotNull final Player player, public void breakBlock(@NotNull final Player player,
@NotNull final Block block) { @NotNull final Block block) {
if (!(player instanceof CraftPlayer)) {
return;
}
((CraftPlayer) player).getHandle().playerInteractManager.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ())); ((CraftPlayer) player).getHandle().playerInteractManager.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ()));
} }
} }

View File

@@ -22,18 +22,29 @@ import java.util.Arrays;
public final class ChatComponent implements ChatComponentProxy { public final class ChatComponent implements ChatComponentProxy {
@Override @Override
public Object modifyComponent(@NotNull final Object object) { public Object modifyComponent(@NotNull final Object object) {
if (!(object instanceof IChatBaseComponent)) { if (!(object instanceof IChatBaseComponent chatComponent)) {
return object; return object;
} }
IChatBaseComponent chatComponent = (IChatBaseComponent) object; for (IChatBaseComponent iChatBaseComponent : chatComponent) {
chatComponent.stream().forEach(this::modifyBaseComponent); if (iChatBaseComponent == null) {
continue;
}
modifyBaseComponent(iChatBaseComponent);
}
return chatComponent; return chatComponent;
} }
private void modifyBaseComponent(@NotNull final IChatBaseComponent component) { private void modifyBaseComponent(@NotNull final IChatBaseComponent component) {
component.getSiblings().forEach(this::modifyBaseComponent); for (IChatBaseComponent sibling : component.getSiblings()) {
if (sibling == null) {
continue;
}
modifyBaseComponent(sibling);
}
if (component instanceof ChatMessage) { if (component instanceof ChatMessage) {
Arrays.stream(((ChatMessage) component).getArgs()) Arrays.stream(((ChatMessage) component).getArgs())
.filter(o -> o instanceof IChatBaseComponent) .filter(o -> o instanceof IChatBaseComponent)

View File

@@ -1,8 +1,7 @@
package com.willfp.eco.proxy.v1_16_R1; package com.willfp.eco.proxy.v1_16_R1;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import com.willfp.eco.core.display.Display; import com.willfp.eco.core.display.Display;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack; import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftMerchantRecipe; import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftMerchantRecipe;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe; import org.bukkit.inventory.MerchantRecipe;
@@ -11,30 +10,56 @@ import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field; import java.lang.reflect.Field;
public final class VillagerTrade implements VillagerTradeProxy { public final class VillagerTrade implements VillagerTradeProxy {
@Override /**
public void displayTrade(@NotNull final MerchantRecipe merchantRecipe) { * Handle.
*/
private final Field handle;
/**
* Create new Villager Trade.
*/
public VillagerTrade() {
try { try {
// Bukkit MerchantRecipe result handle = CraftMerchantRecipe.class.getDeclaredField("handle");
Field fResult = MerchantRecipe.class.getDeclaredField("result"); handle.setAccessible(true);
fResult.setAccessible(true); return;
ItemStack result = merchantRecipe.getResult(); } catch (NoSuchFieldException e) {
Display.displayAndFinalize(result);
fResult.set(merchantRecipe, result);
// Get NMS MerchantRecipe from CraftMerchantRecipe
Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle");
fHandle.setAccessible(true);
net.minecraft.server.v1_16_R1.MerchantRecipe handle = (net.minecraft.server.v1_16_R1.MerchantRecipe) fHandle.get(merchantRecipe); // NMS Recipe
Field fSelling = net.minecraft.server.v1_16_R1.MerchantRecipe.class.getDeclaredField("sellingItem");
fSelling.setAccessible(true);
ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem);
Display.displayAndFinalize(selling);
fSelling.set(handle, CraftItemStack.asNMSCopy(selling));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace(); e.printStackTrace();
} }
throw new RuntimeException("Error!");
}
@Override
public MerchantRecipe displayTrade(@NotNull final MerchantRecipe recipe) {
CraftMerchantRecipe oldRecipe = (CraftMerchantRecipe) recipe;
CraftMerchantRecipe newRecipe = new CraftMerchantRecipe(
Display.display(recipe.getResult().clone()),
recipe.getUses(),
recipe.getMaxUses(),
recipe.hasExperienceReward(),
recipe.getVillagerExperience(),
recipe.getPriceMultiplier()
);
for (ItemStack ingredient : recipe.getIngredients()) {
newRecipe.addIngredient(Display.display(ingredient.clone()));
}
getHandle(newRecipe).setSpecialPrice(getHandle(oldRecipe).getSpecialPrice());
return newRecipe;
}
@NotNull
private net.minecraft.server.v1_16_R1.MerchantRecipe getHandle(@NotNull final CraftMerchantRecipe recipe) {
try {
return (net.minecraft.server.v1_16_R1.MerchantRecipe) handle.get(recipe);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
throw new IllegalArgumentException("Not CMR");
} }
} }

View File

@@ -11,6 +11,10 @@ public final class BlockBreak implements BlockBreakProxy {
@Override @Override
public void breakBlock(@NotNull final Player player, public void breakBlock(@NotNull final Player player,
@NotNull final Block block) { @NotNull final Block block) {
if (!(player instanceof CraftPlayer)) {
return;
}
((CraftPlayer) player).getHandle().playerInteractManager.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ())); ((CraftPlayer) player).getHandle().playerInteractManager.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ()));
} }
} }

View File

@@ -22,18 +22,29 @@ import java.util.Arrays;
public final class ChatComponent implements ChatComponentProxy { public final class ChatComponent implements ChatComponentProxy {
@Override @Override
public Object modifyComponent(@NotNull final Object object) { public Object modifyComponent(@NotNull final Object object) {
if (!(object instanceof IChatBaseComponent)) { if (!(object instanceof IChatBaseComponent chatComponent)) {
return object; return object;
} }
IChatBaseComponent chatComponent = (IChatBaseComponent) object; for (IChatBaseComponent iChatBaseComponent : chatComponent) {
chatComponent.stream().forEach(this::modifyBaseComponent); if (iChatBaseComponent == null) {
continue;
}
modifyBaseComponent(iChatBaseComponent);
}
return chatComponent; return chatComponent;
} }
private void modifyBaseComponent(@NotNull final IChatBaseComponent component) { private void modifyBaseComponent(@NotNull final IChatBaseComponent component) {
component.getSiblings().forEach(this::modifyBaseComponent); for (IChatBaseComponent sibling : component.getSiblings()) {
if (sibling == null) {
continue;
}
modifyBaseComponent(sibling);
}
if (component instanceof ChatMessage) { if (component instanceof ChatMessage) {
Arrays.stream(((ChatMessage) component).getArgs()) Arrays.stream(((ChatMessage) component).getArgs())
.filter(o -> o instanceof IChatBaseComponent) .filter(o -> o instanceof IChatBaseComponent)

View File

@@ -1,8 +1,7 @@
package com.willfp.eco.proxy.v1_16_R2; package com.willfp.eco.proxy.v1_16_R2;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import com.willfp.eco.core.display.Display; import com.willfp.eco.core.display.Display;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack; import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftMerchantRecipe; import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftMerchantRecipe;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe; import org.bukkit.inventory.MerchantRecipe;
@@ -11,30 +10,56 @@ import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field; import java.lang.reflect.Field;
public final class VillagerTrade implements VillagerTradeProxy { public final class VillagerTrade implements VillagerTradeProxy {
@Override /**
public void displayTrade(@NotNull final MerchantRecipe merchantRecipe) { * Handle.
*/
private final Field handle;
/**
* Create new Villager Trade.
*/
public VillagerTrade() {
try { try {
// Bukkit MerchantRecipe result handle = CraftMerchantRecipe.class.getDeclaredField("handle");
Field fResult = MerchantRecipe.class.getDeclaredField("result"); handle.setAccessible(true);
fResult.setAccessible(true); return;
ItemStack result = merchantRecipe.getResult(); } catch (NoSuchFieldException e) {
Display.displayAndFinalize(result);
fResult.set(merchantRecipe, result);
// Get NMS MerchantRecipe from CraftMerchantRecipe
Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle");
fHandle.setAccessible(true);
net.minecraft.server.v1_16_R2.MerchantRecipe handle = (net.minecraft.server.v1_16_R2.MerchantRecipe) fHandle.get(merchantRecipe); // NMS Recipe
Field fSelling = net.minecraft.server.v1_16_R2.MerchantRecipe.class.getDeclaredField("sellingItem");
fSelling.setAccessible(true);
ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem);
Display.displayAndFinalize(selling);
fSelling.set(handle, CraftItemStack.asNMSCopy(selling));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace(); e.printStackTrace();
} }
throw new RuntimeException("Error!");
}
@Override
public MerchantRecipe displayTrade(@NotNull final MerchantRecipe recipe) {
CraftMerchantRecipe oldRecipe = (CraftMerchantRecipe) recipe;
CraftMerchantRecipe newRecipe = new CraftMerchantRecipe(
Display.display(recipe.getResult().clone()),
recipe.getUses(),
recipe.getMaxUses(),
recipe.hasExperienceReward(),
recipe.getVillagerExperience(),
recipe.getPriceMultiplier()
);
for (ItemStack ingredient : recipe.getIngredients()) {
newRecipe.addIngredient(Display.display(ingredient.clone()));
}
getHandle(newRecipe).setSpecialPrice(getHandle(oldRecipe).getSpecialPrice());
return newRecipe;
}
@NotNull
private net.minecraft.server.v1_16_R2.MerchantRecipe getHandle(@NotNull final CraftMerchantRecipe recipe) {
try {
return (net.minecraft.server.v1_16_R2.MerchantRecipe) handle.get(recipe);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
throw new IllegalArgumentException("Not CMR");
} }
} }

View File

@@ -11,6 +11,10 @@ public final class BlockBreak implements BlockBreakProxy {
@Override @Override
public void breakBlock(@NotNull final Player player, public void breakBlock(@NotNull final Player player,
@NotNull final Block block) { @NotNull final Block block) {
if (!(player instanceof CraftPlayer)) {
return;
}
((CraftPlayer) player).getHandle().playerInteractManager.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ())); ((CraftPlayer) player).getHandle().playerInteractManager.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ()));
} }
} }

View File

@@ -22,18 +22,29 @@ import java.util.Arrays;
public final class ChatComponent implements ChatComponentProxy { public final class ChatComponent implements ChatComponentProxy {
@Override @Override
public Object modifyComponent(@NotNull final Object object) { public Object modifyComponent(@NotNull final Object object) {
if (!(object instanceof IChatBaseComponent)) { if (!(object instanceof IChatBaseComponent chatComponent)) {
return object; return object;
} }
IChatBaseComponent chatComponent = (IChatBaseComponent) object; for (IChatBaseComponent iChatBaseComponent : chatComponent) {
chatComponent.stream().forEach(this::modifyBaseComponent); if (iChatBaseComponent == null) {
continue;
}
modifyBaseComponent(iChatBaseComponent);
}
return chatComponent; return chatComponent;
} }
private void modifyBaseComponent(@NotNull final IChatBaseComponent component) { private void modifyBaseComponent(@NotNull final IChatBaseComponent component) {
component.getSiblings().forEach(this::modifyBaseComponent); for (IChatBaseComponent sibling : component.getSiblings()) {
if (sibling == null) {
continue;
}
modifyBaseComponent(sibling);
}
if (component instanceof ChatMessage) { if (component instanceof ChatMessage) {
Arrays.stream(((ChatMessage) component).getArgs()) Arrays.stream(((ChatMessage) component).getArgs())
.filter(o -> o instanceof IChatBaseComponent) .filter(o -> o instanceof IChatBaseComponent)

View File

@@ -1,8 +1,7 @@
package com.willfp.eco.proxy.v1_16_R3; package com.willfp.eco.proxy.v1_16_R3;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import com.willfp.eco.core.display.Display; import com.willfp.eco.core.display.Display;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack; import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftMerchantRecipe; import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftMerchantRecipe;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe; import org.bukkit.inventory.MerchantRecipe;
@@ -11,30 +10,56 @@ import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field; import java.lang.reflect.Field;
public final class VillagerTrade implements VillagerTradeProxy { public final class VillagerTrade implements VillagerTradeProxy {
@Override /**
public void displayTrade(@NotNull final MerchantRecipe merchantRecipe) { * Handle.
*/
private final Field handle;
/**
* Create new Villager Trade.
*/
public VillagerTrade() {
try { try {
// Bukkit MerchantRecipe result handle = CraftMerchantRecipe.class.getDeclaredField("handle");
Field fResult = MerchantRecipe.class.getDeclaredField("result"); handle.setAccessible(true);
fResult.setAccessible(true); return;
ItemStack result = merchantRecipe.getResult(); } catch (NoSuchFieldException e) {
Display.displayAndFinalize(result);
fResult.set(merchantRecipe, result);
// Get NMS MerchantRecipe from CraftMerchantRecipe
Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle");
fHandle.setAccessible(true);
net.minecraft.server.v1_16_R3.MerchantRecipe handle = (net.minecraft.server.v1_16_R3.MerchantRecipe) fHandle.get(merchantRecipe); // NMS RecipeR
Field fSelling = net.minecraft.server.v1_16_R3.MerchantRecipe.class.getDeclaredField("sellingItem");
fSelling.setAccessible(true);
ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem);
Display.displayAndFinalize(selling);
fSelling.set(handle, CraftItemStack.asNMSCopy(selling));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace(); e.printStackTrace();
} }
throw new RuntimeException("Error!");
}
@Override
public MerchantRecipe displayTrade(@NotNull final MerchantRecipe recipe) {
CraftMerchantRecipe oldRecipe = (CraftMerchantRecipe) recipe;
CraftMerchantRecipe newRecipe = new CraftMerchantRecipe(
Display.display(recipe.getResult().clone()),
recipe.getUses(),
recipe.getMaxUses(),
recipe.hasExperienceReward(),
recipe.getVillagerExperience(),
recipe.getPriceMultiplier()
);
for (ItemStack ingredient : recipe.getIngredients()) {
newRecipe.addIngredient(Display.display(ingredient.clone()));
}
getHandle(newRecipe).setSpecialPrice(getHandle(oldRecipe).getSpecialPrice());
return newRecipe;
}
@NotNull
private net.minecraft.server.v1_16_R3.MerchantRecipe getHandle(@NotNull final CraftMerchantRecipe recipe) {
try {
return (net.minecraft.server.v1_16_R3.MerchantRecipe) handle.get(recipe);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
throw new IllegalArgumentException("Not CMR");
} }
} }

View File

@@ -0,0 +1,6 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot:1.17-R0.1-SNAPSHOT'
}

View File

@@ -0,0 +1,19 @@
package com.willfp.eco.proxy.v1_17_R1;
import com.willfp.eco.proxy.proxies.AutoCraftProxy;
import net.minecraft.network.protocol.game.PacketPlayOutAutoRecipe;
import net.minecraft.resources.MinecraftKey;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
public final class AutoCraft implements AutoCraftProxy {
@Override
public void modifyPacket(@NotNull final Object packet) throws NoSuchFieldException, IllegalAccessException {
PacketPlayOutAutoRecipe recipePacket = (PacketPlayOutAutoRecipe) packet;
Field fKey = recipePacket.getClass().getDeclaredField("b");
fKey.setAccessible(true);
MinecraftKey key = (MinecraftKey) fKey.get(recipePacket);
fKey.set(recipePacket, new MinecraftKey(key.getNamespace(), key.getKey() + "_displayed"));
}
}

View File

@@ -0,0 +1,20 @@
package com.willfp.eco.proxy.v1_17_R1;
import com.willfp.eco.proxy.proxies.BlockBreakProxy;
import net.minecraft.core.BlockPosition;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public final class BlockBreak implements BlockBreakProxy {
@Override
public void breakBlock(@NotNull final Player player,
@NotNull final Block block) {
if (!(player instanceof CraftPlayer)) {
return;
}
((CraftPlayer) player).getHandle().d.breakBlock(new BlockPosition(block.getX(), block.getY(), block.getZ()));
}
}

View File

@@ -0,0 +1,115 @@
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.proxy.proxies.ChatComponentProxy;
import com.willfp.eco.core.display.Display;
import net.minecraft.nbt.MojangsonParser;
import net.minecraft.network.chat.ChatBaseComponent;
import net.minecraft.network.chat.ChatHoverable;
import net.minecraft.network.chat.ChatMessage;
import net.minecraft.network.chat.ChatModifier;
import net.minecraft.network.chat.IChatBaseComponent;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
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 object) {
if (!(object instanceof IChatBaseComponent chatComponent)) {
return object;
}
for (IChatBaseComponent iChatBaseComponent : chatComponent) {
if (iChatBaseComponent == null) {
continue;
}
modifyBaseComponent(iChatBaseComponent);
}
return chatComponent;
}
private void modifyBaseComponent(@NotNull final IChatBaseComponent component) {
for (IChatBaseComponent sibling : component.getSiblings()) {
if (sibling == null) {
continue;
}
modifyBaseComponent(sibling);
}
if (component instanceof ChatMessage) {
Arrays.stream(((ChatMessage) component).getArgs())
.filter(o -> o instanceof IChatBaseComponent)
.map(o -> (IChatBaseComponent) o)
.forEach(this::modifyBaseComponent);
}
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);
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.world.item.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

@@ -0,0 +1,41 @@
package com.willfp.eco.proxy.v1_17_R1;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.willfp.eco.proxy.proxies.SkullProxy;
import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;
public final class Skull implements SkullProxy {
/**
* Cached method to set the gameProfile.
*/
private Method setProfile = null;
@Override
public void setSkullTexture(@NotNull final SkullMeta meta,
@NotNull final String base64) {
try {
if (setProfile == null) {
setProfile = meta.getClass().getDeclaredMethod("setProfile", GameProfile.class);
setProfile.setAccessible(true);
}
UUID uuid = new UUID(
base64.substring(base64.length() - 20).hashCode(),
base64.substring(base64.length() - 10).hashCode()
);
GameProfile profile = new GameProfile(uuid, "talismans");
profile.getProperties().put("textures", new Property("textures", base64));
setProfile.invoke(meta, profile);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,13 @@
package com.willfp.eco.proxy.v1_17_R1;
import com.willfp.eco.proxy.proxies.TridentStackProxy;
import org.bukkit.entity.Trident;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public final class TridentStack implements TridentStackProxy {
@Override
public ItemStack getTridentStack(@NotNull final Trident trident) {
return trident.getItem();
}
}

View File

@@ -0,0 +1,65 @@
package com.willfp.eco.proxy.v1_17_R1;
import com.willfp.eco.core.display.Display;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftMerchantRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
public final class VillagerTrade implements VillagerTradeProxy {
/**
* Handle.
*/
private final Field handle;
/**
* Create new Villager Trade.
*/
public VillagerTrade() {
try {
handle = CraftMerchantRecipe.class.getDeclaredField("handle");
handle.setAccessible(true);
return;
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
throw new RuntimeException("Error!");
}
@Override
public MerchantRecipe displayTrade(@NotNull final MerchantRecipe recipe) {
CraftMerchantRecipe oldRecipe = (CraftMerchantRecipe) recipe;
CraftMerchantRecipe newRecipe = new CraftMerchantRecipe(
Display.display(recipe.getResult().clone()),
recipe.getUses(),
recipe.getMaxUses(),
recipe.hasExperienceReward(),
recipe.getVillagerExperience(),
recipe.getPriceMultiplier()
);
for (ItemStack ingredient : recipe.getIngredients()) {
newRecipe.addIngredient(Display.display(ingredient.clone()));
}
getHandle(newRecipe).setSpecialPrice(getHandle(oldRecipe).getSpecialPrice());
return newRecipe;
}
@NotNull
private net.minecraft.world.item.trading.MerchantRecipe getHandle(@NotNull final CraftMerchantRecipe recipe) {
try {
return (net.minecraft.world.item.trading.MerchantRecipe) handle.get(recipe);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
throw new IllegalArgumentException("Not CMR");
}
}

View File

@@ -4,6 +4,7 @@ version rootProject.version
dependencies { dependencies {
implementation 'org.apache.maven:maven-artifact:3.0.3' implementation 'org.apache.maven:maven-artifact:3.0.3'
implementation 'org.bstats:bstats-bukkit:1.7' implementation 'org.bstats:bstats-bukkit:1.7'
compileOnly 'com.google.code.gson:gson:2.8.7'
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT' compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
compileOnly project(":eco-core:core-proxy") compileOnly project(":eco-core:core-proxy")
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT' compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT'
@@ -16,6 +17,15 @@ dependencies {
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.157'
// CombatLogX V10 + NewbieHelper Expansion
compileOnly 'com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT'
compileOnly 'com.SirBlobman.combatlogx.expansions:NewbieHelper:10.0.0.0-SNAPSHOT'
// CombatLogX V11 + NewbieHelper Expansion
compileOnly 'com.github.sirblobman.combatlogx:api:11.0.0.0-SNAPSHOT'
compileOnly 'com.github.sirblobman.combatlogx.expansion:newbie-helper:11.0.0.0-SNAPSHOT'
compileOnly fileTree(dir: '../../lib', include: ['*.jar']) compileOnly fileTree(dir: '../../lib', include: ['*.jar'])
} }

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.spigot;
import com.willfp.eco.internal.Internals;
import org.jetbrains.annotations.NotNull;
public class EcoInternals extends Internals {
private final EcoSpigotPlugin plugin;
EcoInternals(@NotNull final EcoSpigotPlugin plugin) {
this.plugin = plugin;
}
@Override
public EcoSpigotPlugin getPlugin() {
return plugin;
}
}

View File

@@ -2,16 +2,17 @@ package com.willfp.eco.spigot;
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.command.AbstractCommand; import com.willfp.eco.core.data.Data;
import com.willfp.eco.core.display.Display; import com.willfp.eco.core.display.Display;
import com.willfp.eco.core.display.DisplayModule;
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;
import com.willfp.eco.core.integrations.antigrief.AntigriefManager; import com.willfp.eco.core.integrations.antigrief.AntigriefManager;
import com.willfp.eco.core.integrations.mcmmo.McmmoManager; import com.willfp.eco.core.integrations.mcmmo.McmmoManager;
import com.willfp.eco.internal.Internals;
import com.willfp.eco.proxy.proxies.BlockBreakProxy; import com.willfp.eco.proxy.proxies.BlockBreakProxy;
import com.willfp.eco.proxy.proxies.SkullProxy; import com.willfp.eco.proxy.proxies.SkullProxy;
import com.willfp.eco.proxy.proxies.TridentStackProxy; import com.willfp.eco.proxy.proxies.TridentStackProxy;
import com.willfp.eco.spigot.config.DataJson;
import com.willfp.eco.spigot.display.PacketAutoRecipe; import com.willfp.eco.spigot.display.PacketAutoRecipe;
import com.willfp.eco.spigot.display.PacketChat; import com.willfp.eco.spigot.display.PacketChat;
import com.willfp.eco.spigot.display.PacketOpenWindowMerchant; import com.willfp.eco.spigot.display.PacketOpenWindowMerchant;
@@ -23,10 +24,15 @@ import com.willfp.eco.spigot.eventlisteners.ArmorListener;
import com.willfp.eco.spigot.eventlisteners.DispenserArmorListener; import com.willfp.eco.spigot.eventlisteners.DispenserArmorListener;
import com.willfp.eco.spigot.eventlisteners.EntityDeathByEntityListeners; import com.willfp.eco.spigot.eventlisteners.EntityDeathByEntityListeners;
import com.willfp.eco.spigot.eventlisteners.NaturalExpGainListeners; import com.willfp.eco.spigot.eventlisteners.NaturalExpGainListeners;
import com.willfp.eco.spigot.eventlisteners.PlayerJumpListeners;
import com.willfp.eco.spigot.gui.GUIListener;
import com.willfp.eco.spigot.integrations.anticheat.AnticheatAAC; import com.willfp.eco.spigot.integrations.anticheat.AnticheatAAC;
import com.willfp.eco.spigot.integrations.anticheat.AnticheatMatrix; import com.willfp.eco.spigot.integrations.anticheat.AnticheatMatrix;
import com.willfp.eco.spigot.integrations.anticheat.AnticheatNCP; import com.willfp.eco.spigot.integrations.anticheat.AnticheatNCP;
import com.willfp.eco.spigot.integrations.antigrief.AntigriefCombatLogX; import com.willfp.eco.spigot.integrations.anticheat.AnticheatSpartan;
import com.willfp.eco.spigot.integrations.anticheat.AnticheatVulcan;
import com.willfp.eco.spigot.integrations.antigrief.AntigriefCombatLogXV10;
import com.willfp.eco.spigot.integrations.antigrief.AntigriefCombatLogXV11;
import com.willfp.eco.spigot.integrations.antigrief.AntigriefFactionsUUID; import com.willfp.eco.spigot.integrations.antigrief.AntigriefFactionsUUID;
import com.willfp.eco.spigot.integrations.antigrief.AntigriefGriefPrevention; import com.willfp.eco.spigot.integrations.antigrief.AntigriefGriefPrevention;
import com.willfp.eco.spigot.integrations.antigrief.AntigriefKingdoms; import com.willfp.eco.spigot.integrations.antigrief.AntigriefKingdoms;
@@ -39,9 +45,13 @@ import com.willfp.eco.util.BlockUtils;
import com.willfp.eco.util.SkullUtils; import com.willfp.eco.util.SkullUtils;
import com.willfp.eco.util.TridentUtils; import com.willfp.eco.util.TridentUtils;
import lombok.Getter; import lombok.Getter;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -53,42 +63,45 @@ public class EcoSpigotPlugin extends EcoPlugin {
@Getter @Getter
private static EcoSpigotPlugin instance; private static EcoSpigotPlugin instance;
/**
* data.json.
*/
private final DataJson dataJson;
/** /**
* Create a new instance of eco. * Create a new instance of eco.
*/ */
public EcoSpigotPlugin() { public EcoSpigotPlugin() {
super("eco", 87955, 10043, "com.willfp.eco.proxy", "&a"); super(87955, 10043, "com.willfp.eco.proxy", "&a");
instance = this; instance = this;
Internals.setInterfacing(new EcoInternals(this));
Display.setFinalizeKey(this.getNamespacedKeyFactory().create("finalized")); Display.setFinalizeKey(this.getNamespacedKeyFactory().create("finalized"));
SkullProxy skullProxy = InternalProxyUtils.getProxy(SkullProxy.class); SkullProxy skullProxy = ProxyUtils.getProxy(SkullProxy.class);
SkullUtils.initialize(skullProxy::setSkullTexture); SkullUtils.initialize(skullProxy::setSkullTexture);
BlockBreakProxy blockBreakProxy = InternalProxyUtils.getProxy(BlockBreakProxy.class); BlockBreakProxy blockBreakProxy = ProxyUtils.getProxy(BlockBreakProxy.class);
BlockUtils.initialize(blockBreakProxy::breakBlock); BlockUtils.initialize(blockBreakProxy::breakBlock);
TridentStackProxy tridentStackProxy = InternalProxyUtils.getProxy(TridentStackProxy.class); TridentStackProxy tridentStackProxy = ProxyUtils.getProxy(TridentStackProxy.class);
TridentUtils.initialize(tridentStackProxy::getTridentStack); TridentUtils.initialize(tridentStackProxy::getTridentStack);
this.dataJson = new DataJson(this);
Data.init(this.dataJson);
} }
@Override @Override
public void enable() { public void enable() {
new CollatedRunnable(this); new CollatedRunnable(this);
this.getEventManager().registerListener(new NaturalExpGainListeners());
this.getEventManager().registerListener(new ArmorListener());
this.getEventManager().registerListener(new DispenserArmorListener());
this.getEventManager().registerListener(new EntityDeathByEntityListeners(this));
this.getEventManager().registerListener(new ShapedRecipeListener());
} }
@Override @Override
public void disable() { public void disable() {
try {
Data.save(this.dataJson);
} catch (IOException e) {
e.printStackTrace();
} }
@Override
public void load() {
} }
@Override @Override
@@ -96,11 +109,6 @@ public class EcoSpigotPlugin extends EcoPlugin {
new CollatedRunnable(this); new CollatedRunnable(this);
} }
@Override
public void postLoad() {
}
@Override @Override
public List<IntegrationLoader> getIntegrationLoaders() { public List<IntegrationLoader> getIntegrationLoaders() {
return Arrays.asList( return Arrays.asList(
@@ -111,48 +119,60 @@ public class EcoSpigotPlugin extends EcoPlugin {
new IntegrationLoader("Towny", () -> AntigriefManager.register(new AntigriefTowny())), new IntegrationLoader("Towny", () -> AntigriefManager.register(new AntigriefTowny())),
new IntegrationLoader("Lands", () -> AntigriefManager.register(new AntigriefLands(this))), new IntegrationLoader("Lands", () -> AntigriefManager.register(new AntigriefLands(this))),
new IntegrationLoader("Kingdoms", () -> AntigriefManager.register(new AntigriefKingdoms())), new IntegrationLoader("Kingdoms", () -> AntigriefManager.register(new AntigriefKingdoms())),
new IntegrationLoader("CombatLogX", () -> AntigriefManager.register(new AntigriefCombatLogX())), new IntegrationLoader("CombatLogX", () -> {
PluginManager pluginManager = Bukkit.getPluginManager();
Plugin plugin_CombatLogX = pluginManager.getPlugin("CombatLogX");
if (plugin_CombatLogX == null) return;
String pluginVersion = plugin_CombatLogX.getDescription().getVersion();
if (pluginVersion.startsWith("10")) {
AntigriefManager.register(new AntigriefCombatLogXV10());
}
if(pluginVersion.startsWith("11")) {
AntigriefManager.register(new AntigriefCombatLogXV11());
}
}),
// Anticheat // Anticheat
new IntegrationLoader("AAC5", () -> AnticheatManager.register(this, new AnticheatAAC())), new IntegrationLoader("AAC5", () -> AnticheatManager.register(this, new AnticheatAAC())),
new IntegrationLoader("Matrix", () -> AnticheatManager.register(this, new AnticheatMatrix())), new IntegrationLoader("Matrix", () -> AnticheatManager.register(this, new AnticheatMatrix())),
new IntegrationLoader("NoCheatPlus", () -> AnticheatManager.register(this, new AnticheatNCP())), new IntegrationLoader("NoCheatPlus", () -> AnticheatManager.register(this, new AnticheatNCP())),
new IntegrationLoader("Spartan", () -> AnticheatManager.register(this, new AnticheatSpartan())),
new IntegrationLoader("Vulcan", () -> AnticheatManager.register(this, new AnticheatVulcan())),
// Misc // Misc
new IntegrationLoader("mcMMO", () -> McmmoManager.register(new McmmoIntegrationImpl())) new IntegrationLoader("mcMMO", () -> McmmoManager.register(new McmmoIntegrationImpl()))
); );
} }
@Override
public List<AbstractCommand> getCommands() {
return new ArrayList<>();
}
@Override @Override
public List<AbstractPacketAdapter> getPacketAdapters() { public List<AbstractPacketAdapter> getPacketAdapters() {
return Arrays.asList( List<AbstractPacketAdapter> adapters = new ArrayList<>(Arrays.asList(
new PacketAutoRecipe(this), new PacketAutoRecipe(this),
new PacketChat(this), new PacketChat(this),
new PacketOpenWindowMerchant(this),
new PacketSetCreativeSlot(this), new PacketSetCreativeSlot(this),
new PacketSetSlot(this), new PacketSetSlot(this),
new PacketWindowItems(this) new PacketWindowItems(this)
); ));
if (!this.getConfigYml().getBool("disable-display-on-villagers")) {
adapters.add(new PacketOpenWindowMerchant(this));
}
return adapters;
} }
@Override @Override
public List<Listener> getListeners() { public List<Listener> getListeners() {
return new ArrayList<>(); return Arrays.asList(
} new NaturalExpGainListeners(),
new ArmorListener(),
@Override new DispenserArmorListener(),
public List<Class<?>> getUpdatableClasses() { new EntityDeathByEntityListeners(this),
return new ArrayList<>(); new ShapedRecipeListener(this),
} new PlayerJumpListeners(),
new GUIListener(this)
@Override );
@Nullable
protected DisplayModule createDisplayModule() {
return null;
} }
} }

View File

@@ -1,20 +0,0 @@
package com.willfp.eco.spigot;
import com.willfp.eco.core.proxy.AbstractProxy;
import com.willfp.eco.proxy.util.ProxyFactory;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
@UtilityClass
public class InternalProxyUtils {
/**
* Get the implementation of a specified proxy.
*
* @param proxyClass The proxy interface.
* @param <T> The type of the proxy.
* @return The proxy implementation.
*/
public @NotNull <T extends AbstractProxy> T getProxy(@NotNull final Class<T> proxyClass) {
return new ProxyFactory<>(EcoSpigotPlugin.getInstance(), proxyClass).getProxy();
}
}

View File

@@ -0,0 +1,13 @@
package com.willfp.eco.spigot;
import com.willfp.eco.core.proxy.AbstractProxy;
import com.willfp.eco.proxy.util.ProxyFactory;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
@UtilityClass
public class ProxyUtils {
public <T extends AbstractProxy> T getProxy(@NotNull final Class<T> proxy) {
return new ProxyFactory<>(EcoSpigotPlugin.getInstance(), proxy).getProxy();
}
}

View File

@@ -0,0 +1,16 @@
package com.willfp.eco.spigot.config;
import com.willfp.eco.core.config.JsonStaticBaseConfig;
import com.willfp.eco.spigot.EcoSpigotPlugin;
import org.jetbrains.annotations.NotNull;
public class DataJson extends JsonStaticBaseConfig {
/**
* Init data.json.
*
* @param plugin EcoSpigotPlugin.
*/
public DataJson(@NotNull final EcoSpigotPlugin plugin) {
super("data", plugin);
}
}

View File

@@ -3,10 +3,10 @@ package com.willfp.eco.spigot.display;
import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import com.willfp.eco.proxy.proxies.AutoCraftProxy;
import com.willfp.eco.spigot.InternalProxyUtils;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.AbstractPacketAdapter; import com.willfp.eco.core.AbstractPacketAdapter;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.proxy.proxies.AutoCraftProxy;
import com.willfp.eco.spigot.ProxyUtils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -34,7 +34,7 @@ public class PacketAutoRecipe extends AbstractPacketAdapter {
} }
try { try {
InternalProxyUtils.getProxy(AutoCraftProxy.class).modifyPacket(packet.getHandle()); ProxyUtils.getProxy(AutoCraftProxy.class).modifyPacket(packet.getHandle());
} catch (NoSuchFieldException | IllegalAccessException e) { } catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -4,10 +4,10 @@ import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.ListenerPriority; import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.WrappedChatComponent; import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.willfp.eco.proxy.proxies.ChatComponentProxy;
import com.willfp.eco.spigot.InternalProxyUtils;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.AbstractPacketAdapter; import com.willfp.eco.core.AbstractPacketAdapter;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.proxy.proxies.ChatComponentProxy;
import com.willfp.eco.spigot.ProxyUtils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -34,7 +34,7 @@ public class PacketChat extends AbstractPacketAdapter {
return; return;
} }
WrappedChatComponent newComponent = WrappedChatComponent.fromHandle(InternalProxyUtils.getProxy(ChatComponentProxy.class).modifyComponent(component.getHandle())); WrappedChatComponent newComponent = WrappedChatComponent.fromHandle(ProxyUtils.getProxy(ChatComponentProxy.class).modifyComponent(component.getHandle()));
packet.getChatComponents().write(i, newComponent); packet.getChatComponents().write(i, newComponent);
} }
} }

View File

@@ -1,17 +1,23 @@
package com.willfp.eco.spigot.display; package com.willfp.eco.spigot.display;
import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy; import com.comphenix.protocol.events.PacketEvent;
import com.willfp.eco.spigot.InternalProxyUtils;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.AbstractPacketAdapter; import com.willfp.eco.core.AbstractPacketAdapter;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import com.willfp.eco.spigot.ProxyUtils;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe; import org.bukkit.inventory.MerchantRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class PacketOpenWindowMerchant extends AbstractPacketAdapter { public class PacketOpenWindowMerchant extends AbstractPacketAdapter {
/** /**
@@ -20,16 +26,32 @@ public class PacketOpenWindowMerchant extends AbstractPacketAdapter {
* @param plugin The plugin to listen through. * @param plugin The plugin to listen through.
*/ */
public PacketOpenWindowMerchant(@NotNull final EcoPlugin plugin) { public PacketOpenWindowMerchant(@NotNull final EcoPlugin plugin) {
super(plugin, PacketType.Play.Server.OPEN_WINDOW_MERCHANT, false); super(plugin, PacketType.Play.Server.OPEN_WINDOW_MERCHANT, ListenerPriority.MONITOR, true);
} }
@Override @Override
public void onSend(@NotNull final PacketContainer packet, public void onSend(@NotNull final PacketContainer packet,
@NotNull final Player player) { @NotNull final Player player,
List<MerchantRecipe> recipes = packet.getMerchantRecipeLists().readSafely(0); @NotNull final PacketEvent event) {
List<MerchantRecipe> recipes = new ArrayList<>();
recipes = recipes.stream().peek(merchantRecipe -> InternalProxyUtils.getProxy(VillagerTradeProxy.class).displayTrade(merchantRecipe)).collect(Collectors.toList()); if (this.getPlugin().getConfigYml().getBool("villager-display-fix")) {
for (MerchantRecipe recipe : packet.getMerchantRecipeLists().read(0)) {
packet.getMerchantRecipeLists().writeSafely(0, recipes); ItemStack result = recipe.getResult();
ItemMeta meta = result.getItemMeta();
if (meta != null) {
meta.removeItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_POTION_EFFECTS);
meta.getPersistentDataContainer().remove(NamespacedKey.fromString("ecoenchants:ecoenchantlore-skip"));
result.setItemMeta(meta);
}
}
}
for (MerchantRecipe recipe : packet.getMerchantRecipeLists().read(0)) {
MerchantRecipe newRecipe = ProxyUtils.getProxy(VillagerTradeProxy.class).displayTrade(recipe);
recipes.add(newRecipe);
}
packet.getMerchantRecipeLists().write(0, recipes);
} }
} }

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