Skip to content

Commit

Permalink
feat(api,bundle,core): add an interface for BoxBootstrapContext to ac…
Browse files Browse the repository at this point in the history
…cess it from api module
  • Loading branch information
Siroshun09 committed Apr 11, 2024
1 parent 076bb3a commit fee9369
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.okocraft.box.api.bootstrap;

import net.okocraft.box.api.feature.BoxFeature;
import net.okocraft.box.api.feature.FeatureContext;
import net.okocraft.box.api.message.DefaultMessageCollector;
import net.okocraft.box.api.model.manager.EventManager;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.util.function.Function;

public interface BootstrapContext {

static @NotNull BootstrapContext get() {
try {
var clazz = Class.forName("net.okocraft.box.bootstrap.BoxBootstrap");
var bootstrap = clazz.getMethod("get").invoke(null);
var getContext = clazz.getMethod("getContext");
return (BootstrapContext) getContext.invoke(bootstrap);
} catch (ClassNotFoundException | InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
throw new RuntimeException("Could not get BootstrapContext", e);
}
}

@NotNull Path getDataDirectory();

@NotNull String getVersion();

@NotNull EventManager getEventManager();

@NotNull DefaultMessageCollector getDefaultMessageCollector();

@Contract("_ -> this")
@NotNull BootstrapContext addFeature(@NotNull Function<FeatureContext.Registration, ? extends BoxFeature> featureFactory);

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
package net.okocraft.box.bootstrap;

import com.github.siroshun09.event4j.priority.Priority;
import com.github.siroshun09.event4j.simple.EventServiceProvider;
import com.github.siroshun09.messages.api.directory.DirectorySource;
import com.github.siroshun09.messages.api.source.StringMessageMap;
import com.github.siroshun09.messages.api.util.Loader;
import com.github.siroshun09.messages.api.util.PropertiesFile;
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
import net.kyori.adventure.key.Key;
import net.okocraft.box.api.event.BoxEvent;
import net.okocraft.box.api.feature.BoxFeature;
import net.okocraft.box.api.feature.FeatureContext;
import net.okocraft.box.core.message.BoxMessageProvider;
import net.okocraft.box.core.model.manager.event.BoxEventManager;
import net.okocraft.box.storage.api.registry.StorageRegistry;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
Expand All @@ -27,7 +24,7 @@
import java.util.function.Function;
import java.util.function.Supplier;

public final class BoxBootstrapContext {
public final class BoxBootstrapContext implements net.okocraft.box.api.bootstrap.BootstrapContext {

@Contract("_ -> new")
@SuppressWarnings("UnstableApiUsage")
Expand All @@ -41,7 +38,7 @@ public final class BoxBootstrapContext {
private final Path dataDirectory;
private final String version;
private final StorageRegistry storageRegistry;
private final EventServiceProvider<Key, BoxEvent, Priority> eventServiceProvider;
private final BoxEventManager eventManager;
private final BoxMessageProvider.Collector defaultMessageCollector;
private final Map<Locale, Loader<Locale, Map<String, String>>> localizationLoaderMap = new HashMap<>();
private final List<BoxFeature> boxFeatureList = new ArrayList<>();
Expand All @@ -51,30 +48,45 @@ public final class BoxBootstrapContext {
this.dataDirectory = pluginDirectory;
this.version = version;
this.storageRegistry = new StorageRegistry();
this.eventServiceProvider = EventServiceProvider.factory().keyClass(Key.class).eventClass(BoxEvent.class).orderComparator(Priority.COMPARATOR, Priority.NORMAL).create();
this.eventManager = BoxEventManager.create();
this.defaultMessageCollector = BoxMessageProvider.createCollector();
}

public @NotNull Path getPluginDirectory() {
@Override
public @NotNull Path getDataDirectory() {
return dataDirectory;
}

@Override
public @NotNull String getVersion() {
return version;
}

public @NotNull StorageRegistry getStorageRegistry() {
return storageRegistry;
}

public @NotNull EventServiceProvider<Key, BoxEvent, Priority> getEventServiceProvider() {
return this.eventServiceProvider;
@Override
public @NotNull BoxEventManager getEventManager() {
return this.eventManager;
}

@Override
public @NotNull BoxMessageProvider.Collector getDefaultMessageCollector() {
return this.defaultMessageCollector;
}

@Override
@Contract("_ -> this")
public @NotNull BoxBootstrapContext addFeature(@NotNull Function<FeatureContext.Registration, ? extends BoxFeature> featureFactory) {
this.boxFeatureList.add(featureFactory.apply(new FeatureContext.Registration(this.dataDirectory, this.defaultMessageCollector)));
return this;
}

public @NotNull StorageRegistry getStorageRegistry() {
return storageRegistry;
}

public @NotNull List<BoxFeature> getBoxFeatureList() {
return this.boxFeatureList;
}

public void addLocalization(@NotNull Locale locale, @NotNull Supplier<Map<String, String>> defaultMessagesSupplier) {
this.localizationLoaderMap.put(locale, ignored -> {
try {
Expand All @@ -99,14 +111,4 @@ public void addLocalization(@NotNull Locale locale, @NotNull Supplier<Map<String
}
);
}

public @NotNull List<BoxFeature> getBoxFeatureList() {
return this.boxFeatureList;
}

@Contract("_ -> this")
public @NotNull BoxBootstrapContext addFeature(@NotNull Function<FeatureContext.Registration, ? extends BoxFeature> featureFactory) {
this.boxFeatureList.add(featureFactory.apply(new FeatureContext.Registration(this.dataDirectory, this.defaultMessageCollector)));
return this;
}
}
8 changes: 5 additions & 3 deletions bundle/src/main/java/net/okocraft/box/plugin/BoxPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ public BoxPlugin(@NotNull BoxBootstrapContext boxBootstrapContext) {
context = new PluginContext(
this,
boxBootstrapContext.getVersion(),
boxBootstrapContext.getPluginDirectory(),
boxBootstrapContext.getDataDirectory(),
PlatformDependent.createScheduler(this),
boxBootstrapContext.getEventServiceProvider(),
boxBootstrapContext.getEventManager(),
boxBootstrapContext.createMessageProvider(),
new Config(boxBootstrapContext.getPluginDirectory()),
new Config(boxBootstrapContext.getDataDirectory()),
PlatformDependent.createItemProvider(),
PlatformDependent.createCommandRegisterer(this.getName().toLowerCase(Locale.ENGLISH))
);
Expand Down Expand Up @@ -73,6 +73,8 @@ public void onLoad() {

var start = Instant.now();

this.pluginContext.eventManager().initializeAsyncEventCaller(this.pluginContext.scheduler());

try {
StorageHolder.init(this.pluginContext.config().loadAndCreateStorage(this.storageRegistry));
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.okocraft.box.bootstrap;

import net.okocraft.box.api.bootstrap.BootstrapContext;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

class BootstrapContextTest {
@Test
void testGet() {
try (var mock = Mockito.mockStatic(BoxBootstrap.class)) {
var bootstrap = Mockito.mock(BoxBootstrap.class);
var context = Mockito.mock(BoxBootstrapContext.class);
Mockito.when(bootstrap.getContext()).thenReturn(context);
mock.when(BoxBootstrap::get).thenReturn(bootstrap);
Assertions.assertSame(context, BootstrapContext.get());
}
}
}
24 changes: 11 additions & 13 deletions core/src/main/java/net/okocraft/box/core/BoxCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
public class BoxCore implements BoxAPI {

private final PluginContext context;
private final BoxEventManager eventManager;

private Storage storage;
private BoxItemManager itemManager;
Expand All @@ -66,12 +65,11 @@ public class BoxCore implements BoxAPI {

public BoxCore(@NotNull PluginContext context) {
this.context = context;
this.eventManager = new BoxEventManager(context.eventServiceProvider(), context.scheduler());
}

public boolean enable(@NotNull Storage storage) {
if (this.context.config().coreSetting().debug()) {
DebugListener.register(this.eventManager);
DebugListener.register(this.context.eventManager());
BoxLogger.logger().info("Debug mode is ENABLED");
}

Expand All @@ -93,18 +91,18 @@ public boolean enable(@NotNull Storage storage) {
try {
var itemLoadResult = ItemLoader.load(storage.getItemStorage(), this.context.defaultItemProvider());
itemLoadResult.logItemCount();
this.itemManager = new BoxItemManager(storage.getItemStorage(), this.eventManager, this.context.scheduler(), this.context.defaultItemProvider(), itemLoadResult.asIterator());
this.itemManager = new BoxItemManager(storage.getItemStorage(), this.context.eventManager(), this.context.scheduler(), this.context.defaultItemProvider(), itemLoadResult.asIterator());
} catch (Exception e) {
BoxLogger.logger().error("Could not load default/custom items", e);
return false;
}

var stockDataSetting = this.context.config().coreSetting().stockData();
this.stockManager = new BoxStockManager(storage.getStockStorage(), this.eventManager, this.itemManager::getBoxItemOrNull, stockDataSetting.unloadTime(), stockDataSetting.saveInterval(), TimeUnit.SECONDS);
this.stockManager = new BoxStockManager(storage.getStockStorage(), this.context.eventManager(), this.itemManager::getBoxItemOrNull, stockDataSetting.unloadTime(), stockDataSetting.saveInterval(), TimeUnit.SECONDS);

this.customDataManager = new BoxCustomDataManager(storage.getCustomDataStorage());

this.playerMap = new BoxPlayerMapImpl(this.userManager, this.stockManager, this.eventManager, this.context.scheduler(), this.context.messageProvider());
this.playerMap = new BoxPlayerMapImpl(this.userManager, this.stockManager, this.context.eventManager(), this.context.scheduler(), this.context.messageProvider());
this.playerMap.loadAll();

Bukkit.getPluginManager().registerEvents(new PlayerConnectionListener(this.playerMap), context.plugin());
Expand All @@ -131,7 +129,7 @@ public void disable() {

stockManager.close();

DebugListener.unregister(this.eventManager);
DebugListener.unregister(this.context.eventManager());

BoxLogger.logger().info("Closing the storage...");

Expand All @@ -157,7 +155,7 @@ public void accept(Supplier<Component> componentSupplier) {
}
};

DebugListener.unregister(this.eventManager);
DebugListener.unregister(this.context.eventManager());

if (!(sender instanceof ConsoleCommandSender)) {
BoxLogger.logger().info("Reloading box...");
Expand All @@ -172,7 +170,7 @@ public void accept(Supplier<Component> componentSupplier) {
}

if (this.context.config().coreSetting().debug()) {
DebugListener.register(this.eventManager);
DebugListener.register(this.context.eventManager());
BoxLogger.logger().info("Debug mode is ENABLED");
}

Expand All @@ -190,7 +188,7 @@ public void accept(Supplier<Component> componentSupplier) {
if (feature instanceof Reloadable reloadable) {
try {
reloadable.reload(featureReloadContext);
this.eventManager.call(new FeatureEvent(feature, FeatureEvent.Type.RELOAD));
this.context.eventManager().call(new FeatureEvent(feature, FeatureEvent.Type.RELOAD));
} catch (Throwable e) {
playerMessenger.accept(() -> CoreMessages.FEATURE_RELOAD_FAILURE.apply(feature, e).source(source).message());
BoxLogger.logger().error("Could not reload {}", feature.getName(), e);
Expand All @@ -215,7 +213,7 @@ public void accept(Supplier<Component> componentSupplier) {

@Override
public @NotNull BoxEventManager getEventManager() {
return this.eventManager;
return this.context.eventManager();
}

@Override
Expand Down Expand Up @@ -278,7 +276,7 @@ public void initializeFeatures(@NotNull List<BoxFeature> features) {

for (var feature : features) {
initializeFeature(feature, featureMap, context);
this.eventManager.call(new FeatureEvent(feature, FeatureEvent.Type.ENABLE));
this.context.eventManager().call(new FeatureEvent(feature, FeatureEvent.Type.ENABLE));
}
}

Expand Down Expand Up @@ -323,7 +321,7 @@ public void disableAllFeatures() {
continue;
}

this.eventManager.call(new FeatureEvent(feature, FeatureEvent.Type.DISABLE));
this.context.eventManager().call(new FeatureEvent(feature, FeatureEvent.Type.DISABLE));
BoxLogger.logger().info("Feature '{}' has been disabled.", feature.getName());
}
}
Expand Down
7 changes: 2 additions & 5 deletions core/src/main/java/net/okocraft/box/core/PluginContext.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package net.okocraft.box.core;

import com.github.siroshun09.event4j.priority.Priority;
import com.github.siroshun09.event4j.simple.EventServiceProvider;
import net.kyori.adventure.key.Key;
import net.okocraft.box.api.event.BoxEvent;
import net.okocraft.box.api.scheduler.BoxScheduler;
import net.okocraft.box.core.command.CommandRegisterer;
import net.okocraft.box.core.config.Config;
import net.okocraft.box.core.message.BoxMessageProvider;
import net.okocraft.box.core.model.manager.event.BoxEventManager;
import net.okocraft.box.storage.api.util.item.DefaultItemProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
Expand All @@ -18,7 +15,7 @@ public record PluginContext(@NotNull JavaPlugin plugin,
@NotNull String version,
@NotNull Path dataDirectory,
@NotNull BoxScheduler scheduler,
@NotNull EventServiceProvider<Key, BoxEvent, Priority> eventServiceProvider,
@NotNull BoxEventManager eventManager,
@NotNull BoxMessageProvider messageProvider,
@NotNull Config config,
@NotNull DefaultItemProvider defaultItemProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,32 @@
import net.okocraft.box.api.event.BoxEvent;
import net.okocraft.box.api.model.manager.EventManager;
import net.okocraft.box.api.scheduler.BoxScheduler;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.concurrent.ForkJoinPool;
import java.util.function.Consumer;

public class BoxEventManager implements EventManager {

@Contract(" -> new")
public static @NotNull BoxEventManager create() {
return new BoxEventManager(
EventServiceProvider.factory()
.keyClass(Key.class)
.eventClass(BoxEvent.class)
.orderComparator(Priority.COMPARATOR, Priority.NORMAL)
.create()
);
}

private final EventServiceProvider<Key, BoxEvent, Priority> provider;
private final AsyncEventCaller<BoxEvent> asyncEventCaller;
private @Nullable AsyncEventCaller<BoxEvent> asyncEventCaller; // initialize later

public BoxEventManager(@NotNull EventServiceProvider<Key, BoxEvent, Priority> provider, @NotNull BoxScheduler scheduler) {
private BoxEventManager(@NotNull EventServiceProvider<Key, BoxEvent, Priority> provider) {
this.provider = provider;
this.asyncEventCaller = AsyncEventCaller.create(provider.caller(), scheduler::runAsyncTask);
}

@Override
Expand All @@ -33,12 +45,22 @@ public void call(@NotNull BoxEvent event) {

@Override
public void callAsync(@NotNull BoxEvent event) {
this.asyncEventCaller.callAsync(event);
this.callAsync(event, null);
}

@SuppressWarnings("resource")
@Override
public <E extends BoxEvent> void callAsync(@NotNull E event, @Nullable Consumer<? super E> callback) {
this.asyncEventCaller.callAsync(event, callback);
if (this.asyncEventCaller != null) {
this.asyncEventCaller.callAsync(event, callback);
} else {
ForkJoinPool.commonPool().execute(() -> {
this.call(event);
if (callback != null) {
callback.accept(event);
}
});
}
}

@Override
Expand All @@ -60,4 +82,8 @@ public void unsubscribeAll(@NotNull Collection<? extends SubscribedListener<Key,
public void unsubscribeByKey(@NotNull Key key) {
this.provider.unsubscribeByKey(key);
}

public void initializeAsyncEventCaller(@NotNull BoxScheduler scheduler) {
this.asyncEventCaller = AsyncEventCaller.create(this.provider.caller(), scheduler::runAsyncTask);
}
}

0 comments on commit fee9369

Please sign in to comment.