Compare commits

..

39 Commits

Author SHA1 Message Date
Auxilor
d96ad10960 Added locker to registry 2023-04-20 19:27:52 +01:00
Auxilor
21283b0928 Added ExternalDataStoreObjectAdapter 2023-04-20 19:19:00 +01:00
Auxilor
2797687f01 Cleanup 2023-04-20 17:54:23 +01:00
Auxilor
9c68d1fbc3 Merge branch 'master' into develop
# Conflicts:
#	eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsOraxen.kt
2023-04-20 17:45:06 +01:00
Auxilor
9371d9b88d Upstream 2023-04-20 17:44:58 +01:00
Auxilor
14e2ead488 Fixed javadoc, updated Kingdoms 2023-04-20 17:42:46 +01:00
Auxilor
5473bb8ef8 Cleaned up IntegrationRegistry 2023-04-20 17:34:18 +01:00
Auxilor
90c55849ae Isolated integration registration 2023-04-20 17:24:56 +01:00
Auxilor
9809140cf9 Isolated remaining integrations 2023-04-20 17:23:24 +01:00
Auxilor
49a82dc005 Isolated ShopManager 2023-04-20 17:15:18 +01:00
Auxilor
92dec03b9a Added IntegrationRegistry 2023-04-20 17:09:46 +01:00
Auxilor
7453c70b87 Fixed imports 2023-04-20 16:52:49 +01:00
Auxilor
3038ea43d0 Updated to 6.55.0 2023-04-20 16:51:11 +01:00
Auxilor
3c6ddd8255 Added OutdatedEcoVersionError 2023-04-20 16:50:35 +01:00
Auxilor
925ee04cc1 Added Version as a cross-version compatible version of DefaultArtifactVersion 2023-04-20 16:48:20 +01:00
Auxilor
6f7de8716b Added KRegistrable 2023-04-20 16:41:35 +01:00
Auxilor
a17b951a8b Made registry lockable and iterable 2023-04-20 16:40:06 +01:00
Auxilor
f003ed06a8 Fixed imports 2023-04-19 18:00:19 +01:00
Auxilor
f864953da2 Updated to 6.54.1 2023-04-19 17:38:22 +01:00
Auxilor
6ef31444ac Removed Checkstyle CI, cleaned up Oraxen PR 2023-04-19 17:38:09 +01:00
Will FP
99258116de Merge pull request #264 from MCCasper/master
fix oraxen and SNBT
2023-04-19 12:33:14 -04:00
casper
a59c68102e fix SNBT matching the same tag for diff materials 2023-04-19 11:09:26 -05:00
casper
2482525fe2 load oraxen later 2023-04-18 22:23:49 -05:00
Auxilor
acb326c0c8 Updated to 6.54.0 2023-04-13 12:13:32 -04:00
Auxilor
11d947e24b Updated to 6.53.2 2023-04-13 12:09:14 -04:00
Auxilor
3cced3012c Added Prerequisite#HAS_1_19_4 2023-04-13 11:59:04 -04:00
Auxilor
520523e903 Isolated integration loading 2023-04-13 11:57:49 -04:00
Auxilor
ee36cc74f8 Improved lifecycle error logging 2023-04-13 11:50:32 -04:00
Auxilor
55344e0550 Improved lifecycle error handling, isolated tasks 2023-04-13 11:49:43 -04:00
Auxilor
75f6f05c7d Merge branch 'master' into develop 2023-03-30 14:05:09 +01:00
Auxilor
17fa519501 Revert "Fixed ContinuallyAppliedPersistentDataContainer"
This reverts commit 1852ff86ec.
2023-03-30 14:04:43 +01:00
Auxilor
1a72cf3ca9 Revert "Updated to 6.53.2"
This reverts commit d11f355c44.
2023-03-30 14:04:43 +01:00
Auxilor
d11f355c44 Updated to 6.53.2 2023-03-30 12:08:37 +01:00
Auxilor
1852ff86ec Fixed ContinuallyAppliedPersistentDataContainer 2023-03-30 12:08:26 +01:00
Auxilor
ffe9219f45 Changed README to show repo.auxilor.io 2023-03-29 13:33:24 +01:00
Auxilor
f67a5d3b3d Added repo.auxilor.io 2023-03-29 13:30:15 +01:00
Auxilor
bbd541abe0 Added repo.auxilor.io 2023-03-29 13:21:40 +01:00
Auxilor
f5e289966f Fixed tab completion for dynamically registered commands 2023-03-28 17:12:35 +01:00
Auxilor
bcfa4bd82e Added json() extension 2023-03-25 17:48:27 +00:00
38 changed files with 686 additions and 198 deletions

View File

@@ -1,15 +0,0 @@
name: Check PR Codestyle
on: [ pull_request ]
jobs:
checkstyle:
name: Checkstyle
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dbelyaev/action-checkstyle@v0.5.1
with:
github_token: ${{ secrets.github_token }}
reporter: github-pr-review
level: warning
checkstyle_config: ../../config/checkstyle/checkstyle.xml

View File

@@ -28,6 +28,8 @@ jobs:
- name: Publish artifact - name: Publish artifact
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
# The GITHUB_REF tag comes in the format 'refs/tags/xxx'. # The GITHUB_REF tag comes in the format 'refs/tags/xxx'.
# So if we split on '/' and take the 3rd value, we can get the release name. # So if we split on '/' and take the 3rd value, we can get the release name.

View File

@@ -63,7 +63,7 @@ eco comes packed with all the tools you need in your plugins:
# For developers # For developers
## Javadoc ## Javadoc
The 6.49.0 Javadoc can be found [here](https://javadoc.jitpack.io/com/willfp/eco/6.49.0/javadoc/) The 6.53.0 Javadoc can be found [here](https://javadoc.jitpack.io/com/willfp/eco/6.53.0/javadoc/)
## Plugin Information ## Plugin Information
@@ -75,31 +75,31 @@ depend:
- eco - eco
``` ```
## Get from JitPack: ## Dependency Information:
Gradle: Gradle:
```groovy ```kts
repositories { repositories {
maven { url 'https://jitpack.io' } maven("https://repo.auxilor.io/repository/maven-public/")
} }
``` ```
```groovy ```groovy
dependencies { dependencies {
compileOnly 'com.willfp:eco:Tag' compileOnly("com.willfp:eco:Tag")
} }
``` ```
Replace `Tag` with a release tag for eco, eg `6.49.0`. Replace `Tag` with a release tag for eco, eg `6.53.0`.
Maven: Maven:
```xml ```xml
<repository> <repository>
<id>jitpack.io</id> <id>auxilor</id>
<url>https://jitpack.io</url> <url>https://repo.auxilor.io/repository/maven-public/</url>
</repository> </repository>
``` ```
@@ -112,7 +112,7 @@ Maven:
</dependency> </dependency>
``` ```
Replace `Tag` with a release tag for eco, eg `6.49.0`. Replace `Tag` with a release tag for eco, eg `6.53.0`.
## Build locally: ## Build locally:

View File

@@ -39,4 +39,17 @@ publishing {
} }
} }
} }
publishing {
repositories {
maven {
name = "Auxilor"
url = uri("https://repo.auxilor.io/repository/maven-releases/")
credentials {
username = System.getenv("MAVEN_USERNAME")
password = System.getenv("MAVEN_PASSWORD")
}
}
}
}
} }

View File

@@ -19,9 +19,10 @@ import com.willfp.eco.core.proxy.ProxyFactory;
import com.willfp.eco.core.registry.Registrable; import com.willfp.eco.core.registry.Registrable;
import com.willfp.eco.core.registry.Registry; import com.willfp.eco.core.registry.Registry;
import com.willfp.eco.core.scheduling.Scheduler; import com.willfp.eco.core.scheduling.Scheduler;
import com.willfp.eco.core.version.OutdatedEcoVersionError;
import com.willfp.eco.core.version.Version;
import com.willfp.eco.core.web.UpdateChecker; import com.willfp.eco.core.web.UpdateChecker;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
@@ -38,6 +39,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -346,14 +348,14 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
they have an outdated version of eco installed. they have an outdated version of eco installed.
*/ */
DefaultArtifactVersion runningVersion = new DefaultArtifactVersion(Eco.get().getEcoPlugin().getDescription().getVersion()); Version runningVersion = new Version(Eco.get().getEcoPlugin().getDescription().getVersion());
DefaultArtifactVersion requiredVersion = new DefaultArtifactVersion(this.getMinimumEcoVersion()); Version requiredVersion = new Version(this.getMinimumEcoVersion());
if (!(runningVersion.compareTo(requiredVersion) > 0 || runningVersion.equals(requiredVersion))) { if (!(runningVersion.compareTo(requiredVersion) > 0 || runningVersion.equals(requiredVersion))) {
this.getLogger().severe("You are running an outdated version of eco!"); 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("You must be on at least" + this.getMinimumEcoVersion());
this.getLogger().severe("Download the newest version here:"); this.getLogger().severe("Download the newest version here:");
this.getLogger().severe("https://polymart.org/download/773/recent/JSpprMspkuyecf5y1wQ2Jn8OoLQSQ_IW"); this.getLogger().severe("https://polymart.org/download/773/recent/JSpprMspkuyecf5y1wQ2Jn8OoLQSQ_IW");
Bukkit.getPluginManager().disablePlugin(this); throw new OutdatedEcoVersionError("This plugin requires at least eco version " + this.getMinimumEcoVersion() + " to run.");
} }
} }
@@ -369,8 +371,8 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
if (this.getResourceId() != 0 && !Eco.get().getEcoPlugin().getConfigYml().getBool("no-update-checker")) { if (this.getResourceId() != 0 && !Eco.get().getEcoPlugin().getConfigYml().getBool("no-update-checker")) {
new UpdateChecker(this).getVersion(version -> { new UpdateChecker(this).getVersion(version -> {
DefaultArtifactVersion currentVersion = new DefaultArtifactVersion(this.getDescription().getVersion()); Version currentVersion = new Version(this.getDescription().getVersion());
DefaultArtifactVersion mostRecentVersion = new DefaultArtifactVersion(version); Version mostRecentVersion = new Version(version);
if (!(currentVersion.compareTo(mostRecentVersion) > 0 || currentVersion.equals(mostRecentVersion))) { if (!(currentVersion.compareTo(mostRecentVersion) > 0 || currentVersion.equals(mostRecentVersion))) {
this.outdated = true; this.outdated = true;
this.getLogger().warning(this.getName() + " is out of date! (Version " + this.getDescription().getVersion() + ")"); this.getLogger().warning(this.getName() + " is out of date! (Version " + this.getDescription().getVersion() + ")");
@@ -392,8 +394,13 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
this.loadIntegrationLoaders().forEach(integrationLoader -> { this.loadIntegrationLoaders().forEach(integrationLoader -> {
if (enabledPlugins.contains(integrationLoader.getPluginName().toLowerCase())) { if (enabledPlugins.contains(integrationLoader.getPluginName().toLowerCase())) {
this.loadedIntegrations.add(integrationLoader.getPluginName()); try {
integrationLoader.load(); integrationLoader.load();
this.loadedIntegrations.add(integrationLoader.getPluginName());
} catch (Exception e) {
this.getLogger().warning("Failed to load integration for " + integrationLoader.getPluginName());
e.printStackTrace();
}
} }
}); });
@@ -429,9 +436,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
} }
} }
this.onEnable.get(LifecyclePosition.START).forEach(Runnable::run); this.handleLifecycle(this.onEnable, this::handleEnable);
this.handleEnable();
this.onEnable.get(LifecyclePosition.END).forEach(Runnable::run);
this.getLogger().info(""); this.getLogger().info("");
} }
@@ -466,9 +471,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
this.getEventManager().unregisterAllListeners(); this.getEventManager().unregisterAllListeners();
this.getScheduler().cancelAll(); this.getScheduler().cancelAll();
this.onDisable.get(LifecyclePosition.START).forEach(Runnable::run); this.handleLifecycle(this.onDisable, this::handleDisable);
this.handleDisable();
this.onDisable.get(LifecyclePosition.END).forEach(Runnable::run);
if (this.isSupportingExtensions()) { if (this.isSupportingExtensions()) {
this.getExtensionLoader().unloadExtensions(); this.getExtensionLoader().unloadExtensions();
@@ -505,9 +508,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
public final void onLoad() { public final void onLoad() {
super.onLoad(); super.onLoad();
this.onLoad.get(LifecyclePosition.START).forEach(Runnable::run); this.handleLifecycle(this.onLoad, this::handleLoad);
this.handleLoad();
this.onLoad.get(LifecyclePosition.END).forEach(Runnable::run);
} }
/** /**
@@ -561,9 +562,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
this.getLogger().severe(""); this.getLogger().severe("");
} }
this.afterLoad.get(LifecyclePosition.START).forEach(Runnable::run); this.handleLifecycle(this.afterLoad, this::handleAfterLoad);
this.handleAfterLoad();
this.afterLoad.get(LifecyclePosition.END).forEach(Runnable::run);
this.reload(); this.reload();
@@ -604,9 +603,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
this.getConfigHandler().callUpdate(); this.getConfigHandler().callUpdate();
this.getConfigHandler().callUpdate(); // Call twice to fix issues this.getConfigHandler().callUpdate(); // Call twice to fix issues
this.onReload.get(LifecyclePosition.START).forEach(Runnable::run); this.handleLifecycle(this.onReload, this::handleReload);
this.handleReload();
this.onReload.get(LifecyclePosition.END).forEach(Runnable::run);
for (Extension extension : this.extensionLoader.getLoadedExtensions()) { for (Extension extension : this.extensionLoader.getLoadedExtensions()) {
extension.handleReload(); extension.handleReload();
@@ -646,6 +643,43 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
return System.currentTimeMillis() - startTime; return System.currentTimeMillis() - startTime;
} }
/**
* Handle lifecycle.
*
* @param tasks The tasks.
* @param handler The handler.
*/
private void handleLifecycle(@NotNull final ListMap<LifecyclePosition, Runnable> tasks,
@NotNull final Runnable handler) {
for (Runnable task : tasks.get(LifecyclePosition.START)) {
try {
task.run();
} catch (final Exception e) {
this.getLogger().log(Level.SEVERE, "Error while running lifecycle task!");
this.getLogger().log(Level.SEVERE, "The plugin may not function properly");
e.printStackTrace();
}
}
try {
handler.run();
} catch (final Exception e) {
this.getLogger().log(Level.SEVERE, "Error while running lifecycle task!");
this.getLogger().log(Level.SEVERE, "The plugin may not function properly");
e.printStackTrace();
}
for (Runnable task : tasks.get(LifecyclePosition.END)) {
try {
task.run();
} catch (final Exception e) {
this.getLogger().log(Level.SEVERE, "Error while running lifecycle task!");
this.getLogger().log(Level.SEVERE, "The plugin may not function properly");
e.printStackTrace();
}
}
}
/** /**
* The plugin-specific code to be executed on enable. * The plugin-specific code to be executed on enable.
* <p> * <p>

View File

@@ -37,6 +37,14 @@ public class Prerequisite {
"Requires server to have ProtocolLib" "Requires server to have ProtocolLib"
); );
/**
* Requires the server to be running 1.19.4.
*/
public static final Prerequisite HAS_1_19_4 = new Prerequisite(
() -> ProxyConstants.NMS_VERSION.contains("19_R3"),
"Requires server to be running 1.19.4+"
);
/** /**
* Requires the server to be running 1.19. * Requires the server to be running 1.19.
*/ */

View File

@@ -3,17 +3,26 @@ package com.willfp.eco.core.data;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
* A simple store key-value store for data to be stored outside of plugins. * A simple store key-value store for data to be stored outside of plugins.
*/ */
@SuppressWarnings("unchecked")
public final class ExternalDataStore { public final class ExternalDataStore {
/** /**
* The store. * The store.
*/ */
private static final HashMap<String, Object> data = new HashMap<>(); private static final Map<String, Object> DATA = new HashMap<>();
/**
* The store adapters.
*/
private static final List<ExternalDataStoreObjectAdapter<?, ?>> STORE_ADAPTERS = new ArrayList<>();
/** /**
* Put data into the store. * Put data into the store.
@@ -23,7 +32,29 @@ public final class ExternalDataStore {
*/ */
public static void put(@NotNull final String key, public static void put(@NotNull final String key,
@NotNull final Object value) { @NotNull final Object value) {
data.put(key, value); doPut(key, value);
}
/**
* Put data into the store.
*
* @param key The key.
* @param value The value.
* @param <A> The stored type.
*/
private static <A> void doPut(@NotNull final String key,
@NotNull final A value) {
Object storedValue = value;
for (ExternalDataStoreObjectAdapter<?, ?> unknownAdapter : STORE_ADAPTERS) {
if (unknownAdapter.getAccessedClass().isInstance(value)) {
ExternalDataStoreObjectAdapter<A, ?> adapter = (ExternalDataStoreObjectAdapter<A, ?>) unknownAdapter;
storedValue = adapter.toStoredObject(value);
break;
}
}
DATA.put(key, storedValue);
} }
/** /**
@@ -37,7 +68,30 @@ public final class ExternalDataStore {
@Nullable @Nullable
public static <T> T get(@NotNull final String key, public static <T> T get(@NotNull final String key,
@NotNull final Class<T> clazz) { @NotNull final Class<T> clazz) {
Object value = data.get(key); return doGet(key, clazz);
}
/**
* Get data from the store.
*
* @param key The key.
* @param clazz The class.
* @param <A> The accessed type.
* @param <S> The stored type.
* @return The value.
*/
@Nullable
private static <A, S> A doGet(@NotNull final String key,
@NotNull final Class<A> clazz) {
Object value = DATA.get(key);
for (ExternalDataStoreObjectAdapter<?, ?> unknownAdapter : STORE_ADAPTERS) {
if (unknownAdapter.getStoredClass().isInstance(value) && unknownAdapter.getAccessedClass().equals(clazz)) {
ExternalDataStoreObjectAdapter<A, S> adapter = (ExternalDataStoreObjectAdapter<A, S>) unknownAdapter;
value = adapter.toAccessedObject((S) value);
break;
}
}
if (clazz.isInstance(value)) { if (clazz.isInstance(value)) {
return clazz.cast(value); return clazz.cast(value);
@@ -79,6 +133,15 @@ public final class ExternalDataStore {
return get(key, clazz, defaultValue.get()); return get(key, clazz, defaultValue.get());
} }
/**
* Register a new adapter.
*
* @param adapter The adapter.
*/
public static void registerAdapter(@NotNull final ExternalDataStoreObjectAdapter<?, ?> adapter) {
STORE_ADAPTERS.add(adapter);
}
private ExternalDataStore() { private ExternalDataStore() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
} }

View File

@@ -0,0 +1,69 @@
package com.willfp.eco.core.data;
import org.jetbrains.annotations.NotNull;
/**
* An adapter for objects stored in {@link ExternalDataStore}.
*
* @param <A> The accessed class.
* @param <S> The stored class.
*/
public abstract class ExternalDataStoreObjectAdapter<A, S> {
/**
* The class that is accessed (read / written).
*/
private final Class<? extends A> accessedClass;
/**
* The class that is stored internally.
*/
private final Class<? extends S> storedClass;
/**
* Create a new adapter.
*
* @param accessedClass The class that is accessed (read / written).
* @param storedClass The class that is stored internally.
*/
protected ExternalDataStoreObjectAdapter(@NotNull final Class<? extends A> accessedClass,
@NotNull final Class<? extends S> storedClass) {
this.accessedClass = accessedClass;
this.storedClass = storedClass;
}
/**
* Convert an object to the stored object.
*
* @param obj The object.
* @return The stored object.
*/
@NotNull
public abstract S toStoredObject(@NotNull final A obj);
/**
* Convert an object to the accessed object.
*
* @param obj The object.
* @return The accessed object.
*/
@NotNull
public abstract A toAccessedObject(@NotNull final S obj);
/**
* Get the class that is accessed (read / written).
*
* @return The class.
*/
public Class<? extends A> getAccessedClass() {
return accessedClass;
}
/**
* Get the class that is stored internally.
*
* @return The class.
*/
public Class<? extends S> getStoredClass() {
return storedClass;
}
}

View File

@@ -1,13 +1,22 @@
package com.willfp.eco.core.integrations; package com.willfp.eco.core.integrations;
import com.willfp.eco.core.registry.Registrable;
import com.willfp.eco.core.registry.Registry;
import org.jetbrains.annotations.NotNull;
/** /**
* Abstract class for integrations. * Abstract class for integrations.
*/ */
public interface Integration { public interface Integration extends Registrable {
/** /**
* Get the name of integration. * Get the name of integration.
* *
* @return The name. * @return The name.
*/ */
String getPluginName(); String getPluginName();
@Override
default @NotNull String getID() {
return Registry.tryFitPattern(this.getPluginName());
}
} }

View File

@@ -0,0 +1,131 @@
package com.willfp.eco.core.integrations;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.registry.Registry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* Registry for integrations.
*
* @param <T> The type of integration.
*/
public class IntegrationRegistry<T extends Integration> extends Registry<T> {
@Override
public @NotNull T register(@NotNull final T element) {
return executeSafely(() -> super.register(element), element);
}
/**
* Iterate over all integrations, safely.
*
* @param action The action to perform.
*/
public void forEachSafely(@NotNull final Consumer<T> action) {
for (T integration : new HashSet<>(this.values())) {
executeSafely(() -> action.accept(integration), integration);
}
}
/**
* If any integrations return true, safely.
*
* @param predicate The predicate to test.
* @return If any integrations return true.
*/
public boolean anySafely(@NotNull final Predicate<T> predicate) {
for (T integration : new HashSet<>(this.values())) {
Boolean result = executeSafely(() -> predicate.test(integration), integration);
if (result != null && result) {
return true;
}
}
return false;
}
/**
* Get the first integration that returns a value, safely.
*
* @param function The function to apply.
* @param defaultValue The default value.
* @param <R> The type of value.
* @return The first value that returns a value.
*/
@NotNull
public <R> R firstSafely(@NotNull final Function<T, R> function,
@NotNull final R defaultValue) {
if (this.isEmpty()) {
return defaultValue;
}
T integration = this.iterator().next();
return executeSafely(() -> function.apply(integration), integration, defaultValue);
}
/**
* Executes a given action safely, catching any exceptions and logging the issue.
*
* @param action The action to execute.
* @param integration The integration to apply the action on.
*/
private void executeSafely(@NotNull final Runnable action,
@NotNull final T integration) {
executeSafely(() -> {
action.run();
return null;
}, integration);
}
/**
* Executes a given action safely, catching any exceptions and logging the issue.
*
* @param action The action to execute.
* @param integration The integration to apply the action on.
* @param <R> The return type of the action.
* @return The result of the action, or null if an exception was thrown.
*/
private <R> R executeSafely(@NotNull final Supplier<R> action,
@NotNull final T integration) {
return executeSafely(action, integration, null);
}
/**
* Executes a given action safely, catching any exceptions and logging the issue.
*
* @param action The action to execute.
* @param integration The integration to apply the action on.
* @param defaultValue The default value to return if an exception is thrown.
* @param <R> The return type of the action.
* @return The result of the action, or the default value if an exception was thrown.
*/
private <R> R executeSafely(@NotNull final Supplier<R> action,
@NotNull final T integration,
@Nullable final R defaultValue) {
try {
return action.get();
} catch (final Exception e) {
Eco.get().getEcoPlugin().getLogger().warning("Integration for " + integration.getPluginName() + " threw an exception!");
Eco.get().getEcoPlugin().getLogger().warning("The integration will be disabled.");
e.printStackTrace();
this.remove(integration.getPluginName());
return defaultValue;
}
}
/**
* If all integrations return true, safely.
*
* @param predicate The predicate to test.
* @return If all integrations return true.
*/
public boolean allSafely(@NotNull final Predicate<T> predicate) {
return !this.anySafely(predicate.negate());
}
}

View File

@@ -1,11 +1,9 @@
package com.willfp.eco.core.integrations.afk; package com.willfp.eco.core.integrations.afk;
import com.willfp.eco.core.integrations.IntegrationRegistry;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/** /**
* Class to handle afk integrations. * Class to handle afk integrations.
*/ */
@@ -13,7 +11,7 @@ public final class AFKManager {
/** /**
* A set of all registered integrations. * A set of all registered integrations.
*/ */
private static final Set<AFKIntegration> REGISTERED = new HashSet<>(); private static final IntegrationRegistry<AFKIntegration> REGISTRY = new IntegrationRegistry<>();
/** /**
* Register a new integration. * Register a new integration.
@@ -21,8 +19,7 @@ public final class AFKManager {
* @param integration The integration to register. * @param integration The integration to register.
*/ */
public static void register(@NotNull final AFKIntegration integration) { public static void register(@NotNull final AFKIntegration integration) {
REGISTERED.removeIf(it -> it.getPluginName().equalsIgnoreCase(integration.getPluginName())); REGISTRY.register(integration);
REGISTERED.add(integration);
} }
/** /**
@@ -32,13 +29,7 @@ public final class AFKManager {
* @return If afk. * @return If afk.
*/ */
public static boolean isAfk(@NotNull final Player player) { public static boolean isAfk(@NotNull final Player player) {
for (AFKIntegration integration : REGISTERED) { return REGISTRY.anySafely(integration -> integration.isAfk(player));
if (integration.isAfk(player)) {
return true;
}
}
return false;
} }
private AFKManager() { private AFKManager() {

View File

@@ -1,13 +1,11 @@
package com.willfp.eco.core.integrations.anticheat; package com.willfp.eco.core.integrations.anticheat;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import com.willfp.eco.core.integrations.IntegrationRegistry;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/** /**
* Class to handle anticheat integrations. * Class to handle anticheat integrations.
*/ */
@@ -15,7 +13,7 @@ public final class AnticheatManager {
/** /**
* A set of all registered anticheats. * A set of all registered anticheats.
*/ */
private static final Set<AnticheatIntegration> ANTICHEATS = new HashSet<>(); private static final IntegrationRegistry<AnticheatIntegration> REGISTRY = new IntegrationRegistry<>();
/** /**
* Register a new anticheat. * Register a new anticheat.
@@ -26,8 +24,7 @@ public final class AnticheatManager {
if (anticheat instanceof Listener) { if (anticheat instanceof Listener) {
Eco.get().getEcoPlugin().getEventManager().registerListener((Listener) anticheat); Eco.get().getEcoPlugin().getEventManager().registerListener((Listener) anticheat);
} }
ANTICHEATS.removeIf(it -> it.getPluginName().equalsIgnoreCase(anticheat.getPluginName())); REGISTRY.register(anticheat);
ANTICHEATS.add(anticheat);
} }
/** /**
@@ -36,17 +33,16 @@ public final class AnticheatManager {
* @param player The player to exempt. * @param player The player to exempt.
*/ */
public static void exemptPlayer(@NotNull final Player player) { public static void exemptPlayer(@NotNull final Player player) {
ANTICHEATS.forEach(anticheat -> anticheat.exempt(player)); REGISTRY.forEachSafely(anticheat -> anticheat.exempt(player));
} }
/** /**
* Unexempt a player from triggering anticheats. * Unexempt a player from triggering anticheats.
* This is ran a tick after it is called to ensure that there are no event timing conflicts.
* *
* @param player The player to remove the exemption. * @param player The player to remove the exemption.
*/ */
public static void unexemptPlayer(@NotNull final Player player) { public static void unexemptPlayer(@NotNull final Player player) {
ANTICHEATS.forEach(anticheat -> anticheat.unexempt(player)); REGISTRY.forEachSafely(anticheat -> anticheat.unexempt(player));
} }
private AnticheatManager() { private AnticheatManager() {

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.integrations.antigrief; package com.willfp.eco.core.integrations.antigrief;
import com.willfp.eco.core.integrations.IntegrationRegistry;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
@@ -16,7 +17,7 @@ public final class AntigriefManager {
/** /**
* Registered antigriefs. * Registered antigriefs.
*/ */
private static final Set<AntigriefIntegration> REGISTERED = new HashSet<>(); private static final IntegrationRegistry<AntigriefIntegration> REGISTRY = new IntegrationRegistry<>();
/** /**
* Register a new AntiGrief/Land Management integration. * Register a new AntiGrief/Land Management integration.
@@ -24,8 +25,7 @@ public final class AntigriefManager {
* @param antigrief The integration to register. * @param antigrief The integration to register.
*/ */
public static void register(@NotNull final AntigriefIntegration antigrief) { public static void register(@NotNull final AntigriefIntegration antigrief) {
REGISTERED.removeIf(it -> it.getPluginName().equalsIgnoreCase(antigrief.getPluginName())); REGISTRY.register(antigrief);
REGISTERED.add(antigrief);
} }
/** /**
@@ -34,8 +34,7 @@ public final class AntigriefManager {
* @param antigrief The integration to unregister. * @param antigrief The integration to unregister.
*/ */
public static void unregister(@NotNull final AntigriefIntegration antigrief) { public static void unregister(@NotNull final AntigriefIntegration antigrief) {
REGISTERED.removeIf(it -> it.getPluginName().equalsIgnoreCase(antigrief.getPluginName())); REGISTRY.remove(antigrief);
REGISTERED.remove(antigrief);
} }
/** /**
@@ -47,7 +46,7 @@ public final class AntigriefManager {
*/ */
public static boolean canPickupItem(@NotNull final Player player, public static boolean canPickupItem(@NotNull final Player player,
@NotNull final Location location) { @NotNull final Location location) {
return REGISTERED.stream().allMatch(antigriefIntegration -> antigriefIntegration.canPickupItem(player, location)); return REGISTRY.allSafely(integration -> integration.canPickupItem(player, location));
} }
/** /**
@@ -59,7 +58,7 @@ public final class AntigriefManager {
*/ */
public static boolean canBreakBlock(@NotNull final Player player, public static boolean canBreakBlock(@NotNull final Player player,
@NotNull final Block block) { @NotNull final Block block) {
return REGISTERED.stream().allMatch(antigriefIntegration -> antigriefIntegration.canBreakBlock(player, block)); return REGISTRY.allSafely(integration -> integration.canBreakBlock(player, block));
} }
/** /**
@@ -71,7 +70,7 @@ public final class AntigriefManager {
*/ */
public static boolean canCreateExplosion(@NotNull final Player player, public static boolean canCreateExplosion(@NotNull final Player player,
@NotNull final Location location) { @NotNull final Location location) {
return REGISTERED.stream().allMatch(antigriefIntegration -> antigriefIntegration.canCreateExplosion(player, location)); return REGISTRY.allSafely(integration -> integration.canCreateExplosion(player, location));
} }
/** /**
@@ -83,7 +82,7 @@ public final class AntigriefManager {
*/ */
public static boolean canPlaceBlock(@NotNull final Player player, public static boolean canPlaceBlock(@NotNull final Player player,
@NotNull final Block block) { @NotNull final Block block) {
return REGISTERED.stream().allMatch(antigriefIntegration -> antigriefIntegration.canPlaceBlock(player, block)); return REGISTRY.allSafely(integration -> integration.canPlaceBlock(player, block));
} }
/** /**
@@ -95,7 +94,7 @@ public final class AntigriefManager {
*/ */
public static boolean canInjure(@NotNull final Player player, public static boolean canInjure(@NotNull final Player player,
@NotNull final LivingEntity victim) { @NotNull final LivingEntity victim) {
return REGISTERED.stream().allMatch(antigriefIntegration -> antigriefIntegration.canInjure(player, victim)); return REGISTRY.allSafely(integration -> integration.canInjure(player, victim));
} }
private AntigriefManager() { private AntigriefManager() {

View File

@@ -1,10 +1,8 @@
package com.willfp.eco.core.integrations.customentities; package com.willfp.eco.core.integrations.customentities;
import com.willfp.eco.core.integrations.IntegrationRegistry;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/** /**
* Class to handle custom entity integrations. * Class to handle custom entity integrations.
*/ */
@@ -12,7 +10,7 @@ public final class CustomEntitiesManager {
/** /**
* A set of all registered integrations. * A set of all registered integrations.
*/ */
private static final Set<CustomEntitiesIntegration> REGISTERED = new HashSet<>(); private static final IntegrationRegistry<CustomEntitiesIntegration> REGISTRY = new IntegrationRegistry<>();
/** /**
* Register a new integration. * Register a new integration.
@@ -20,8 +18,7 @@ public final class CustomEntitiesManager {
* @param integration The integration to register. * @param integration The integration to register.
*/ */
public static void register(@NotNull final CustomEntitiesIntegration integration) { public static void register(@NotNull final CustomEntitiesIntegration integration) {
REGISTERED.removeIf(it -> it.getPluginName().equalsIgnoreCase(integration.getPluginName())); REGISTRY.register(integration);
REGISTERED.add(integration);
} }
/** /**
@@ -30,9 +27,7 @@ public final class CustomEntitiesManager {
* @see com.willfp.eco.core.entities.Entities * @see com.willfp.eco.core.entities.Entities
*/ */
public static void registerAllEntities() { public static void registerAllEntities() {
for (CustomEntitiesIntegration integration : REGISTERED) { REGISTRY.forEachSafely(CustomEntitiesIntegration::registerAllEntities);
integration.registerAllEntities();
}
} }
private CustomEntitiesManager() { private CustomEntitiesManager() {

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.integrations.customitems; package com.willfp.eco.core.integrations.customitems;
import com.willfp.eco.core.integrations.IntegrationRegistry;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashSet; import java.util.HashSet;
@@ -12,7 +13,7 @@ public final class CustomItemsManager {
/** /**
* A set of all registered integrations. * A set of all registered integrations.
*/ */
private static final Set<CustomItemsIntegration> REGISTERED = new HashSet<>(); private static final IntegrationRegistry<CustomItemsIntegration> REGISTRY = new IntegrationRegistry<>();
/** /**
* Register a new integration. * Register a new integration.
@@ -20,8 +21,7 @@ public final class CustomItemsManager {
* @param integration The integration to register. * @param integration The integration to register.
*/ */
public static void register(@NotNull final CustomItemsIntegration integration) { public static void register(@NotNull final CustomItemsIntegration integration) {
REGISTERED.removeIf(it -> it.getPluginName().equalsIgnoreCase(integration.getPluginName())); REGISTRY.register(integration);
REGISTERED.add(integration);
} }
/** /**
@@ -30,9 +30,7 @@ public final class CustomItemsManager {
* @see com.willfp.eco.core.items.Items * @see com.willfp.eco.core.items.Items
*/ */
public static void registerAllItems() { public static void registerAllItems() {
for (CustomItemsIntegration customItemsIntegration : REGISTERED) { REGISTRY.forEachSafely(CustomItemsIntegration::registerAllItems);
customItemsIntegration.registerAllItems();
}
} }
/** /**
@@ -41,9 +39,7 @@ public final class CustomItemsManager {
* @see com.willfp.eco.core.items.Items * @see com.willfp.eco.core.items.Items
*/ */
public static void registerProviders() { public static void registerProviders() {
for (CustomItemsIntegration customItemsIntegration : REGISTERED) { REGISTRY.forEachSafely(CustomItemsIntegration::registerProvider);
customItemsIntegration.registerProvider();
}
} }
private CustomItemsManager() { private CustomItemsManager() {

View File

@@ -1,11 +1,10 @@
package com.willfp.eco.core.integrations.economy; package com.willfp.eco.core.integrations.economy;
import com.willfp.eco.core.integrations.IntegrationRegistry;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;
/** /**
* Class to handle economy. * Class to handle economy.
@@ -14,7 +13,7 @@ public final class EconomyManager {
/** /**
* A set of all registered integrations. * A set of all registered integrations.
*/ */
private static final Set<EconomyIntegration> REGISTERED = new HashSet<>(); private static final IntegrationRegistry<EconomyIntegration> REGISTRY = new IntegrationRegistry<>();
/** /**
* Register a new integration. * Register a new integration.
@@ -22,8 +21,7 @@ public final class EconomyManager {
* @param integration The integration to register. * @param integration The integration to register.
*/ */
public static void register(@NotNull final EconomyIntegration integration) { public static void register(@NotNull final EconomyIntegration integration) {
REGISTERED.removeIf(it -> it.getPluginName().equalsIgnoreCase(integration.getPluginName())); REGISTRY.register(integration);
REGISTERED.add(integration);
} }
/** /**
@@ -32,7 +30,7 @@ public final class EconomyManager {
* @return If any economy. * @return If any economy.
*/ */
public static boolean hasRegistrations() { public static boolean hasRegistrations() {
return !REGISTERED.isEmpty(); return REGISTRY.isNotEmpty();
} }
/** /**
@@ -56,11 +54,10 @@ public final class EconomyManager {
*/ */
public static boolean hasAmount(@NotNull final OfflinePlayer player, public static boolean hasAmount(@NotNull final OfflinePlayer player,
final BigDecimal amount) { final BigDecimal amount) {
for (EconomyIntegration integration : REGISTERED) { return REGISTRY.firstSafely(
return integration.hasAmount(player, amount); integration -> integration.hasAmount(player, amount),
} false
);
return false;
} }
/** /**
@@ -84,11 +81,10 @@ public final class EconomyManager {
*/ */
public static boolean giveMoney(@NotNull final OfflinePlayer player, public static boolean giveMoney(@NotNull final OfflinePlayer player,
@NotNull final BigDecimal amount) { @NotNull final BigDecimal amount) {
for (EconomyIntegration integration : REGISTERED) { return REGISTRY.firstSafely(
return integration.giveMoney(player, amount); integration -> integration.giveMoney(player, amount),
} false
);
return false;
} }
/** /**
@@ -112,11 +108,10 @@ public final class EconomyManager {
*/ */
public static boolean removeMoney(@NotNull final OfflinePlayer player, public static boolean removeMoney(@NotNull final OfflinePlayer player,
@NotNull final BigDecimal amount) { @NotNull final BigDecimal amount) {
for (EconomyIntegration integration : REGISTERED) { return REGISTRY.firstSafely(
return integration.removeMoney(player, amount); integration -> integration.removeMoney(player, amount),
} false
);
return false;
} }
/** /**
@@ -136,11 +131,10 @@ public final class EconomyManager {
* @return The balance. * @return The balance.
*/ */
public static BigDecimal getExactBalance(@NotNull final OfflinePlayer player) { public static BigDecimal getExactBalance(@NotNull final OfflinePlayer player) {
for (EconomyIntegration integration : REGISTERED) { return REGISTRY.firstSafely(
return integration.getExactBalance(player); integration -> integration.getExactBalance(player),
} BigDecimal.ZERO
);
return BigDecimal.ZERO;
} }
private EconomyManager() { private EconomyManager() {

View File

@@ -1,12 +1,10 @@
package com.willfp.eco.core.integrations.guidetection; package com.willfp.eco.core.integrations.guidetection;
import com.willfp.eco.core.integrations.IntegrationRegistry;
import com.willfp.eco.util.MenuUtils; import com.willfp.eco.util.MenuUtils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/** /**
* Class to handle GUI detection. * Class to handle GUI detection.
*/ */
@@ -14,7 +12,7 @@ public final class GUIDetectionManager {
/** /**
* A set of all registered integrations. * A set of all registered integrations.
*/ */
private static final Set<GUIDetectionIntegration> REGISTERED = new HashSet<>(); private static final IntegrationRegistry<GUIDetectionIntegration> REGISTRY = new IntegrationRegistry<>();
/** /**
* Register a new integration. * Register a new integration.
@@ -22,8 +20,7 @@ public final class GUIDetectionManager {
* @param integration The integration to register. * @param integration The integration to register.
*/ */
public static void register(@NotNull final GUIDetectionIntegration integration) { public static void register(@NotNull final GUIDetectionIntegration integration) {
REGISTERED.removeIf(it -> it.getPluginName().equalsIgnoreCase(integration.getPluginName())); REGISTRY.register(integration);
REGISTERED.add(integration);
} }
/** /**
@@ -37,13 +34,7 @@ public final class GUIDetectionManager {
return true; return true;
} }
for (GUIDetectionIntegration integration : REGISTERED) { return REGISTRY.anySafely(integration -> integration.hasGUIOpen(player));
if (integration.hasGUIOpen(player)) {
return true;
}
}
return false;
} }
private GUIDetectionManager() { private GUIDetectionManager() {

View File

@@ -1,11 +1,10 @@
package com.willfp.eco.core.integrations.hologram; package com.willfp.eco.core.integrations.hologram;
import com.willfp.eco.core.integrations.IntegrationRegistry;
import org.bukkit.Location; import org.bukkit.Location;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* Class to handle hologram integrations. * Class to handle hologram integrations.
@@ -14,7 +13,7 @@ public final class HologramManager {
/** /**
* A set of all registered integrations. * A set of all registered integrations.
*/ */
private static final Set<HologramIntegration> REGISTERED = new HashSet<>(); private static final IntegrationRegistry<HologramIntegration> REGISTRY = new IntegrationRegistry<>();
/** /**
* Register a new integration. * Register a new integration.
@@ -22,8 +21,7 @@ public final class HologramManager {
* @param integration The integration to register. * @param integration The integration to register.
*/ */
public static void register(@NotNull final HologramIntegration integration) { public static void register(@NotNull final HologramIntegration integration) {
REGISTERED.removeIf(it -> it.getPluginName().equalsIgnoreCase(integration.getPluginName())); REGISTRY.register(integration);
REGISTERED.add(integration);
} }
/** /**
@@ -35,11 +33,10 @@ public final class HologramManager {
*/ */
public static Hologram createHologram(@NotNull final Location location, public static Hologram createHologram(@NotNull final Location location,
@NotNull final List<String> contents) { @NotNull final List<String> contents) {
for (HologramIntegration integration : REGISTERED) { return REGISTRY.firstSafely(
return integration.createHologram(location, contents); integration -> integration.createHologram(location, contents),
} new DummyHologram()
);
return new DummyHologram();
} }
private HologramManager() { private HologramManager() {

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.integrations.mcmmo; package com.willfp.eco.core.integrations.mcmmo;
import com.willfp.eco.core.integrations.IntegrationRegistry;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -14,7 +15,7 @@ public final class McmmoManager {
/** /**
* A set of all registered integrations. * A set of all registered integrations.
*/ */
private static final Set<McmmoIntegration> REGISTERED = new HashSet<>(); private static final IntegrationRegistry<McmmoIntegration> REGISTERED = new IntegrationRegistry<>();
/** /**
* Register a new integration. * Register a new integration.
@@ -22,8 +23,7 @@ public final class McmmoManager {
* @param integration The integration to register. * @param integration The integration to register.
*/ */
public static void register(@NotNull final McmmoIntegration integration) { public static void register(@NotNull final McmmoIntegration integration) {
REGISTERED.removeIf(it -> it.getPluginName().equalsIgnoreCase(integration.getPluginName())); REGISTERED.register(integration);
REGISTERED.add(integration);
} }
/** /**
@@ -34,13 +34,11 @@ public final class McmmoManager {
*/ */
public static int getBonusDropCount(@NotNull final Block block) { public static int getBonusDropCount(@NotNull final Block block) {
int finalValue = 0; int finalValue = 0;
for (McmmoIntegration mcmmoIntegration : REGISTERED) { for (McmmoIntegration mcmmoIntegration : REGISTERED) {
finalValue += mcmmoIntegration.getBonusDropCount(block); finalValue += mcmmoIntegration.getBonusDropCount(block);
} }
return finalValue; return finalValue;
} }
@@ -51,13 +49,7 @@ public final class McmmoManager {
* @return If the event is fake. * @return If the event is fake.
*/ */
public static boolean isFake(@NotNull final Event event) { public static boolean isFake(@NotNull final Event event) {
for (McmmoIntegration mcmmoIntegration : REGISTERED) { return REGISTERED.anySafely(integration -> integration.isFake(event));
if (mcmmoIntegration.isFake(event)) {
return true;
}
}
return false;
} }
private McmmoManager() { private McmmoManager() {

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.integrations.shop; package com.willfp.eco.core.integrations.shop;
import com.willfp.eco.core.integrations.IntegrationRegistry;
import com.willfp.eco.core.price.Price; import com.willfp.eco.core.price.Price;
import com.willfp.eco.core.price.impl.PriceFree; import com.willfp.eco.core.price.impl.PriceFree;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -13,11 +14,12 @@ import java.util.Set;
/** /**
* Class to handle shop integrations. * Class to handle shop integrations.
*/ */
@SuppressWarnings("DeprecatedIsStillUsed")
public final class ShopManager { public final class ShopManager {
/** /**
* A set of all registered integrations. * A set of all registered integrations.
*/ */
private static final Set<ShopIntegration> REGISTERED = new HashSet<>(); private static final IntegrationRegistry<ShopIntegration> REGISTRY = new IntegrationRegistry<>();
/** /**
* Register a new integration. * Register a new integration.
@@ -25,17 +27,14 @@ public final class ShopManager {
* @param integration The integration to register. * @param integration The integration to register.
*/ */
public static void register(@NotNull final ShopIntegration integration) { public static void register(@NotNull final ShopIntegration integration) {
REGISTERED.removeIf(it -> it.getPluginName().equalsIgnoreCase(integration.getPluginName())); REGISTRY.register(integration);
REGISTERED.add(integration);
} }
/** /**
* Register eco item provider for shop plugins. * Register eco item provider for shop plugins.
*/ */
public static void registerEcoProvider() { public static void registerEcoProvider() {
for (ShopIntegration shopIntegration : REGISTERED) { REGISTRY.forEachSafely(ShopIntegration::registerEcoProvider);
shopIntegration.registerEcoProvider();
}
} }
/** /**
@@ -51,11 +50,7 @@ public final class ShopManager {
return false; return false;
} }
for (ShopIntegration integration : REGISTERED) { return REGISTRY.anySafely(integration -> integration.isSellable(itemStack, player));
return integration.isSellable(itemStack, player);
}
return false;
} }
/** /**
@@ -74,11 +69,10 @@ public final class ShopManager {
return new PriceFree(); return new PriceFree();
} }
for (ShopIntegration integration : REGISTERED) { return REGISTRY.firstSafely(
return integration.getUnitValue(itemStack, player); integration -> integration.getUnitValue(itemStack, player),
} new PriceFree()
);
return new PriceFree();
} }
/** /**
@@ -108,11 +102,10 @@ public final class ShopManager {
return 0.0; return 0.0;
} }
for (ShopIntegration shopIntegration : REGISTERED) { return REGISTRY.firstSafely(
return shopIntegration.getUnitValue(itemStack, player).getValue(player, itemStack.getAmount()); integration -> integration.getUnitValue(itemStack, player).getValue(player, itemStack.getAmount()),
} 0.0
);
return 0.0;
} }
/** /**
@@ -121,7 +114,7 @@ public final class ShopManager {
* @return The integrations. * @return The integrations.
*/ */
public static Set<ShopIntegration> getRegisteredIntegrations() { public static Set<ShopIntegration> getRegisteredIntegrations() {
return new HashSet<>(REGISTERED); return new HashSet<>(REGISTRY.values());
} }
private ShopManager() { private ShopManager() {

View File

@@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -14,7 +15,7 @@ import java.util.regex.Pattern;
* *
* @param <T> The type of {@link Registrable}. * @param <T> The type of {@link Registrable}.
*/ */
public class Registry<T extends Registrable> { public class Registry<T extends Registrable> implements Iterable<T> {
/** /**
* The ID pattern. * The ID pattern.
*/ */
@@ -25,6 +26,17 @@ public class Registry<T extends Registrable> {
*/ */
private final Map<String, T> registry = new HashMap<>(); private final Map<String, T> registry = new HashMap<>();
/**
* If the registry is locked.
*/
private boolean isLocked = false;
/**
* The locker, used to 'secure' registries and prevent random unlocking.
*/
@Nullable
private Object locker = null;
/** /**
* Instantiate a new registry. * Instantiate a new registry.
*/ */
@@ -40,6 +52,10 @@ public class Registry<T extends Registrable> {
*/ */
@NotNull @NotNull
public T register(@NotNull final T element) { public T register(@NotNull final T element) {
if (this.isLocked) {
throw new IllegalStateException("Cannot add to locked registry! (ID: " + element.getID() + ")");
}
Validate.isTrue(ID_PATTERN.matcher(element.getID()).matches(), "ID must match pattern: " + ID_PATTERN.pattern() + " (was " + element.getID() + ")"); Validate.isTrue(ID_PATTERN.matcher(element.getID()).matches(), "ID must match pattern: " + ID_PATTERN.pattern() + " (was " + element.getID() + ")");
registry.put(element.getID(), element); registry.put(element.getID(), element);
@@ -56,6 +72,10 @@ public class Registry<T extends Registrable> {
* @return The element. * @return The element.
*/ */
public T remove(@NotNull final T element) { public T remove(@NotNull final T element) {
if (this.isLocked) {
throw new IllegalStateException("Cannot remove from locked registry! (ID: " + element.getID() + ")");
}
element.onRemove(); element.onRemove();
registry.remove(element.getID()); registry.remove(element.getID());
@@ -71,6 +91,10 @@ public class Registry<T extends Registrable> {
*/ */
@Nullable @Nullable
public T remove(@NotNull final String id) { public T remove(@NotNull final String id) {
if (this.isLocked) {
throw new IllegalStateException("Cannot remove from locked registry! (ID: " + id + ")");
}
T element = registry.get(id); T element = registry.get(id);
if (element != null) { if (element != null) {
@@ -109,6 +133,61 @@ public class Registry<T extends Registrable> {
return Set.copyOf(registry.values()); return Set.copyOf(registry.values());
} }
/**
* Get if the registry is locked.
*
* @return If the registry is locked.
*/
public boolean isLocked() {
return isLocked;
}
/**
* Lock the registry.
*
* @param locker The locker.
*/
public void lock(@Nullable final Object locker) {
this.locker = locker;
isLocked = true;
}
/**
* Unlock the registry.
*
* @param locker The locker.
*/
public void unlock(@Nullable final Object locker) {
if (this.locker != locker) {
throw new IllegalArgumentException("Cannot unlock registry!");
}
isLocked = false;
}
/**
* Get if the registry is empty.
*
* @return If the registry is empty.
*/
public boolean isEmpty() {
return registry.isEmpty();
}
/**
* Get if the registry is not empty.
*
* @return If the registry is not empty.
*/
public boolean isNotEmpty() {
return !isEmpty();
}
@NotNull
@Override
public Iterator<T> iterator() {
return values().iterator();
}
/** /**
* Try to fit a string to the ID pattern. * Try to fit a string to the ID pattern.
* *

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.core.version;
import org.jetbrains.annotations.NotNull;
/**
* An error thrown when eco is outdated.
*/
public class OutdatedEcoVersionError extends Error {
/**
* Create a new OutdatedEcoVersionError.
*
* @param message The message.
*/
public OutdatedEcoVersionError(@NotNull final String message) {
super(message);
}
}

View File

@@ -0,0 +1,53 @@
package com.willfp.eco.core.version;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.jetbrains.annotations.NotNull;
/**
* A minimal class to represent a version, uses DefaultArtifactVersion under the hood.
* <p>
* This class exists to resolve issues where 1.17 doesn't include DefaultArtifactVersion.
*/
public class Version implements Comparable<Version> {
/**
* The version.
*/
private final DefaultArtifactVersion version;
/**
* Create a new version.
*
* @param version The version.
*/
public Version(@NotNull final String version) {
this.version = new DefaultArtifactVersion(version);
}
@Override
public int compareTo(@NotNull final Version o) {
return this.version.compareTo(o.version);
}
@Override
public String toString() {
return this.version.toString();
}
@Override
public boolean equals(@NotNull final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Version other)) {
return false;
}
return this.version.equals(other.version);
}
@Override
public int hashCode() {
return this.version.hashCode();
}
}

View File

@@ -38,6 +38,15 @@ class DSLConfig internal constructor(type: ConfigType) : GenericConfig(type) {
fun config(type: ConfigType = ConfigType.YAML, builder: DSLConfig.() -> Unit): Config = fun config(type: ConfigType = ConfigType.YAML, builder: DSLConfig.() -> Unit): Config =
DSLConfig(type).apply(builder) DSLConfig(type).apply(builder)
/**
* Helper function to create JSON configs with a kotlin DSL.
*
* @param builder The builder.
* @return The config.
*/
fun json(builder: DSLConfig.() -> Unit): Config =
config(ConfigType.JSON, builder)
/** @see Configs.empty */ /** @see Configs.empty */
fun emptyConfig() = Configs.empty() fun emptyConfig() = Configs.empty()

View File

@@ -0,0 +1,13 @@
package com.willfp.eco.core.registry
/**
* A registrable that has a string ID, for use with Kotlin.
*/
interface KRegistrable : Registrable {
/**
* The ID of the registrable.
*/
val id: String
override fun getID() = id
}

View File

@@ -0,0 +1,27 @@
package com.willfp.eco.internal.data
import com.willfp.eco.core.data.ExternalDataStoreObjectAdapter
import com.willfp.eco.core.version.Version
object VersionToStringAdapter: ExternalDataStoreObjectAdapter<Version, String>(
Version::class.java,
String::class.java
) {
override fun toAccessedObject(obj: String): Version = Version(obj)
override fun toStoredObject(obj: Version): String = obj.toString()
}
class MavenVersionToStringAdapter(
className: String
): ExternalDataStoreObjectAdapter<Any, String>(
Class.forName(className),
String::class.java
) {
private val constructor = Class.forName(className)
.getConstructor(String::class.java)
override fun toAccessedObject(obj: String): Any = constructor.newInstance(obj)
override fun toStoredObject(obj: Any): String = obj.toString()
}

View File

@@ -45,7 +45,7 @@ class SNBTConverter : SNBTConverterProxy {
val nms = CraftItemStack.asNMSCopy(itemStack) val nms = CraftItemStack.asNMSCopy(itemStack)
val nmsTag = nms.save(CompoundTag()) val nmsTag = nms.save(CompoundTag())
nmsTag.remove("Count") nmsTag.remove("Count")
return tag.copy().merge(nmsTag) == nmsTag return tag.copy().merge(nmsTag) == nmsTag && itemStack.type == item.type
} }
override fun getItem(): ItemStack = item override fun getItem(): ItemStack = item

View File

@@ -45,7 +45,7 @@ class SNBTConverter : SNBTConverterProxy {
val nms = CraftItemStack.asNMSCopy(itemStack) val nms = CraftItemStack.asNMSCopy(itemStack)
val nmsTag = nms.save(CompoundTag()) val nmsTag = nms.save(CompoundTag())
nmsTag.remove("Count") nmsTag.remove("Count")
return tag.copy().merge(nmsTag) == nmsTag return tag.copy().merge(nmsTag) == nmsTag && itemStack.type == item.type
} }
override fun getItem(): ItemStack = item override fun getItem(): ItemStack = item

View File

@@ -45,7 +45,7 @@ class SNBTConverter : SNBTConverterProxy {
val nms = CraftItemStack.asNMSCopy(itemStack) val nms = CraftItemStack.asNMSCopy(itemStack)
val nmsTag = nms.save(CompoundTag()) val nmsTag = nms.save(CompoundTag())
nmsTag.remove("Count") nmsTag.remove("Count")
return tag.copy().merge(nmsTag) == nmsTag return tag.copy().merge(nmsTag) == nmsTag && itemStack.type == item.type
} }
override fun getItem(): ItemStack = item override fun getItem(): ItemStack = item

View File

@@ -3,6 +3,7 @@ package com.willfp.eco.internal.spigot.proxy.v1_19_R1
import com.willfp.eco.core.items.TestableItem import com.willfp.eco.core.items.TestableItem
import com.willfp.eco.core.recipe.parts.EmptyTestableItem import com.willfp.eco.core.recipe.parts.EmptyTestableItem
import com.willfp.eco.internal.spigot.proxy.SNBTConverterProxy import com.willfp.eco.internal.spigot.proxy.SNBTConverterProxy
import com.willfp.eco.internal.spigot.proxy.common.toMaterial
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.SnbtPrinterTagVisitor import net.minecraft.nbt.SnbtPrinterTagVisitor
import net.minecraft.nbt.TagParser import net.minecraft.nbt.TagParser
@@ -44,7 +45,7 @@ class SNBTConverter : SNBTConverterProxy {
val nms = CraftItemStack.asNMSCopy(itemStack) val nms = CraftItemStack.asNMSCopy(itemStack)
val nmsTag = nms.save(CompoundTag()) val nmsTag = nms.save(CompoundTag())
nmsTag.remove("Count") nmsTag.remove("Count")
return tag.copy().merge(nmsTag) == nmsTag return tag.copy().merge(nmsTag) == nmsTag && itemStack.type == item.type
} }
override fun getItem(): ItemStack = item override fun getItem(): ItemStack = item

View File

@@ -44,7 +44,7 @@ class SNBTConverter : SNBTConverterProxy {
val nms = CraftItemStack.asNMSCopy(itemStack) val nms = CraftItemStack.asNMSCopy(itemStack)
val nmsTag = nms.save(CompoundTag()) val nmsTag = nms.save(CompoundTag())
nmsTag.remove("Count") nmsTag.remove("Count")
return tag.copy().merge(nmsTag) == nmsTag return tag.copy().merge(nmsTag) == nmsTag && itemStack.type == item.type
} }
override fun getItem(): ItemStack = item override fun getItem(): ItemStack = item

View File

@@ -44,7 +44,7 @@ class SNBTConverter : SNBTConverterProxy {
val nms = CraftItemStack.asNMSCopy(itemStack) val nms = CraftItemStack.asNMSCopy(itemStack)
val nmsTag = nms.save(CompoundTag()) val nmsTag = nms.save(CompoundTag())
nmsTag.remove("Count") nmsTag.remove("Count")
return tag.copy().merge(nmsTag) == nmsTag return tag.copy().merge(nmsTag) == nmsTag && itemStack.type == item.type
} }
override fun getItem(): ItemStack = item override fun getItem(): ItemStack = item

View File

@@ -37,7 +37,7 @@ dependencies {
compileOnly("com.github.jiangdashao:matrix-api-repo:317d4635fd") compileOnly("com.github.jiangdashao:matrix-api-repo:317d4635fd")
compileOnly("com.gmail.nossr50.mcMMO:mcMMO:2.1.202") compileOnly("com.gmail.nossr50.mcMMO:mcMMO:2.1.202")
compileOnly("me.clip:placeholderapi:2.10.10") compileOnly("me.clip:placeholderapi:2.10.10")
compileOnly("com.github.oraxen:oraxen:bea381fb82") compileOnly("com.github.oraxen:oraxen:1.155.0")
compileOnly("com.github.brcdev-minecraft:shopgui-api:3.0.0") compileOnly("com.github.brcdev-minecraft:shopgui-api:3.0.0")
compileOnly("com.github.LoneDev6:API-ItemsAdder:2.4.7") compileOnly("com.github.LoneDev6:API-ItemsAdder:2.4.7")
compileOnly("com.arcaniax:HeadDatabase-API:1.3.0") compileOnly("com.arcaniax:HeadDatabase-API:1.3.0")

View File

@@ -3,6 +3,7 @@ package com.willfp.eco.internal.spigot
import com.willfp.eco.core.Eco import com.willfp.eco.core.Eco
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.Prerequisite import com.willfp.eco.core.Prerequisite
import com.willfp.eco.core.data.ExternalDataStore
import com.willfp.eco.core.entities.Entities import com.willfp.eco.core.entities.Entities
import com.willfp.eco.core.integrations.IntegrationLoader import com.willfp.eco.core.integrations.IntegrationLoader
import com.willfp.eco.core.integrations.afk.AFKManager import com.willfp.eco.core.integrations.afk.AFKManager
@@ -19,6 +20,8 @@ import com.willfp.eco.core.items.Items
import com.willfp.eco.core.packet.PacketListener import com.willfp.eco.core.packet.PacketListener
import com.willfp.eco.core.particle.Particles import com.willfp.eco.core.particle.Particles
import com.willfp.eco.core.price.Prices import com.willfp.eco.core.price.Prices
import com.willfp.eco.internal.data.MavenVersionToStringAdapter
import com.willfp.eco.internal.data.VersionToStringAdapter
import com.willfp.eco.internal.entities.EntityArgParserAdult import com.willfp.eco.internal.entities.EntityArgParserAdult
import com.willfp.eco.internal.entities.EntityArgParserAttackDamage import com.willfp.eco.internal.entities.EntityArgParserAttackDamage
import com.willfp.eco.internal.entities.EntityArgParserAttackSpeed import com.willfp.eco.internal.entities.EntityArgParserAttackSpeed
@@ -120,6 +123,7 @@ import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInComplex
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInVanilla import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInVanilla
import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapedCraftingRecipeStackHandler import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapedCraftingRecipeStackHandler
import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapelessCraftingRecipeStackHandler import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapelessCraftingRecipeStackHandler
import com.willfp.eco.util.ClassUtils
import me.TechsCode.UltraEconomy.UltraEconomy import me.TechsCode.UltraEconomy.UltraEconomy
import net.kyori.adventure.platform.bukkit.BukkitAudiences import net.kyori.adventure.platform.bukkit.BukkitAudiences
import net.milkbowl.vault.economy.Economy import net.milkbowl.vault.economy.Economy
@@ -178,6 +182,20 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
SegmentParserUseIfPresent.register() SegmentParserUseIfPresent.register()
CustomItemsManager.registerProviders() CustomItemsManager.registerProviders()
ExternalDataStore.registerAdapter(VersionToStringAdapter)
// Handle with shadow.
val className = listOf(
"org",
"apache",
"maven",
"artifact",
"versioning",
"DefaultArtifactVersion"
).joinToString(".")
if (ClassUtils.exists(className)) {
ExternalDataStore.registerAdapter(MavenVersionToStringAdapter(className))
}
} }
override fun handleEnable() { override fun handleEnable() {
@@ -270,6 +288,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
IntegrationLoader("CombatLogX") { IntegrationLoader("CombatLogX") {
val pluginManager = Bukkit.getPluginManager() val pluginManager = Bukkit.getPluginManager()
val combatLogXPlugin = pluginManager.getPlugin("CombatLogX") ?: return@IntegrationLoader val combatLogXPlugin = pluginManager.getPlugin("CombatLogX") ?: return@IntegrationLoader
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
val pluginVersion = combatLogXPlugin.description.version val pluginVersion = combatLogXPlugin.description.version
if (pluginVersion.startsWith("10")) { if (pluginVersion.startsWith("10")) {
@@ -294,7 +313,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
IntegrationLoader("MythicMobs") { CustomEntitiesManager.register(CustomEntitiesMythicMobs()) }, IntegrationLoader("MythicMobs") { CustomEntitiesManager.register(CustomEntitiesMythicMobs()) },
// Custom Items // Custom Items
IntegrationLoader("Oraxen") { CustomItemsManager.register(CustomItemsOraxen()) }, IntegrationLoader("Oraxen") { CustomItemsManager.register(CustomItemsOraxen(this)) },
IntegrationLoader("ItemsAdder") { CustomItemsManager.register(CustomItemsItemsAdder()) }, IntegrationLoader("ItemsAdder") { CustomItemsManager.register(CustomItemsItemsAdder()) },
IntegrationLoader("HeadDatabase") { CustomItemsManager.register(CustomItemsHeadDatabase(this)) }, IntegrationLoader("HeadDatabase") { CustomItemsManager.register(CustomItemsHeadDatabase(this)) },
IntegrationLoader("ExecutableItems") { CustomItemsManager.register(CustomItemsExecutableItems()) }, IntegrationLoader("ExecutableItems") { CustomItemsManager.register(CustomItemsExecutableItems()) },

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.internal.spigot.integrations.customitems package com.willfp.eco.internal.spigot.integrations.customitems
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.integrations.customitems.CustomItemsIntegration import com.willfp.eco.core.integrations.customitems.CustomItemsIntegration
import com.willfp.eco.core.items.CustomItem import com.willfp.eco.core.items.CustomItem
import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.Items
@@ -7,16 +8,27 @@ import com.willfp.eco.core.items.TestableItem
import com.willfp.eco.core.items.provider.ItemProvider import com.willfp.eco.core.items.provider.ItemProvider
import com.willfp.eco.util.NamespacedKeyUtils import com.willfp.eco.util.NamespacedKeyUtils
import io.th0rgal.oraxen.api.OraxenItems import io.th0rgal.oraxen.api.OraxenItems
import io.th0rgal.oraxen.api.events.OraxenItemsLoadedEvent
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
class CustomItemsOraxen : CustomItemsIntegration { class CustomItemsOraxen(
private val plugin: EcoPlugin
) : CustomItemsIntegration, Listener {
override fun registerProvider() { override fun registerProvider() {
Items.registerItemProvider(OraxenProvider()) plugin.eventManager.registerListener(this)
} }
override fun getPluginName(): String { override fun getPluginName(): String {
return "Oraxen" return "Oraxen"
} }
@EventHandler
@Suppress("UNUSED_PARAMETER")
fun onItemRegister(event: OraxenItemsLoadedEvent) {
Items.registerItemProvider(OraxenProvider())
}
private class OraxenProvider : ItemProvider("oraxen") { private class OraxenProvider : ItemProvider("oraxen") {
override fun provideForKey(key: String): TestableItem? { override fun provideForKey(key: String): TestableItem? {
val item = OraxenItems.getItemById(key) ?: return null val item = OraxenItems.getItemById(key) ?: return null

View File

@@ -1,3 +1,3 @@
version = 6.53.1 version = 6.55.0
plugin-name = eco plugin-name = eco
kotlin.code.style = official kotlin.code.style = official

Binary file not shown.

BIN
lib/KingdomsX-1.16.5.jar Normal file

Binary file not shown.