Merge pull request #3104 from Multiverse/ben/mv5/multi-plugin-hk2-support

multi plugin hk2 support
This commit is contained in:
Ben Woo 2024-10-12 13:36:47 +08:00 committed by GitHub
commit 1ea3531d26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
51 changed files with 369 additions and 261 deletions

View File

@ -8,7 +8,7 @@ plugins {
} }
version = System.getenv('GITHUB_VERSION') ?: 'local' version = System.getenv('GITHUB_VERSION') ?: 'local'
group = 'com.onarandombox.multiversecore' group = 'org.mvplugins.multiverse.core'
description = 'Multiverse-Core' description = 'Multiverse-Core'
java { java {
@ -111,6 +111,9 @@ dependencies {
// Utils // Utils
shadowed 'io.vavr:vavr:0.10.4' shadowed 'io.vavr:vavr:0.10.4'
shadowed 'org.glassfish.hk2:hk2-locator:3.0.3' shadowed 'org.glassfish.hk2:hk2-locator:3.0.3'
shadowed('org.glassfish.hk2:hk2-inhabitant-generator:3.0.3') {
exclude group: 'org.apache.maven', module: 'maven-core'
}
shadowed('com.dumptruckman.minecraft:Logging:1.1.1') { shadowed('com.dumptruckman.minecraft:Logging:1.1.1') {
exclude group: 'junit', module: 'junit' exclude group: 'junit', module: 'junit'
} }

View File

@ -8,10 +8,8 @@
package org.mvplugins.multiverse.core; package org.mvplugins.multiverse.core;
import java.io.File; import java.io.File;
import java.lang.annotation.Annotation;
import java.util.List; import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors;
import com.dumptruckman.minecraft.util.Logging; import com.dumptruckman.minecraft.util.Logging;
import io.vavr.control.Try; import io.vavr.control.Try;
@ -22,24 +20,21 @@ import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader; import org.bukkit.plugin.java.JavaPluginLoader;
import org.glassfish.hk2.api.MultiException;
import org.glassfish.hk2.api.ServiceHandle;
import org.glassfish.hk2.api.ServiceLocator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.anchor.AnchorManager; import org.mvplugins.multiverse.core.anchor.AnchorManager;
import org.mvplugins.multiverse.core.api.Destination; import org.mvplugins.multiverse.core.api.Destination;
import org.mvplugins.multiverse.core.api.MVCore; import org.mvplugins.multiverse.core.api.MVCore;
import org.mvplugins.multiverse.core.commands.CoreCommand;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager; import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
import org.mvplugins.multiverse.core.commandtools.PluginLocales; import org.mvplugins.multiverse.core.commandtools.PluginLocales;
import org.mvplugins.multiverse.core.config.MVCoreConfig; import org.mvplugins.multiverse.core.config.MVCoreConfig;
import org.mvplugins.multiverse.core.destination.DestinationsProvider; import org.mvplugins.multiverse.core.destination.DestinationsProvider;
import org.mvplugins.multiverse.core.economy.MVEconomist; import org.mvplugins.multiverse.core.economy.MVEconomist;
import org.mvplugins.multiverse.core.inject.InjectableListener; import org.mvplugins.multiverse.core.listeners.CoreListener;
import org.mvplugins.multiverse.core.inject.PluginInjection; import org.mvplugins.multiverse.core.inject.PluginServiceLocator;
import org.mvplugins.multiverse.core.inject.PluginServiceLocatorFactory;
import org.mvplugins.multiverse.core.placeholders.MultiverseCorePlaceholders; import org.mvplugins.multiverse.core.placeholders.MultiverseCorePlaceholders;
import org.mvplugins.multiverse.core.utils.TestingMode; import org.mvplugins.multiverse.core.utils.TestingMode;
import org.mvplugins.multiverse.core.utils.metrics.MetricsConfigurator; import org.mvplugins.multiverse.core.utils.metrics.MetricsConfigurator;
@ -54,7 +49,9 @@ import org.mvplugins.multiverse.core.world.config.SpawnLocation;
public class MultiverseCore extends JavaPlugin implements MVCore { public class MultiverseCore extends JavaPlugin implements MVCore {
private static final int PROTOCOL = 50; private static final int PROTOCOL = 50;
private ServiceLocator serviceLocator; private PluginServiceLocatorFactory serviceLocatorFactory;
private PluginServiceLocator serviceLocator;
@Inject @Inject
private Provider<MVCoreConfig> configProvider; private Provider<MVCoreConfig> configProvider;
@Inject @Inject
@ -150,12 +147,12 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
} }
private void initializeDependencyInjection() { private void initializeDependencyInjection() {
serviceLocator = PluginInjection.createServiceLocator(new MultiverseCorePluginBinder(this)) serviceLocatorFactory = new PluginServiceLocatorFactory();
.andThenTry(locator -> { serviceLocator = serviceLocatorFactory.init()
PluginInjection.enable(this, locator); .flatMap(ignore -> serviceLocatorFactory.registerPlugin(new MultiverseCorePluginBinder(this)))
}) .flatMap(PluginServiceLocator::enable)
.getOrElseThrow(exception -> { .getOrElseThrow(exception -> {
Logging.severe("Failed to initialize dependency injection"); Logging.severe("Failed to initialize dependency injection!");
getServer().getPluginManager().disablePlugin(this); getServer().getPluginManager().disablePlugin(this);
return new RuntimeException(exception); return new RuntimeException(exception);
}); });
@ -163,9 +160,13 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private void shutdownDependencyInjection() { private void shutdownDependencyInjection() {
if (serviceLocator != null) { if (serviceLocator != null) {
PluginInjection.disable(this, serviceLocator); serviceLocator.disable();
serviceLocator = null; serviceLocator = null;
} }
if (serviceLocatorFactory != null) {
serviceLocatorFactory.shutdown();
serviceLocatorFactory = null;
}
} }
private boolean shouldShowConfig() { private boolean shouldShowConfig() {
@ -195,7 +196,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private void registerEvents() { private void registerEvents() {
var pluginManager = getServer().getPluginManager(); var pluginManager = getServer().getPluginManager();
Try.run(() -> serviceLocator.getAllServices(InjectableListener.class).forEach( Try.run(() -> serviceLocator.getAllServices(CoreListener.class).forEach(
listener -> pluginManager.registerEvents(listener, this))) listener -> pluginManager.registerEvents(listener, this)))
.onFailure(e -> { .onFailure(e -> {
throw new RuntimeException("Failed to register listeners. Terminating...", e); throw new RuntimeException("Failed to register listeners. Terminating...", e);
@ -207,10 +208,8 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
*/ */
private void registerCommands() { private void registerCommands() {
Try.of(() -> commandManagerProvider.get()) Try.of(() -> commandManagerProvider.get())
.andThenTry(commandManager -> { .andThenTry(commandManager -> serviceLocator.getAllServices(CoreCommand.class)
serviceLocator.getAllServices(MultiverseCommand.class) .forEach(commandManager::registerCommand))
.forEach(commandManager::registerCommand);
})
.onFailure(e -> { .onFailure(e -> {
Logging.severe("Failed to register commands"); Logging.severe("Failed to register commands");
e.printStackTrace(); e.printStackTrace();
@ -222,9 +221,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
*/ */
private void setUpLocales() { private void setUpLocales() {
Try.of(() -> commandManagerProvider.get()) Try.of(() -> commandManagerProvider.get())
.andThen(commandManager -> { .andThen(commandManager -> commandManager.usePerIssuerLocale(true, true))
commandManager.usePerIssuerLocale(true, true);
})
.mapTry(commandManager -> pluginLocalesProvider.get()) .mapTry(commandManager -> pluginLocalesProvider.get())
.andThen(pluginLocales -> { .andThen(pluginLocales -> {
pluginLocales.addFileResClassLoader(this); pluginLocales.addFileResClassLoader(this);
@ -282,7 +279,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private void loadPlaceholderApiIntegration() { private void loadPlaceholderApiIntegration() {
if (configProvider.get().isRegisterPapiHook() if (configProvider.get().isRegisterPapiHook()
&& getServer().getPluginManager().getPlugin("PlaceholderAPI") != null) { && getServer().getPluginManager().getPlugin("PlaceholderAPI") != null) {
Try.run(() -> serviceLocator.createAndInitialize(MultiverseCorePlaceholders.class)) Try.run(() -> serviceLocator.getService(MultiverseCorePlaceholders.class))
.onFailure(e -> { .onFailure(e -> {
Logging.severe("Failed to load PlaceholderAPI integration."); Logging.severe("Failed to load PlaceholderAPI integration.");
e.printStackTrace(); e.printStackTrace();
@ -330,6 +327,22 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
return authors.toString(); return authors.toString();
} }
/**
* {@inheritDoc}
*/
@Override
public PluginServiceLocatorFactory getServiceLocatorFactory() {
return serviceLocatorFactory;
}
/**
* {@inheritDoc}
*/
@Override
public PluginServiceLocator getServiceLocator() {
return serviceLocator;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -371,46 +384,6 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
&& anchorManagerProvider.get().saveAnchors(); && anchorManagerProvider.get().saveAnchors();
} }
/**
* Gets the best service from this plugin that implements the given contract or has the given implementation.
*
* @param contractOrImpl The contract or concrete implementation to get the best instance of
* @param qualifiers The set of qualifiers that must match this service definition
* @param <T> The type of the contract to get
* @return An instance of the contract or impl if it is a service and is already instantiated, null otherwise
* @throws MultiException if there was an error during service lookup
*/
@Nullable
public <T> T getService(@NotNull Class<T> contractOrImpl, Annotation... qualifiers) throws MultiException {
var handle = serviceLocator.getServiceHandle(contractOrImpl, qualifiers);
if (handle != null && handle.isActive()) {
return handle.getService();
}
return null;
}
/**
* Gets all services from this plugin that implement the given contract or have the given implementation and have
* the provided qualifiers.
*
* @param contractOrImpl The contract or concrete implementation to get the best instance of
* @param qualifiers The set of qualifiers that must match this service definition
* @param <T> The type of the contract to get
* @return A list of services implementing this contract or concrete implementation. May not return null, but may
* return an empty list.
* @throws MultiException if there was an error during service lookup
*/
@NotNull
public <T> List<T> getAllServices(
@NotNull Class<T> contractOrImpl,
Annotation... qualifiers) throws MultiException {
var handles = serviceLocator.getAllServiceHandles(contractOrImpl, qualifiers);
return handles.stream()
.filter(ServiceHandle::isActive)
.map(ServiceHandle::getService)
.collect(Collectors.toList());
}
/** /**
* This is for unit testing ONLY. Do not use this constructor. * This is for unit testing ONLY. Do not use this constructor.
* *

View File

@ -7,6 +7,9 @@
package org.mvplugins.multiverse.core.api; package org.mvplugins.multiverse.core.api;
import org.mvplugins.multiverse.core.inject.PluginServiceLocator;
import org.mvplugins.multiverse.core.inject.PluginServiceLocatorFactory;
/** /**
* Multiverse 2 Core API * Multiverse 2 Core API
* <p> * <p>
@ -14,6 +17,13 @@ package org.mvplugins.multiverse.core.api;
*/ */
public interface MVCore extends MVPlugin { public interface MVCore extends MVPlugin {
/**
* Gets the {@link PluginServiceLocatorFactory} used to create {@link PluginServiceLocator}s.
*
* @return The {@link PluginServiceLocatorFactory}
*/
PluginServiceLocatorFactory getServiceLocatorFactory();
/** /**
* Saves all configs. * Saves all configs.
* *

View File

@ -7,6 +7,8 @@
package org.mvplugins.multiverse.core.api; package org.mvplugins.multiverse.core.api;
import org.mvplugins.multiverse.core.inject.PluginServiceLocator;
/** /**
* This interface is implemented by every official Multiverse-plugin. * This interface is implemented by every official Multiverse-plugin.
*/ */
@ -33,4 +35,11 @@ public interface MVPlugin {
* @return The readable authors-{@link String} * @return The readable authors-{@link String}
*/ */
String getAuthors(); String getAuthors();
/**
* Gets the {@link PluginServiceLocator} for this plugin.
*
* @return The {@link PluginServiceLocator}
*/
PluginServiceLocator getServiceLocator();
} }

View File

@ -20,7 +20,7 @@ import org.mvplugins.multiverse.core.utils.MVCorei18n;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class CheckCommand extends MultiverseCommand { class CheckCommand extends CoreCommand {
private final DestinationsProvider destinationsProvider; private final DestinationsProvider destinationsProvider;

View File

@ -24,7 +24,7 @@ import org.mvplugins.multiverse.core.world.options.CloneWorldOptions;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class CloneCommand extends MultiverseCommand { class CloneCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;

View File

@ -20,7 +20,7 @@ import org.mvplugins.multiverse.core.exceptions.MultiverseException;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class ConfigCommand extends MultiverseCommand { class ConfigCommand extends CoreCommand {
private final MVCoreConfig config; private final MVCoreConfig config;

View File

@ -14,7 +14,7 @@ import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class ConfirmCommand extends MultiverseCommand { class ConfirmCommand extends CoreCommand {
@Inject @Inject
ConfirmCommand(@NotNull MVCommandManager commandManager) { ConfirmCommand(@NotNull MVCommandManager commandManager) {

View File

@ -19,7 +19,7 @@ import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class CoordinatesCommand extends MultiverseCommand { class CoordinatesCommand extends CoreCommand {
private final LocationManipulation locationManipulation; private final LocationManipulation locationManipulation;

View File

@ -0,0 +1,13 @@
package org.mvplugins.multiverse.core.commands;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Contract;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
@Contract
public abstract class CoreCommand extends MultiverseCommand {
protected CoreCommand(@NotNull MVCommandManager commandManager) {
super(commandManager);
}
}

View File

@ -30,7 +30,7 @@ import org.mvplugins.multiverse.core.world.options.CreateWorldOptions;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class CreateCommand extends MultiverseCommand { class CreateCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;
private GeneratorProvider generatorProvider; private GeneratorProvider generatorProvider;

View File

@ -19,7 +19,7 @@ import org.mvplugins.multiverse.core.utils.MVCorei18n;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class DebugCommand extends MultiverseCommand { class DebugCommand extends CoreCommand {
private final MVCoreConfig config; private final MVCoreConfig config;

View File

@ -31,7 +31,7 @@ import org.mvplugins.multiverse.core.world.helpers.PlayerWorldTeleporter;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class DeleteCommand extends MultiverseCommand { class DeleteCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;
private final PlayerWorldTeleporter playerWorldTeleporter; private final PlayerWorldTeleporter playerWorldTeleporter;

View File

@ -42,7 +42,7 @@ import static org.mvplugins.multiverse.core.utils.file.FileUtils.getServerProper
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class DumpsCommand extends MultiverseCommand { class DumpsCommand extends CoreCommand {
private final MultiverseCore plugin; private final MultiverseCore plugin;
private final WorldManager worldManager; private final WorldManager worldManager;

View File

@ -41,7 +41,7 @@ import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
@Subcommand("gamerule|rule|gamerules|rules") @Subcommand("gamerule|rule|gamerules|rules")
class GameruleCommand extends MultiverseCommand { class GameruleCommand extends CoreCommand {
private final CommandValueFlag<Integer> PAGE_FLAG = flag(CommandValueFlag private final CommandValueFlag<Integer> PAGE_FLAG = flag(CommandValueFlag
.builder("--page", Integer.class) .builder("--page", Integer.class)

View File

@ -35,7 +35,7 @@ import org.mvplugins.multiverse.core.world.generators.GeneratorProvider;
*/ */
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class GeneratorsCommand extends MultiverseCommand { class GeneratorsCommand extends CoreCommand {
private final GeneratorProvider generatorProvider; private final GeneratorProvider generatorProvider;

View File

@ -27,7 +27,7 @@ import org.mvplugins.multiverse.core.world.options.ImportWorldOptions;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class ImportCommand extends MultiverseCommand { class ImportCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;

View File

@ -35,7 +35,7 @@ import org.mvplugins.multiverse.core.world.MultiverseWorld;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class InfoCommand extends MultiverseCommand { class InfoCommand extends CoreCommand {
private final CommandValueFlag<Integer> PAGE_FLAG = flag(CommandValueFlag private final CommandValueFlag<Integer> PAGE_FLAG = flag(CommandValueFlag
.builder("--page", Integer.class) .builder("--page", Integer.class)

View File

@ -36,7 +36,7 @@ import org.mvplugins.multiverse.core.world.entrycheck.WorldEntryCheckerProvider;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class ListCommand extends MultiverseCommand { class ListCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;
private final WorldEntryCheckerProvider worldEntryCheckerProvider; private final WorldEntryCheckerProvider worldEntryCheckerProvider;

View File

@ -21,7 +21,7 @@ import org.mvplugins.multiverse.core.world.WorldManager;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class LoadCommand extends MultiverseCommand { class LoadCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;

View File

@ -24,7 +24,7 @@ import org.mvplugins.multiverse.core.world.WorldManager;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class ModifyCommand extends MultiverseCommand { class ModifyCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;

View File

@ -34,7 +34,7 @@ import org.mvplugins.multiverse.core.world.options.RegenWorldOptions;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class RegenCommand extends MultiverseCommand { class RegenCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;
private final PlayerWorldTeleporter playerWorldTeleporter; private final PlayerWorldTeleporter playerWorldTeleporter;

View File

@ -23,7 +23,7 @@ import org.mvplugins.multiverse.core.world.WorldManager;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class ReloadCommand extends MultiverseCommand { class ReloadCommand extends CoreCommand {
private final MVCoreConfig config; private final MVCoreConfig config;
private final AnchorManager anchorManager; private final AnchorManager anchorManager;

View File

@ -29,7 +29,7 @@ import org.mvplugins.multiverse.core.world.helpers.PlayerWorldTeleporter;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class RemoveCommand extends MultiverseCommand { class RemoveCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;
private final PlayerWorldTeleporter playerWorldTeleporter; private final PlayerWorldTeleporter playerWorldTeleporter;

View File

@ -14,7 +14,7 @@ import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
import org.mvplugins.multiverse.core.utils.MVCorei18n; import org.mvplugins.multiverse.core.utils.MVCorei18n;
@Service @Service
class RootCommand extends MultiverseCommand { class RootCommand extends CoreCommand {
private final Plugin plugin; private final Plugin plugin;

View File

@ -18,7 +18,7 @@ import org.mvplugins.multiverse.core.world.WorldManager;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
public class SetSpawnCommand extends MultiverseCommand { public class SetSpawnCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;

View File

@ -19,7 +19,7 @@ import org.mvplugins.multiverse.core.world.WorldManager;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class SpawnCommand extends MultiverseCommand { class SpawnCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;
private final AsyncSafetyTeleporter safetyTeleporter; private final AsyncSafetyTeleporter safetyTeleporter;

View File

@ -25,7 +25,7 @@ import org.mvplugins.multiverse.core.utils.MVCorei18n;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class TeleportCommand extends MultiverseCommand { class TeleportCommand extends CoreCommand {
private final CorePermissionsChecker permissionsChecker; private final CorePermissionsChecker permissionsChecker;
private final AsyncSafetyTeleporter safetyTeleporter; private final AsyncSafetyTeleporter safetyTeleporter;

View File

@ -28,7 +28,7 @@ import org.mvplugins.multiverse.core.world.options.UnloadWorldOptions;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class UnloadCommand extends MultiverseCommand { class UnloadCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;
private final PlayerWorldTeleporter playerWorldTeleporter; private final PlayerWorldTeleporter playerWorldTeleporter;

View File

@ -17,7 +17,7 @@ import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class UsageCommand extends MultiverseCommand { class UsageCommand extends CoreCommand {
@Inject @Inject
UsageCommand(@NotNull MVCommandManager commandManager) { UsageCommand(@NotNull MVCommandManager commandManager) {

View File

@ -16,7 +16,7 @@ import org.mvplugins.multiverse.core.utils.MVCorei18n;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
class VersionCommand extends MultiverseCommand { class VersionCommand extends CoreCommand {
private final MultiverseCore plugin; private final MultiverseCore plugin;

View File

@ -37,7 +37,7 @@ import java.util.stream.Collectors;
@Service @Service
@CommandAlias("mv") @CommandAlias("mv")
public class WhoCommand extends MultiverseCommand { public class WhoCommand extends CoreCommand {
private final WorldManager worldManager; private final WorldManager worldManager;

View File

@ -1,7 +0,0 @@
package org.mvplugins.multiverse.core.inject;
import org.bukkit.event.Listener;
import org.jvnet.hk2.annotations.Contract;
@Contract
public interface InjectableListener extends Listener { }

View File

@ -1,121 +0,0 @@
package org.mvplugins.multiverse.core.inject;
import io.vavr.control.Try;
import org.bukkit.plugin.Plugin;
import org.glassfish.hk2.api.DynamicConfigurationService;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.api.ServiceLocatorFactory;
import org.glassfish.hk2.internal.ServiceLocatorFactoryImpl;
import org.glassfish.hk2.utilities.ClasspathDescriptorFileFinder;
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
import org.jetbrains.annotations.NotNull;
import org.mvplugins.multiverse.core.inject.binder.JavaPluginBinder;
import org.mvplugins.multiverse.core.inject.binder.PluginBinder;
import org.mvplugins.multiverse.core.inject.binder.ServerBinder;
/**
* Provides methods to set up dependency injection for plugins.
* <br/>
* This class is a wrapper around the HK2 dependency injection library. It provides methods to create a service locators
* for plugins and to perform injection tasks on plugin instances on enable and disable.
*/
public final class PluginInjection {
/**
* Creates a {@link ServiceLocator} for the given plugin binder.
* <br/>
* The service locator is populated with the plugin instance and all dependencies that are bound in the
* {@link PluginBinder} of the plugin. Plugins must implement their own {@link PluginBinder} to use this class.
* {@link JavaPluginBinder} is provided as a convenience for plugins that extend
* {@link org.bukkit.plugin.java.JavaPlugin}.
*
* @param pluginBinder The plugin binder for the plugin.
* @return A {@link ServiceLocator} for the plugin.
*/
@NotNull
public static Try<ServiceLocator> createServiceLocator(@NotNull PluginBinder<?> pluginBinder) {
var factory = new ServiceLocatorFactoryImpl();
return createSystemServiceLocator(factory)
.flatMap(systemLocator -> createServerServiceLocator(factory, systemLocator))
.flatMap(serverLocator -> new PluginInjection(pluginBinder, factory, serverLocator).load());
}
/**
* Performs necessary steps to enable dependency injection for the given plugin.
* <br/>
* This method will inject all dependencies into the plugin instance and call the {@code @PostConstruct} methods.
*
* @param plugin The plugin to enable dependency injection for.
* @param pluginServiceLocator The service locator for the plugin.
*/
public static void enable(@NotNull Plugin plugin, @NotNull ServiceLocator pluginServiceLocator) {
pluginServiceLocator.inject(plugin);
pluginServiceLocator.postConstruct(plugin);
}
/**
* Performs necessary steps to disable dependency injection for the given plugin.
* <br/>
* This method will call the {@code @PreDestroy} methods and shutdown the service locator.
*
* @param plugin The plugin to disable dependency injection for.
* @param pluginServiceLocator The service locator for the plugin.
*/
public static void disable(@NotNull Plugin plugin, @NotNull ServiceLocator pluginServiceLocator) {
pluginServiceLocator.preDestroy(plugin);
pluginServiceLocator.shutdown();
}
private final PluginBinder<?> pluginBinder;
private final Plugin plugin;
private final ServiceLocator pluginServiceLocator;
private PluginInjection(
@NotNull PluginBinder<?> pluginBinder,
@NotNull ServiceLocatorFactory serviceLocatorFactory,
@NotNull ServiceLocator serverServiceLocator) {
this.pluginBinder = pluginBinder;
plugin = pluginBinder.getPlugin();
pluginServiceLocator = serviceLocatorFactory.create(plugin.getName(), serverServiceLocator);
}
private Try<ServiceLocator> load() {
return Try.runRunnable(() -> ServiceLocatorUtilities.bind(pluginServiceLocator, pluginBinder))
.flatMap(ignored -> populatePluginServiceLocator(pluginServiceLocator, plugin));
}
@NotNull
private static Try<ServiceLocator> createServerServiceLocator(
@NotNull ServiceLocatorFactory serviceLocatorFactory,
@NotNull ServiceLocator systemServiceLocator) {
return Try.of(() -> serviceLocatorFactory.create("server", systemServiceLocator))
.andThenTry(locator -> ServiceLocatorUtilities.bind(locator, new ServerBinder()));
}
@NotNull
private static Try<ServiceLocator> createSystemServiceLocator(
@NotNull ServiceLocatorFactory serviceLocatorFactory) {
ServiceLocator serviceLocator = serviceLocatorFactory.create("system");
return Try.of(() -> serviceLocator.getService(DynamicConfigurationService.class))
.mapTry(dynamicConfigurationService -> {
dynamicConfigurationService.getPopulator().populate();
return serviceLocator;
});
}
@NotNull
private static Try<ServiceLocator> populatePluginServiceLocator(
@NotNull ServiceLocator serviceLocator,
@NotNull Plugin plugin) {
return Try.of(() -> serviceLocator.getService(DynamicConfigurationService.class))
.mapTry(dynamicConfigurationService -> {
dynamicConfigurationService.getPopulator().populate(new ClasspathDescriptorFileFinder(
plugin.getClass().getClassLoader(),
plugin.getName()));
return serviceLocator;
});
}
}

View File

@ -0,0 +1,148 @@
package org.mvplugins.multiverse.core.inject;
import io.vavr.control.Try;
import org.bukkit.plugin.Plugin;
import org.glassfish.hk2.api.DynamicConfigurationService;
import org.glassfish.hk2.api.MultiException;
import org.glassfish.hk2.api.ServiceHandle;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.ClasspathDescriptorFileFinder;
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mvplugins.multiverse.core.inject.binder.PluginBinder;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.stream.Collectors;
public class PluginServiceLocator {
private final PluginBinder<?> pluginBinder;
private final ServiceLocator serviceLocator;
PluginServiceLocator(@NotNull PluginBinder<?> pluginBinder, @NotNull ServiceLocator serviceLocator) {
this.pluginBinder = pluginBinder;
this.serviceLocator = serviceLocator;
}
@NotNull
public Try<PluginServiceLocator> enable() {
return bindPlugin()
.flatMap(ignore -> populateServices())
.flatMap(ignore -> injectPlugin())
.mapTry(ignore -> this);
}
public void disable() {
serviceLocator.preDestroy(pluginBinder.getPlugin());
}
@NotNull
private Try<Void> bindPlugin() {
return Try.of(() -> {
ServiceLocatorUtilities.bind(serviceLocator, pluginBinder);
return null;
});
}
@NotNull
private Try<Void> populateServices() {
Plugin plugin = pluginBinder.getPlugin();
return Try.of(() -> serviceLocator.getService(DynamicConfigurationService.class))
.mapTry(dynamicConfigurationService -> {
dynamicConfigurationService.getPopulator().populate(new ClasspathDescriptorFileFinder(
plugin.getClass().getClassLoader(),
plugin.getName())
);
return null;
});
}
@NotNull
private Try<Void> injectPlugin() {
return Try.of(() -> {
serviceLocator.inject(pluginBinder.getPlugin());
serviceLocator.postConstruct(pluginBinder.getPlugin());
return null;
});
}
/**
* Gets the best service from this plugin that implements the given contract or has the given implementation.
* Service will be instantiated if it is not already instantiated.
*
* @param contractOrImpl The contract or concrete implementation to get the best instance of
* @param qualifiers The set of qualifiers that must match this service definition
* @param <T> The type of the contract to get
* @return An instance of the contract or impl if it is a service, null otherwise
* @throws MultiException
*/
@Nullable
public <T> T getService(@NotNull Class<T> contractOrImpl, Annotation... qualifiers) throws MultiException {
return serviceLocator.getService(contractOrImpl, qualifiers);
}
/**
* Gets the best active service from this plugin that implements the given contract or has the given implementation.
*
* @param contractOrImpl The contract or concrete implementation to get the best instance of
* @param qualifiers The set of qualifiers that must match this service definition
* @param <T> The type of the contract to get
* @return An instance of the contract or impl if it is a service and is already instantiated, null otherwise
* @throws MultiException if there was an error during service lookup
*/
@Nullable
public <T> T getActiveService(@NotNull Class<T> contractOrImpl, Annotation... qualifiers) throws MultiException {
var handle = serviceLocator.getServiceHandle(contractOrImpl, qualifiers);
if (handle != null && handle.isActive()) {
return handle.getService();
}
return null;
}
/**
* Gets all services from this plugin that implement the given contract or have the given implementation and have
* the provided qualifiers. Services will be instantiated if it is not already instantiated.
*
* @param contractOrImpl The contract or concrete implementation to get the best instance of
* @param qualifiers The set of qualifiers that must match this service definition
* @param <T> The type of the contract to get
* @return A list of services implementing this contract or concrete implementation. May not return null, but may
* return an empty list.
* @throws MultiException if there was an error during service lookup
*/
@NotNull
public <T> List<T> getAllServices(
@NotNull Class<T> contractOrImpl,
Annotation... qualifiers) throws MultiException {
return serviceLocator.getAllServices(contractOrImpl, qualifiers);
}
/**
* Gets all services from this plugin that implement the given contract or have the given implementation and have
* the provided qualifiers.
*
* @param contractOrImpl The contract or concrete implementation to get the best instance of
* @param qualifiers The set of qualifiers that must match this service definition
* @param <T> The type of the contract to get
* @return A list of services already instantiated implementing this contract or concrete implementation.
* May not return null, but may return an empty list.
* @throws MultiException if there was an error during service lookup
*/
@NotNull
public <T> List<T> getAllActiveServices(
@NotNull Class<T> contractOrImpl,
Annotation... qualifiers) throws MultiException {
var handles = serviceLocator.getAllServiceHandles(contractOrImpl, qualifiers);
return handles.stream()
.filter(ServiceHandle::isActive)
.map(ServiceHandle::getService)
.collect(Collectors.toList());
}
@NotNull
ServiceLocator getServiceLocator() {
return serviceLocator;
}
}

View File

@ -0,0 +1,75 @@
package org.mvplugins.multiverse.core.inject;
import io.vavr.control.Try;
import org.bukkit.plugin.Plugin;
import org.glassfish.hk2.api.DynamicConfigurationService;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.api.ServiceLocatorFactory;
import org.glassfish.hk2.internal.ServiceLocatorFactoryImpl;
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mvplugins.multiverse.core.inject.binder.PluginBinder;
import org.mvplugins.multiverse.core.inject.binder.ServerBinder;
public class PluginServiceLocatorFactory {
private final ServiceLocatorFactory serviceLocatorFactory;
private ServiceLocator baseServiceLocator;
public PluginServiceLocatorFactory() {
this.serviceLocatorFactory = new ServiceLocatorFactoryImpl();
}
@NotNull
public Try<Void> init() {
return createSystemServiceLocator()
.flatMap(this::createServerServiceLocator)
.mapTry(locator -> {
baseServiceLocator = locator;
return null;
});
}
public void shutdown() {
baseServiceLocator.shutdown();
}
@NotNull
private Try<ServiceLocator> createSystemServiceLocator() {
return Try.of(() -> serviceLocatorFactory.create("system"))
.mapTry(systemServiceLocator -> {
systemServiceLocator.getService(DynamicConfigurationService.class)
.getPopulator()
.populate();
return systemServiceLocator;
});
}
@NotNull
private Try<ServiceLocator> createServerServiceLocator(@NotNull ServiceLocator systemServiceLocator) {
return Try.of(() -> serviceLocatorFactory.create("server", systemServiceLocator))
.mapTry(locator -> {
ServiceLocatorUtilities.bind(locator, new ServerBinder());
return locator;
});
}
public <T extends Plugin> Try<PluginServiceLocator> registerPlugin(@NotNull PluginBinder<T> pluginBinder) {
return createPluginServiceLocator(pluginBinder, baseServiceLocator);
}
public <T extends Plugin> Try<PluginServiceLocator> registerPlugin(
@NotNull PluginBinder<T> pluginBinder,
@NotNull PluginServiceLocator parentServiceLocator) {
return createPluginServiceLocator(pluginBinder, parentServiceLocator.getServiceLocator());
}
private <T extends Plugin> Try<PluginServiceLocator> createPluginServiceLocator(
@NotNull PluginBinder<T> pluginBinder,
@Nullable ServiceLocator parentServiceLocator) {
return Try.of(() -> new PluginServiceLocator(
pluginBinder,
serviceLocatorFactory.create(pluginBinder.getPlugin().getName(), parentServiceLocator)));
}
}

View File

@ -0,0 +1,7 @@
package org.mvplugins.multiverse.core.listeners;
import org.bukkit.event.Listener;
import org.jvnet.hk2.annotations.Contract;
@Contract
public interface CoreListener extends Listener { }

View File

@ -7,14 +7,13 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.config.MVCoreConfig; import org.mvplugins.multiverse.core.config.MVCoreConfig;
import org.mvplugins.multiverse.core.inject.InjectableListener;
import org.mvplugins.multiverse.core.world.WorldManager; import org.mvplugins.multiverse.core.world.WorldManager;
/** /**
* Multiverse's Listener for players. * Multiverse's Listener for players.
*/ */
@Service @Service
public class MVChatListener implements InjectableListener { public class MVChatListener implements CoreListener {
private final MVCoreConfig config; private final MVCoreConfig config;
private final WorldManager worldManager; private final WorldManager worldManager;
private final MVPlayerListener playerListener; private final MVPlayerListener playerListener;

View File

@ -20,7 +20,6 @@ import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.inject.InjectableListener;
import org.mvplugins.multiverse.core.world.WorldManager; import org.mvplugins.multiverse.core.world.WorldManager;
import org.mvplugins.multiverse.core.world.WorldPurger; import org.mvplugins.multiverse.core.world.WorldPurger;
@ -28,7 +27,7 @@ import org.mvplugins.multiverse.core.world.WorldPurger;
* Multiverse's Entity {@link Listener}. * Multiverse's Entity {@link Listener}.
*/ */
@Service @Service
public class MVEntityListener implements InjectableListener { public class MVEntityListener implements CoreListener {
private final WorldManager worldManager; private final WorldManager worldManager;
private final WorldPurger worldPurger; private final WorldPurger worldPurger;

View File

@ -40,7 +40,6 @@ import org.mvplugins.multiverse.core.destination.DestinationsProvider;
import org.mvplugins.multiverse.core.destination.ParsedDestination; import org.mvplugins.multiverse.core.destination.ParsedDestination;
import org.mvplugins.multiverse.core.economy.MVEconomist; import org.mvplugins.multiverse.core.economy.MVEconomist;
import org.mvplugins.multiverse.core.event.MVRespawnEvent; import org.mvplugins.multiverse.core.event.MVRespawnEvent;
import org.mvplugins.multiverse.core.inject.InjectableListener;
import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter; import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter;
import org.mvplugins.multiverse.core.teleportation.TeleportQueue; import org.mvplugins.multiverse.core.teleportation.TeleportQueue;
import org.mvplugins.multiverse.core.utils.result.ResultChain; import org.mvplugins.multiverse.core.utils.result.ResultChain;
@ -54,7 +53,7 @@ import org.mvplugins.multiverse.core.world.helpers.EnforcementHandler;
* Multiverse's Listener for players. * Multiverse's Listener for players.
*/ */
@Service @Service
public class MVPlayerListener implements InjectableListener { public class MVPlayerListener implements CoreListener {
private final Plugin plugin; private final Plugin plugin;
private final MVCoreConfig config; private final MVCoreConfig config;
private final Provider<WorldManager> worldManagerProvider; private final Provider<WorldManager> worldManagerProvider;

View File

@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.config.MVCoreConfig; import org.mvplugins.multiverse.core.config.MVCoreConfig;
import org.mvplugins.multiverse.core.inject.InjectableListener;
import org.mvplugins.multiverse.core.world.WorldManager; import org.mvplugins.multiverse.core.world.WorldManager;
import static org.bukkit.PortalType.CUSTOM; import static org.bukkit.PortalType.CUSTOM;
@ -30,7 +29,7 @@ import static org.bukkit.PortalType.CUSTOM;
* A custom listener for portal related events. * A custom listener for portal related events.
*/ */
@Service @Service
public class MVPortalListener implements InjectableListener { public class MVPortalListener implements CoreListener {
private final MVCoreConfig config; private final MVCoreConfig config;
private final WorldManager worldManager; private final WorldManager worldManager;

View File

@ -14,14 +14,13 @@ import org.bukkit.event.weather.ThunderChangeEvent;
import org.bukkit.event.weather.WeatherChangeEvent; import org.bukkit.event.weather.WeatherChangeEvent;
import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.inject.InjectableListener;
import org.mvplugins.multiverse.core.world.WorldManager; import org.mvplugins.multiverse.core.world.WorldManager;
/** /**
* Multiverse's Weather Listener. * Multiverse's Weather Listener.
*/ */
@Service @Service
public class MVWeatherListener implements InjectableListener { public class MVWeatherListener implements CoreListener {
private final WorldManager worldManager; private final WorldManager worldManager;

View File

@ -15,7 +15,6 @@ import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent; import org.bukkit.event.world.WorldUnloadEvent;
import org.jvnet.hk2.annotations.Service; import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.inject.InjectableListener;
import org.mvplugins.multiverse.core.world.WorldManager; import org.mvplugins.multiverse.core.world.WorldManager;
import org.mvplugins.multiverse.core.world.options.UnloadWorldOptions; import org.mvplugins.multiverse.core.world.options.UnloadWorldOptions;
import org.mvplugins.multiverse.core.world.reasons.LoadFailureReason; import org.mvplugins.multiverse.core.world.reasons.LoadFailureReason;
@ -25,7 +24,7 @@ import org.mvplugins.multiverse.core.world.reasons.UnloadFailureReason;
* Multiverse's World Listener. * Multiverse's World Listener.
*/ */
@Service @Service
public class MVWorldListener implements InjectableListener { public class MVWorldListener implements CoreListener {
private final WorldManager worldManager; private final WorldManager worldManager;

View File

@ -28,7 +28,7 @@ public class WorldConfigNodes {
private LoadedMultiverseWorld world = null; private LoadedMultiverseWorld world = null;
WorldConfigNodes(@NotNull MultiverseCore multiverseCore) { WorldConfigNodes(@NotNull MultiverseCore multiverseCore) {
this.enforcementHandler = multiverseCore.getService(EnforcementHandler.class); this.enforcementHandler = multiverseCore.getServiceLocator().getActiveService(EnforcementHandler.class);
} }
LoadedMultiverseWorld getWorld() { LoadedMultiverseWorld getWorld() {

View File

@ -2,6 +2,7 @@ package org.mvplugins.multiverse.core
import be.seeseemelk.mockbukkit.MockBukkit import be.seeseemelk.mockbukkit.MockBukkit
import be.seeseemelk.mockbukkit.ServerMock import be.seeseemelk.mockbukkit.ServerMock
import org.mvplugins.multiverse.core.inject.PluginServiceLocator
import org.mvplugins.multiverse.core.utils.TestingMode import org.mvplugins.multiverse.core.utils.TestingMode
import kotlin.test.AfterTest import kotlin.test.AfterTest
import kotlin.test.BeforeTest import kotlin.test.BeforeTest
@ -13,12 +14,14 @@ abstract class TestWithMockBukkit {
protected lateinit var server: ServerMock protected lateinit var server: ServerMock
protected lateinit var multiverseCore: MultiverseCore protected lateinit var multiverseCore: MultiverseCore
protected lateinit var serviceLocator : PluginServiceLocator
@BeforeTest @BeforeTest
fun setUpMockBukkit() { fun setUpMockBukkit() {
TestingMode.enable() TestingMode.enable()
server = MockBukkit.mock() server = MockBukkit.mock()
multiverseCore = MockBukkit.load(MultiverseCore::class.java) multiverseCore = MockBukkit.load(MultiverseCore::class.java)
serviceLocator = multiverseCore.serviceLocator
} }
@AfterTest @AfterTest

View File

@ -23,8 +23,8 @@ class LocalizationTest : TestWithMockBukkit() {
@BeforeTest @BeforeTest
fun setUpLocale() { fun setUpLocale() {
locales = assertNotNull(multiverseCore.getService(PluginLocales::class.java)) locales = assertNotNull(serviceLocator.getActiveService(PluginLocales::class.java))
commandManager = assertNotNull(multiverseCore.getService(MVCommandManager::class.java)) commandManager = assertNotNull(serviceLocator.getActiveService(MVCommandManager::class.java))
} }
@Nested @Nested

View File

@ -12,7 +12,7 @@ class ConfigTest : TestWithMockBukkit() {
@BeforeTest @BeforeTest
fun setUp() { fun setUp() {
config = multiverseCore.getService(MVCoreConfig::class.java).takeIf { it != null } ?: run { config = serviceLocator.getActiveService(MVCoreConfig::class.java).takeIf { it != null } ?: run {
throw IllegalStateException("MVCoreConfig is not available as a service") } throw IllegalStateException("MVCoreConfig is not available as a service") }
val defaultConfig = getResourceAsText("/default_config.yml") val defaultConfig = getResourceAsText("/default_config.yml")

View File

@ -17,90 +17,91 @@ import org.mvplugins.multiverse.core.teleportation.SimpleLocationManipulation
import org.mvplugins.multiverse.core.teleportation.TeleportQueue import org.mvplugins.multiverse.core.teleportation.TeleportQueue
import org.mvplugins.multiverse.core.utils.metrics.MetricsConfigurator import org.mvplugins.multiverse.core.utils.metrics.MetricsConfigurator
import org.mvplugins.multiverse.core.world.WorldManager import org.mvplugins.multiverse.core.world.WorldManager
import org.mvplugins.multiverse.core.world.config.WorldsConfigManager
import kotlin.test.* import kotlin.test.*
class InjectionTest : TestWithMockBukkit() { class InjectionTest : TestWithMockBukkit() {
@Test @Test
fun `AnchorManager is available as a service`() { fun `AnchorManager is available as a service`() {
assertNotNull(multiverseCore.getService(AnchorManager::class.java)) assertNotNull(serviceLocator.getActiveService(AnchorManager::class.java))
} }
@Test @Test
fun `AsyncSafetyTeleporter is available as a service`() { fun `AsyncSafetyTeleporter is available as a service`() {
assertNotNull(multiverseCore.getService(AsyncSafetyTeleporter::class.java)) assertNotNull(serviceLocator.getActiveService(AsyncSafetyTeleporter::class.java))
} }
@Test @Test
fun `BlockSafety is available as a service`() { fun `BlockSafety is available as a service`() {
assertNotNull(multiverseCore.getService(BlockSafety::class.java)) assertNotNull(serviceLocator.getActiveService(BlockSafety::class.java))
assertNotNull(multiverseCore.getService(SimpleBlockSafety::class.java)) assertNotNull(serviceLocator.getActiveService(SimpleBlockSafety::class.java))
} }
@Test @Test
fun `MVCommandManager is available as a service`() { fun `MVCommandManager is available as a service`() {
assertNotNull(multiverseCore.getService(MVCommandManager::class.java)) assertNotNull(serviceLocator.getActiveService(MVCommandManager::class.java))
} }
@Test @Test
fun `MVEconomist is available as a service`() { fun `MVEconomist is available as a service`() {
assertNotNull(multiverseCore.getService(MVEconomist::class.java)) assertNotNull(serviceLocator.getActiveService(MVEconomist::class.java))
} }
@Test @Test
fun `LocationManipulation is available as a service`() { fun `LocationManipulation is available as a service`() {
assertNotNull(multiverseCore.getService(LocationManipulation::class.java)) assertNotNull(serviceLocator.getActiveService(LocationManipulation::class.java))
assertNotNull(multiverseCore.getService(SimpleLocationManipulation::class.java)) assertNotNull(serviceLocator.getActiveService(SimpleLocationManipulation::class.java))
} }
@Test @Test
fun `TeleportQueue is available as a service`() { fun `TeleportQueue is available as a service`() {
assertNotNull(multiverseCore.getService(TeleportQueue::class.java)) assertNotNull(serviceLocator.getActiveService(TeleportQueue::class.java))
} }
@Test @Test
fun `MVWorldManager is available as a service`() { fun `MVWorldManager is available as a service`() {
assertNotNull(multiverseCore.getService(WorldManager::class.java)) assertNotNull(serviceLocator.getActiveService(WorldManager::class.java))
} }
@Test @Test
fun `MVEntityListener is available as a service`() { fun `MVEntityListener is available as a service`() {
assertNotNull(multiverseCore.getService(MVEntityListener::class.java)) assertNotNull(serviceLocator.getActiveService(MVEntityListener::class.java))
} }
@Test @Test
fun `MVPlayerListener is available as a service`() { fun `MVPlayerListener is available as a service`() {
assertNotNull(multiverseCore.getService(MVPlayerListener::class.java)) assertNotNull(serviceLocator.getActiveService(MVPlayerListener::class.java))
} }
@Test @Test
fun `MVChatListener is available as a service`() { fun `MVChatListener is available as a service`() {
assertNotNull(multiverseCore.getService(MVChatListener::class.java)) assertNotNull(serviceLocator.getActiveService(MVChatListener::class.java))
} }
@Test @Test
fun `MVPortalListener is available as a service`() { fun `MVPortalListener is available as a service`() {
assertNotNull(multiverseCore.getService(MVPortalListener::class.java)) assertNotNull(serviceLocator.getActiveService(MVPortalListener::class.java))
} }
@Test @Test
fun `MVWeatherListener is available as a service`() { fun `MVWeatherListener is available as a service`() {
assertNotNull(multiverseCore.getService(MVWeatherListener::class.java)) assertNotNull(serviceLocator.getActiveService(MVWeatherListener::class.java))
} }
@Test @Test
fun `MVWorldListener is available as a service`() { fun `MVWorldListener is available as a service`() {
assertNotNull(multiverseCore.getService(MVWorldListener::class.java)) assertNotNull(serviceLocator.getActiveService(MVWorldListener::class.java))
} }
@Test @Test
fun `MVCoreConfig is available as a service`() { fun `MVCoreConfig is available as a service`() {
assertNotNull(multiverseCore.getService(MVCoreConfig::class.java)) assertNotNull(serviceLocator.getActiveService(MVCoreConfig::class.java))
} }
@Test @Test
fun `Commands are available as services`() { fun `Commands are available as services`() {
val commands = multiverseCore.getAllServices(MultiverseCommand::class.java) val commands = serviceLocator.getAllActiveServices(MultiverseCommand::class.java)
// TODO: come up with a better way to test this like via actually testing the effect of calling each command // TODO: come up with a better way to test this like via actually testing the effect of calling each command
// TODO: comment this until all commands are done // TODO: comment this until all commands are done
// assertEquals(18, commands.size) // assertEquals(18, commands.size)
@ -108,7 +109,7 @@ class InjectionTest : TestWithMockBukkit() {
@Test @Test
fun `Destinations are available as services`() { fun `Destinations are available as services`() {
val destinations = multiverseCore.getAllServices(Destination::class.java) val destinations = serviceLocator.getAllActiveServices(Destination::class.java)
// TODO: come up with a better way to test this like via actually testing the effect of using each destination // TODO: come up with a better way to test this like via actually testing the effect of using each destination
assertEquals(6, destinations.size) assertEquals(6, destinations.size)
} }
@ -116,11 +117,11 @@ class InjectionTest : TestWithMockBukkit() {
@Test @Test
fun `MetricsConfigurator is not available as a service`() { fun `MetricsConfigurator is not available as a service`() {
// Also making sure this is not loaded automatically since it's supposed to be disabled during tests // Also making sure this is not loaded automatically since it's supposed to be disabled during tests
assertNull(multiverseCore.getService(MetricsConfigurator::class.java)) assertNull(serviceLocator.getActiveService(MetricsConfigurator::class.java))
} }
@Test @Test
fun `PluginLocales is available as a service`() { fun `PluginLocales is available as a service`() {
assertNotNull(multiverseCore.getService(PluginLocales::class.java)) assertNotNull(serviceLocator.getActiveService(PluginLocales::class.java))
} }
} }

View File

@ -23,7 +23,7 @@ class WorldConfigMangerTest : TestWithMockBukkit() {
assertNotNull(defaultConfig) assertNotNull(defaultConfig)
File(Path.of(multiverseCore.dataFolder.absolutePath, "worlds2.yml").absolutePathString()).writeText(defaultConfig) File(Path.of(multiverseCore.dataFolder.absolutePath, "worlds2.yml").absolutePathString()).writeText(defaultConfig)
worldConfigManager = multiverseCore.getService(WorldsConfigManager::class.java).takeIf { it != null } ?: run { worldConfigManager = serviceLocator.getActiveService(WorldsConfigManager::class.java).takeIf { it != null } ?: run {
throw IllegalStateException("WorldsConfigManager is not available as a service") } throw IllegalStateException("WorldsConfigManager is not available as a service") }
} }

View File

@ -19,7 +19,7 @@ class WorldConfigTest : TestWithMockBukkit() {
assertNotNull(defaultConfig) assertNotNull(defaultConfig)
File(Path.of(multiverseCore.dataFolder.absolutePath, "worlds2.yml").absolutePathString()).writeText(defaultConfig) File(Path.of(multiverseCore.dataFolder.absolutePath, "worlds2.yml").absolutePathString()).writeText(defaultConfig)
worldConfigManager = multiverseCore.getService(WorldsConfigManager::class.java).takeIf { it != null } ?: run { worldConfigManager = serviceLocator.getActiveService(WorldsConfigManager::class.java).takeIf { it != null } ?: run {
throw IllegalStateException("WorldsConfigManager is not available as a service") } throw IllegalStateException("WorldsConfigManager is not available as a service") }
assertTrue(worldConfigManager.load().isSuccess) assertTrue(worldConfigManager.load().isSuccess)

View File

@ -13,7 +13,7 @@ class WorldManagerTest : TestWithMockBukkit() {
@BeforeTest @BeforeTest
fun setUp() { fun setUp() {
worldManager = multiverseCore.getService(WorldManager::class.java).takeIf { it != null } ?: run { worldManager = serviceLocator.getActiveService(WorldManager::class.java).takeIf { it != null } ?: run {
throw IllegalStateException("WorldManager is not available as a service") } throw IllegalStateException("WorldManager is not available as a service") }
worldManager.createWorld(CreateWorldOptions.worldName("world")) worldManager.createWorld(CreateWorldOptions.worldName("world"))