Skip to content

Commit

Permalink
Add datapack registration lifecycle event
Browse files Browse the repository at this point in the history
  • Loading branch information
Machine-Maker committed Jun 16, 2024
1 parent d9111cc commit 3d5b270
Show file tree
Hide file tree
Showing 5 changed files with 482 additions and 0 deletions.
211 changes: 211 additions & 0 deletions patches/api/0477-Add-datapack-registration-lifecycle-event.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 12 May 2024 17:30:54 -0700
Subject: [PATCH] Add datapack registration lifecycle event


diff --git a/src/main/java/io/papermc/paper/datapack/Datapack.java b/src/main/java/io/papermc/paper/datapack/Datapack.java
index 7b2ab0be10a21e0496ad1d485ff8cb2c0b92a2cb..e6037cc5b79b5206e5da8d53c5009932e7c81c86 100644
--- a/src/main/java/io/papermc/paper/datapack/Datapack.java
+++ b/src/main/java/io/papermc/paper/datapack/Datapack.java
@@ -29,4 +29,10 @@ public interface Datapack {
COMPATIBLE,
}

+ /**
+ * Position of the pack in the load order.
+ */
+ enum Position {
+ TOP, BOTTOM
+ }
}
diff --git a/src/main/java/io/papermc/paper/datapack/DatapackRegistrar.java b/src/main/java/io/papermc/paper/datapack/DatapackRegistrar.java
new file mode 100644
index 0000000000000000000000000000000000000000..099383a3649f53cd17b01769f562fae878c73579
--- /dev/null
+++ b/src/main/java/io/papermc/paper/datapack/DatapackRegistrar.java
@@ -0,0 +1,153 @@
+package io.papermc.paper.datapack;
+
+import io.papermc.paper.plugin.configuration.PluginMeta;
+import io.papermc.paper.plugin.lifecycle.event.registrar.Registrar;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Path;
+import java.util.function.Consumer;
+import net.kyori.adventure.text.Component;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Contract;
+
+/**
+ * The registrar for datapacks. The event for this registrar
+ * is called anytime the game tries to discover datapacks at any of the
+ * configured locations. This means that if a datapack should stay available to the server,
+ * it must always be discovered whenever this event fires.
+ * <p>An example of a plugin loading a datapack from within it's own jar is below</p>
+ * <pre>{@code
+ * public class YourPluginBootstrap implements PluginBootstrap {
+ * @Override
+ * public void bootstrap(BoostrapContext context) {
+ * final LifecycleEventManager<BootstrapContext> manager = context.getLifecycleManager();
+ * manager.registerEventHandler(LifecycleEvents.DATAPACK_DISCOVERY, event -> {
+ * DatapackRegistrar registrar = event.registrar();
+ * try {
+ * final URI uri = Objects.requireNonNull(
+ * YourPluginBootstrap.class.getResource("/pack")
+ * ).toURI();
+ * registrar.discoverPack(uri, "packId");
+ * } catch (final URISyntaxException | IOException e) {
+ * throw new RuntimeException(e);
+ * }
+ * });
+ * }
+ * }
+ * }</pre>
+ * @see io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents#DATAPACK_DISCOVERY
+ */
+@ApiStatus.NonExtendable
+@ApiStatus.Experimental
+public interface DatapackRegistrar extends Registrar {
+
+ /**
+ * Discovers a datapack at the specified {@link URI} with the id.
+ * <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
+ *
+ * @param uri the location of the pack
+ * @param id a unique id
+ * @throws IOException if any IO error occurs
+ */
+ default void discoverPack(final @NonNull URI uri, final @NonNull String id) throws IOException {
+ this.discoverPack(uri, id, c -> {});
+ }
+
+ /**
+ * Discovers a datapack at the specified {@link URI} with the id.
+ * <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
+ *
+ * @param uri the location of the pack
+ * @param id a unique id
+ * @param configurer a configurer for extra options
+ * @throws IOException if any IO error occurs
+ */
+ void discoverPack(@NonNull URI uri, @NonNull String id, @NonNull Consumer<Configurer> configurer) throws IOException;
+
+ /**
+ * Discovers a datapack at the specified {@link Path} with the id.
+ * <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
+ *
+ * @param path the location of the pack
+ * @param id a unique id
+ * @throws IOException if any IO error occurs
+ */
+ default void discoverPack(final @NonNull Path path, final @NonNull String id) throws IOException {
+ this.discoverPack(path, id, c -> {});
+ }
+
+ /**
+ * Discovers a datapack at the specified {@link Path} with the id.
+ * <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
+ *
+ * @param path the location of the pack
+ * @param id a unique id
+ * @param configurer a configurer for extra options
+ * @throws IOException if any IO error occurs
+ */
+ void discoverPack(@NonNull Path path, @NonNull String id, @NonNull Consumer<Configurer> configurer) throws IOException;
+
+ /**
+ * Discovers a datapack at the specified {@link URI} with the id.
+ * <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
+ *
+ * @param pluginMeta the plugin which will be the "owner" of this datapack
+ * @param uri the location of the pack
+ * @param id a unique id
+ * @param configurer a configurer for extra options
+ * @throws IOException if any IO error occurs
+ */
+ void discoverPack(@NonNull PluginMeta pluginMeta, @NonNull URI uri, @NonNull String id, @NonNull Consumer<Configurer> configurer) throws IOException;
+
+ /**
+ * Discovers a datapack at the specified {@link Path} with the id.
+ * <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
+ *
+ * @param pluginMeta the plugin which will be the "owner" of this datapack
+ * @param path the location of the pack
+ * @param id a unique id
+ * @param configurer a configurer for extra options
+ * @throws IOException if any IO error occurs
+ */
+ void discoverPack(@NonNull PluginMeta pluginMeta, @NonNull Path path, @NonNull String id, @NonNull Consumer<Configurer> configurer) throws IOException;
+
+ /**
+ * Configures additional, optional, details about a datapack.
+ */
+ @ApiStatus.NonExtendable
+ @ApiStatus.Experimental
+ interface Configurer {
+
+ /**
+ * Changes the title of the datapack from the default which
+ * is just the "id" in the {@code registerPack} methods.
+ *
+ * @param title the new title
+ * @return the configurer for chaining
+ */
+ @Contract(value = "_ -> this", mutates = "this")
+ @NonNull Configurer title(@NonNull Component title);
+
+ /**
+ * Sets if this pack is required. Defaults to false.
+ * A required pack cannot be disabled.
+ *
+ * @param required true to require the pack
+ * @return the configurer for chaining
+ */
+ @Contract(value = "_ -> this", mutates = "this")
+ @NonNull Configurer required(boolean required);
+
+ /**
+ * Configures the position in the
+ * load order of this datapack.
+ *
+ * @param fixed won't move around in the load order as packs are added/removed
+ * @param position try to insert at the top of the order or bottom
+ * @return the configurer for chaining
+ */
+ @Contract(value = "_, _ -> this", mutates = "this")
+ @NonNull Configurer position(boolean fixed, Datapack.@NonNull Position position);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
index 1fab48593c567fe05b085ac6e12dc22556cf0b92..dcff07f8fe1627662726611602bd0f8213e39133 100644
--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java
@@ -1,10 +1,12 @@
package io.papermc.paper.plugin.lifecycle.event.types;

import io.papermc.paper.command.brigadier.Commands;
+import io.papermc.paper.datapack.DatapackRegistrar;
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
+import io.papermc.paper.plugin.lifecycle.event.registrar.RegistrarEvent;
import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.ApiStatus;
@@ -24,6 +26,13 @@ public final class LifecycleEvents {
*/
public static final LifecycleEventType.Prioritizable<LifecycleEventOwner, ReloadableRegistrarEvent<Commands>> COMMANDS = prioritized("commands", LifecycleEventOwner.class);

+ /**
+ * This event is for informing the server about any available datapacks from other sources such as inside a plugin's jar. You
+ * can register a handler for this event only in {@link io.papermc.paper.plugin.bootstrap.PluginBootstrap#bootstrap(BootstrapContext)}.
+ * @see DatapackRegistrar an example of a datapack being discovered
+ */
+ public static final LifecycleEventType.Prioritizable<BootstrapContext, RegistrarEvent<DatapackRegistrar>> DATAPACK_DISCOVERY = prioritized("datapack_discovery", BootstrapContext.class);
+
//<editor-fold desc="helper methods" defaultstate="collapsed">
@ApiStatus.Internal
private static <E extends LifecycleEvent> LifecycleEventType.Monitorable<Plugin, E> plugin(final String name) {
Loading

0 comments on commit 3d5b270

Please sign in to comment.