From 574a5e9071a458c8acb543f4e2e12d3577d98107 Mon Sep 17 00:00:00 2001 From: Erik Jan de Wit Date: Sat, 24 Jun 2023 20:43:04 +0200 Subject: [PATCH] refactored interface to make it easier to use with new api --- .../storeys/japi/impl/EventsImpl.java | 5 +-- .../japi/impl/events/EventService.java | 9 ++--- .../storeys/commands/NarrateCommand.java | 8 ++--- .../storeys/commands/StoryCommand.java | 8 ++--- .../storeys/events/ConditionService.java | 5 +-- .../storeys/model/LocationAction.java | 4 +-- .../storeys/plugin/AbstractStoreysPlugin.java | 25 +++---------- .../minecraft/storeys/util/Command.java | 8 +++-- .../storeys/api/impl/TokenCommand.java | 8 ++--- .../storeys/web/LocationToolListener.java | 4 ++- .../minecraft/storeys/web/LoginCommand.java | 14 ++++---- .../storeys/web/StoreysWebPlugin.java | 36 ++++++++++++------- 12 files changed, 65 insertions(+), 69 deletions(-) diff --git a/api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/EventsImpl.java b/api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/EventsImpl.java index 25c0e761..4d4e0b77 100644 --- a/api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/EventsImpl.java +++ b/api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/EventsImpl.java @@ -30,11 +30,11 @@ import java.util.Optional; import java.util.concurrent.ConcurrentLinkedQueue; import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongepowered.api.Sponge; import org.spongepowered.api.command.Command; -import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.command.CommandResult; import org.spongepowered.api.command.registrar.CommandRegistrar; import org.spongepowered.plugin.PluginContainer; @@ -75,6 +75,7 @@ class EventsImpl implements Events, Unregisterable { return; } registrar.get().register(plugin, spec, name); + //TODO Sponge.server().commandManager().updateCommandTreeForPlayer(); unregistrables.add(() -> { }); @@ -104,7 +105,7 @@ class EventsImpl implements Events, Unregisterable { ch.vorburger.minecraft.storeys.japi.impl.events.Callback otherCallback = invoker -> { invokeCallback(invoker, callback); }; - unregistrables.add(eventService.registerInteractEntity(entityName, otherCallback)); + unregistrables.add(eventService.registerInteractEntity(Component.text(entityName), otherCallback)); } @Override public void unregister() { diff --git a/api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/events/EventService.java b/api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/events/EventService.java index 1519055f..8d414a1b 100644 --- a/api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/events/EventService.java +++ b/api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/events/EventService.java @@ -29,12 +29,9 @@ import javax.inject.Inject; import javax.inject.Singleton; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.spongepowered.api.data.Key; import org.spongepowered.api.data.Keys; -import org.spongepowered.api.data.value.Value; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.event.EventManager; import org.spongepowered.api.event.Listener; @@ -50,7 +47,7 @@ private final Collection onPlayerJoinCallbacks = new ConcurrentLinkedQueue<>(); private final Map> onPlayerInsideCallbacks = new ConcurrentHashMap<>(); - private final Map> onInteractEntityEventCallbacks = new ConcurrentHashMap<>(); + private final Map> onInteractEntityEventCallbacks = new ConcurrentHashMap<>(); private final EventManager eventManager; @@ -94,7 +91,7 @@ public Unregisterable registerInsideLocation(String locationName, Callback callb return add(callbacks, callback); } - public Unregisterable registerInteractEntity(String entityName, Callback callback) { + public Unregisterable registerInteractEntity(Component entityName, Callback callback) { Collection callbacks = onInteractEntityEventCallbacks.computeIfAbsent(entityName, name -> new ConcurrentLinkedQueue<>()); return add(callbacks, callback); } @@ -111,7 +108,7 @@ private Unregisterable add(Collection collection, Callback callback) { Optional optEntityNameText = event.entity().get(Keys.DISPLAY_NAME); LOG.debug("InteractEntityEvent: entityName={}; event={}", optEntityNameText, event); optEntityNameText.ifPresent(entityNameText -> { - Collection callbacks = onInteractEntityEventCallbacks.getOrDefault(((TextComponent) entityNameText).content(), + Collection callbacks = onInteractEntityEventCallbacks.getOrDefault(entityNameText, Collections.emptySet()); for (Callback callback : callbacks) { try { diff --git a/storeys/src/main/java/ch/vorburger/minecraft/storeys/commands/NarrateCommand.java b/storeys/src/main/java/ch/vorburger/minecraft/storeys/commands/NarrateCommand.java index 3e70b1c4..00b8917d 100644 --- a/storeys/src/main/java/ch/vorburger/minecraft/storeys/commands/NarrateCommand.java +++ b/storeys/src/main/java/ch/vorburger/minecraft/storeys/commands/NarrateCommand.java @@ -21,8 +21,6 @@ import ch.vorburger.minecraft.storeys.japi.ReadingSpeed; import ch.vorburger.minecraft.storeys.japi.impl.actions.Narrator; import ch.vorburger.minecraft.storeys.util.Command; -import com.google.common.collect.ImmutableList; -import java.util.List; import javax.inject.Inject; import net.kyori.adventure.text.Component; import org.spongepowered.api.command.CommandResult; @@ -42,11 +40,11 @@ public class NarrateCommand implements Command { this.narrator = narrator; } - @Override public List aliases() { - return ImmutableList.of("narrate"); + @Override public String getName() { + return "narrate"; } - @Override public org.spongepowered.api.command.Command callable() { + @Override public org.spongepowered.api.command.Command.Parameterized createCommand() { // TODO when Sponge uses entity names instead of UUIDs: // TODO requiringPermission() return org.spongepowered.api.command.Command.builder().shortDescription(Component.text(("Make an entity character narrate story lines"))) diff --git a/storeys/src/main/java/ch/vorburger/minecraft/storeys/commands/StoryCommand.java b/storeys/src/main/java/ch/vorburger/minecraft/storeys/commands/StoryCommand.java index 66015819..b7bdddc4 100644 --- a/storeys/src/main/java/ch/vorburger/minecraft/storeys/commands/StoryCommand.java +++ b/storeys/src/main/java/ch/vorburger/minecraft/storeys/commands/StoryCommand.java @@ -27,10 +27,8 @@ import ch.vorburger.minecraft.storeys.model.parser.StoryParser; import ch.vorburger.minecraft.storeys.model.parser.StoryRepository; import ch.vorburger.minecraft.storeys.util.Command; -import com.google.common.collect.ImmutableList; import java.io.File; import java.nio.file.Path; -import java.util.List; import javax.inject.Inject; import net.kyori.adventure.text.Component; import org.spongepowered.api.command.CommandResult; @@ -56,11 +54,11 @@ public class StoryCommand implements Command { this.storyPlayer = storyPlayer; } - @Override public List aliases() { - return ImmutableList.of("story"); + @Override public String getName() { + return "story"; } - @Override public org.spongepowered.api.command.Command callable() { + @Override public org.spongepowered.api.command.Command.Parameterized createCommand() { return org.spongepowered.api.command.Command.builder().shortDescription(Component.text("Tell a story")) // .permission("storeys.commands.story") ? .addParameter(STORY_NAME) // TODO requiringPermission() diff --git a/storeys/src/main/java/ch/vorburger/minecraft/storeys/events/ConditionService.java b/storeys/src/main/java/ch/vorburger/minecraft/storeys/events/ConditionService.java index 88f80d2c..104f0a38 100644 --- a/storeys/src/main/java/ch/vorburger/minecraft/storeys/events/ConditionService.java +++ b/storeys/src/main/java/ch/vorburger/minecraft/storeys/events/ConditionService.java @@ -39,6 +39,7 @@ import org.spongepowered.api.scheduler.ScheduledTask; import org.spongepowered.api.scheduler.Scheduler; import org.spongepowered.api.scheduler.Task; +import org.spongepowered.plugin.PluginContainer; @ThreadSafe @Singleton public class ConditionService implements AutoCloseable { @@ -90,8 +91,8 @@ private ConditionServiceRegistration(Triple private final Scheduler scheduler; private final UUID taskId; - @Inject public ConditionService(Scheduler scheduler) { - Task task = Task.builder().execute(this::run).interval(10, TimeUnit.SECONDS).build(); + @Inject public ConditionService(PluginContainer plugin, Scheduler scheduler) { + Task task = Task.builder().execute(this::run).interval(10, TimeUnit.SECONDS).plugin(plugin).build(); this.scheduler = scheduler; taskId = scheduler.submit(task).uniqueId(); } diff --git a/storeys/src/main/java/ch/vorburger/minecraft/storeys/model/LocationAction.java b/storeys/src/main/java/ch/vorburger/minecraft/storeys/model/LocationAction.java index 0109bbe0..c0a99990 100644 --- a/storeys/src/main/java/ch/vorburger/minecraft/storeys/model/LocationAction.java +++ b/storeys/src/main/java/ch/vorburger/minecraft/storeys/model/LocationAction.java @@ -37,8 +37,8 @@ public class LocationAction implements Action { public LocationAction() { } - @Inject public LocationAction(Scheduler scheduler) { - conditionService = new ConditionService(scheduler); + @Inject public LocationAction(ConditionService conditionService) { + this.conditionService = conditionService; } @Override public void setParameter(String param) { diff --git a/storeys/src/main/java/ch/vorburger/minecraft/storeys/plugin/AbstractStoreysPlugin.java b/storeys/src/main/java/ch/vorburger/minecraft/storeys/plugin/AbstractStoreysPlugin.java index f404d37d..c80f521c 100644 --- a/storeys/src/main/java/ch/vorburger/minecraft/storeys/plugin/AbstractStoreysPlugin.java +++ b/storeys/src/main/java/ch/vorburger/minecraft/storeys/plugin/AbstractStoreysPlugin.java @@ -27,41 +27,28 @@ import com.google.inject.Injector; import java.nio.file.Path; import javax.inject.Inject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.spongepowered.api.command.Command; import org.spongepowered.api.config.ConfigDir; import org.spongepowered.api.event.EventManager; -import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; -import org.spongepowered.api.event.lifecycle.StartingEngineEvent; // Do *NOT* annotate this class with @Plugin public abstract class AbstractStoreysPlugin extends AbstractPlugin { - private static final Logger LOG = LoggerFactory.getLogger(AbstractStoreysPlugin.class); - @Inject @ConfigDir(sharedRoot = false) private Path configDir; @Inject protected Injector pluginInjector; - private Injector childInjector; - @Inject private EventManager eventManager; @Inject private EventService eventService; - @Listener public final void onGameStartingServer(StartingEngineEvent event) throws Exception { - LOG.info("See https://github.com/OASIS-learn-study/minecraft-storeys-maker for how to use /story and /narrate commands"); - start(this, configDir); - } - - protected void start(PluginInstance plugin, Path configDir) throws Exception { + protected void start(PluginInstance plugin, Path configDir) { eventManager.registerListeners(plugin.getPluginContainer(), new GuardGameModeJoinListener()); eventService.setPluginContainer(plugin.getPluginContainer()); // TODO(vorburger) child injector might not actually be required, could possibly just use only pluginInjector? - childInjector = pluginInjector.createChildInjector(binder -> { + Injector childInjector = pluginInjector.createChildInjector(binder -> { binder.bind(PluginInstance.class).toInstance(plugin); binder.bind(Path.class).toInstance(configDir); binder.bind(Scripts.class); @@ -69,13 +56,11 @@ protected void start(PluginInstance plugin, Path configDir) throws Exception { }); } - @Listener public void register(RegisterCommandEvent event) { + public void register(RegisterCommandEvent event) { final StoryCommand storyCommand = pluginInjector.getInstance(StoryCommand.class); final NarrateCommand narrateCommand = pluginInjector.getInstance(NarrateCommand.class); - event.register(this.getPluginContainer(), (Command.Raw) narrateCommand.callable(), narrateCommand.aliases().get(0), - narrateCommand.aliases().toArray(new String[0])); - event.register(this.getPluginContainer(), (Command.Raw) storyCommand.callable(), storyCommand.aliases().get(0), - storyCommand.aliases().toArray(new String[0])); + event.register(this.getPluginContainer(), narrateCommand.createCommand(), narrateCommand.getName(), narrateCommand.aliases()); + event.register(this.getPluginContainer(), storyCommand.createCommand(), storyCommand.getName(), storyCommand.aliases()); } } diff --git a/storeys/src/main/java/ch/vorburger/minecraft/storeys/util/Command.java b/storeys/src/main/java/ch/vorburger/minecraft/storeys/util/Command.java index d71a288f..9e066752 100644 --- a/storeys/src/main/java/ch/vorburger/minecraft/storeys/util/Command.java +++ b/storeys/src/main/java/ch/vorburger/minecraft/storeys/util/Command.java @@ -23,7 +23,11 @@ public interface Command extends CommandExecutor { - org.spongepowered.api.command.Command callable(); + org.spongepowered.api.command.Command.Parameterized createCommand(); - List aliases(); + String getName(); + + default String[] aliases() { + return new String[0]; + } } diff --git a/web/src/main/java/ch/vorburger/minecraft/storeys/api/impl/TokenCommand.java b/web/src/main/java/ch/vorburger/minecraft/storeys/api/impl/TokenCommand.java index 4b74c2ce..957f4213 100644 --- a/web/src/main/java/ch/vorburger/minecraft/storeys/api/impl/TokenCommand.java +++ b/web/src/main/java/ch/vorburger/minecraft/storeys/api/impl/TokenCommand.java @@ -21,8 +21,6 @@ import ch.vorburger.minecraft.storeys.japi.util.CommandExceptions; import ch.vorburger.minecraft.storeys.simple.TokenProvider; import ch.vorburger.minecraft.storeys.util.Command; -import com.google.common.collect.ImmutableList; -import java.util.List; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.format.NamedTextColor; @@ -42,13 +40,13 @@ public TokenCommand(TokenProvider newTokenProvider) { this.tokenProvider = newTokenProvider; } - @Override public org.spongepowered.api.command.Command callable() { + @Override public org.spongepowered.api.command.Command.Parameterized createCommand() { return org.spongepowered.api.command.Command.builder().permission("storeys.token.new") .shortDescription(Component.text("Obtain API token for player")).executor(this).build(); } - @Override public List aliases() { - return ImmutableList.of("token"); + @Override public String getName() { + return "token"; } @Override public CommandResult execute(CommandContext args) throws CommandException { diff --git a/web/src/main/java/ch/vorburger/minecraft/storeys/web/LocationToolListener.java b/web/src/main/java/ch/vorburger/minecraft/storeys/web/LocationToolListener.java index 1fcb13ec..3adc79ca 100644 --- a/web/src/main/java/ch/vorburger/minecraft/storeys/web/LocationToolListener.java +++ b/web/src/main/java/ch/vorburger/minecraft/storeys/web/LocationToolListener.java @@ -45,12 +45,14 @@ import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.HandTypes; import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.EventContext; import org.spongepowered.api.event.EventContextKeys; import org.spongepowered.api.event.EventManager; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.block.InteractBlockEvent; +import org.spongepowered.api.event.filter.cause.First; import org.spongepowered.api.event.lifecycle.StoppedGameEvent; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackSnapshot; @@ -93,7 +95,7 @@ } } - @Listener public void locationToolInteraction(InteractBlockEvent event, Player player) { + @Listener public void locationToolInteraction(InteractBlockEvent.Primary event, @First ServerPlayer player) { final Optional snapshot = event.context().get(EventContextKeys.USED_ITEM); snapshot.ifPresent(itemStackSnapshot -> { final ItemStack itemStack = player.itemInHand(HandTypes.MAIN_HAND); diff --git a/web/src/main/java/ch/vorburger/minecraft/storeys/web/LoginCommand.java b/web/src/main/java/ch/vorburger/minecraft/storeys/web/LoginCommand.java index d4796ba6..f50e572d 100644 --- a/web/src/main/java/ch/vorburger/minecraft/storeys/web/LoginCommand.java +++ b/web/src/main/java/ch/vorburger/minecraft/storeys/web/LoginCommand.java @@ -21,13 +21,10 @@ import ch.vorburger.minecraft.storeys.japi.util.CommandExceptions; import ch.vorburger.minecraft.storeys.simple.TokenProvider; import ch.vorburger.minecraft.storeys.util.Command; -import com.google.common.collect.ImmutableList; import java.net.URL; -import java.util.List; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.format.NamedTextColor; -import org.spongepowered.api.command.Command.Parameterized; import org.spongepowered.api.command.CommandResult; import org.spongepowered.api.command.exception.CommandException; import org.spongepowered.api.command.parameter.CommandContext; @@ -59,13 +56,17 @@ private String getSystemPropertyEnvVarOrDefault(String propertyName, String defa return defaultValue; } - @Override public org.spongepowered.api.command.Command callable() { + @Override public org.spongepowered.api.command.Command.Parameterized createCommand() { return org.spongepowered.api.command.Command.builder().shortDescription(Component.text("Open the browser and start your story")) .executor(this).build(); } - @Override public List aliases() { - return ImmutableList.of("make", "scratch"); + @Override public String getName() { + return "make"; + } + + @Override public String[] aliases() { + return new String[] { "scratch" }; } @Override public CommandResult execute(CommandContext args) throws CommandException { @@ -81,6 +82,7 @@ private String getSystemPropertyEnvVarOrDefault(String propertyName, String defa Component.text("Click here to open a browser and start MAKE actions").clickEvent(ClickEvent.openUrl(new URL(url))) .color(NamedTextColor.GOLD)); }); + return CommandResult.success(); } return CommandResult.error(Component.text("Command source must be Player").color(NamedTextColor.RED)); } diff --git a/web/src/main/java/ch/vorburger/minecraft/storeys/web/StoreysWebPlugin.java b/web/src/main/java/ch/vorburger/minecraft/storeys/web/StoreysWebPlugin.java index 277deb2b..276fb439 100644 --- a/web/src/main/java/ch/vorburger/minecraft/storeys/web/StoreysWebPlugin.java +++ b/web/src/main/java/ch/vorburger/minecraft/storeys/web/StoreysWebPlugin.java @@ -27,14 +27,20 @@ import com.google.inject.TypeLiteral; import com.google.inject.name.Names; import java.nio.file.Path; +import java.util.Optional; import java.util.concurrent.ExecutionException; import javax.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.spongepowered.api.Server; +import org.spongepowered.api.Sponge; import org.spongepowered.api.command.Command; +import org.spongepowered.api.command.registrar.CommandRegistrar; +import org.spongepowered.api.config.ConfigDir; import org.spongepowered.api.config.DefaultConfig; import org.spongepowered.api.event.Listener; -import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; +import org.spongepowered.api.event.lifecycle.StartingEngineEvent; +import org.spongepowered.api.scheduler.Scheduler; import org.spongepowered.configurate.CommentedConfigurationNode; import org.spongepowered.configurate.loader.ConfigurationLoader; import org.spongepowered.plugin.builtin.jvm.Plugin; @@ -43,13 +49,17 @@ // do not extend StoreysPlugin, because we exclude that class in shadowJar private static final Logger LOG = LoggerFactory.getLogger(StoreysWebPlugin.class); - private VertxStarter vertxStarter; - private LoginCommand loginCommand; - private TokenCommand tokenCommand; + @Inject @ConfigDir(sharedRoot = false) private Path configDir; @Inject @DefaultConfig(sharedRoot = true) private ConfigurationLoader configurationLoader; - @Override public void start(PluginInstance plugin, Path configDir) throws Exception { + @Listener public final void onGameStartingServer(StartingEngineEvent event) throws Exception { + LOG.info("See https://github.com/OASIS-learn-study/minecraft-storeys-maker for how to use /story and /narrate commands"); + start(this, configDir); + } + + @Override public void start(PluginInstance plugin, Path configDir) { + LOG.info("See https://github.com/OASIS-learn-study/minecraft-storeys-maker for how to use /story and /narrate commands"); super.start(plugin, configDir); Injector injector = pluginInjector.createChildInjector(binder -> { @@ -60,16 +70,21 @@ binder.bind(new TypeLiteral>() { }).toInstance(configurationLoader); binder.bind(LocationToolListener.class); + binder.bind(Scheduler.class).toInstance(Sponge.asyncScheduler()); }); StaticWebServerVerticle staticWebServerVerticle = injector.getInstance(StaticWebServerVerticle.class); TokenProvider tokenProvider = injector.getInstance(TokenProvider.class); - loginCommand = new LoginCommand(tokenProvider); - tokenCommand = new TokenCommand(tokenProvider); + LoginCommand loginCommand = new LoginCommand(tokenProvider); + TokenCommand tokenCommand = new TokenCommand(tokenProvider); + final Optional> registrar = Sponge.server().commandManager().registrar(Command.Parameterized.class); + final CommandRegistrar commandRegistrar = registrar.get(); + commandRegistrar.register(plugin.getPluginContainer(), loginCommand.createCommand(), loginCommand.getName(), loginCommand.aliases()); + commandRegistrar.register(plugin.getPluginContainer(), tokenCommand.createCommand(), tokenCommand.getName(), tokenCommand.aliases()); try { try { - vertxStarter = new VertxStarter(); + VertxStarter vertxStarter = new VertxStarter(); vertxStarter.deployVerticle(staticWebServerVerticle).toCompletableFuture().get(); } catch (ExecutionException | InterruptedException e) { @@ -82,9 +97,4 @@ throw e; } } - - @Listener public void register(RegisterCommandEvent event) { - event.register(this.getPluginContainer(), - (Command.Raw) loginCommand.callable(), loginCommand.aliases().get(0), loginCommand.aliases().toArray(new String[0])); - } }