mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-18 04:39:24 +01:00
Add datapack registration lifecycle event
This commit is contained in:
parent
acdd6d35ad
commit
bf66c7c548
8 changed files with 1057 additions and 0 deletions
277
patches/api/0490-Add-datapack-registration-lifecycle-event.patch
Normal file
277
patches/api/0490-Add-datapack-registration-lifecycle-event.patch
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
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 233a31afa9673c9cb8d9eb52551425ff15f79661..436606dd81ff666d8378c41f45bbb6a674a477dd 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/datapack/Datapack.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/datapack/Datapack.java
|
||||||
|
@@ -95,4 +95,11 @@ public interface Datapack {
|
||||||
|
TOO_NEW,
|
||||||
|
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..456c26c9295a19743fdb8ea6d42ff672836a9e7b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/datapack/DatapackRegistrar.java
|
||||||
|
@@ -0,0 +1,204 @@
|
||||||
|
+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.Map;
|
||||||
|
+import java.util.function.Consumer;
|
||||||
|
+import net.kyori.adventure.text.Component;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
+import org.jetbrains.annotations.ApiStatus;
|
||||||
|
+import org.jetbrains.annotations.Contract;
|
||||||
|
+import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * 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 {
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Checks if a datapack with the specified name has been discovered.
|
||||||
|
+ *
|
||||||
|
+ * @param name the name of the pack
|
||||||
|
+ * @return true if the pack has been discovered
|
||||||
|
+ * @see Datapack#getName()
|
||||||
|
+ */
|
||||||
|
+ @Contract(pure = true)
|
||||||
|
+ boolean hasPackDiscovered(@NonNull String name);
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Gets a discovered datapack by its name.
|
||||||
|
+ *
|
||||||
|
+ * @param name the name of the pack
|
||||||
|
+ * @return the datapack
|
||||||
|
+ * @throws java.util.NoSuchElementException if the pack is not discovered
|
||||||
|
+ * @see Datapack#getName()
|
||||||
|
+ */
|
||||||
|
+ @Contract(pure = true)
|
||||||
|
+ @NonNull DiscoveredDatapack getDiscoveredPack(@NonNull String name);
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Removes a discovered datapack by its name.
|
||||||
|
+ *
|
||||||
|
+ * @param name the name of the pack
|
||||||
|
+ * @return true if the pack was removed
|
||||||
|
+ * @see Datapack#getName()
|
||||||
|
+ */
|
||||||
|
+ @Contract(mutates = "this")
|
||||||
|
+ boolean removeDiscoveredPack(@NonNull String name);
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Gets all discovered datapacks.
|
||||||
|
+ *
|
||||||
|
+ * @return an unmodifiable map of discovered packs
|
||||||
|
+ */
|
||||||
|
+ @Contract(pure = true)
|
||||||
|
+ @Unmodifiable @NonNull Map<String, DiscoveredDatapack> getDiscoveredPacks();
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * 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 (will be combined with plugin for the datapacks name)
|
||||||
|
+ * @return the discovered datapack (or null if it failed)
|
||||||
|
+ * @throws IOException if any IO error occurs
|
||||||
|
+ */
|
||||||
|
+ default @Nullable DiscoveredDatapack discoverPack(final @NonNull URI uri, final @NonNull String id) throws IOException {
|
||||||
|
+ return 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 (will be combined with plugin for the datapacks name)
|
||||||
|
+ * @param configurer a configurer for extra options
|
||||||
|
+ * @return the discovered datapack (or null if it failed)
|
||||||
|
+ * @throws IOException if any IO error occurs
|
||||||
|
+ */
|
||||||
|
+ @Nullable DiscoveredDatapack 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 (will be combined with plugin for the datapacks name)
|
||||||
|
+ * @return the discovered datapack (or null if it failed)
|
||||||
|
+ * @throws IOException if any IO error occurs
|
||||||
|
+ */
|
||||||
|
+ default @Nullable DiscoveredDatapack discoverPack(final @NonNull Path path, final @NonNull String id) throws IOException {
|
||||||
|
+ return 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 (will be combined with plugin for the datapacks name)
|
||||||
|
+ * @param configurer a configurer for extra options
|
||||||
|
+ * @return the discovered datapack (or null if it failed)
|
||||||
|
+ * @throws IOException if any IO error occurs
|
||||||
|
+ */
|
||||||
|
+ @Nullable DiscoveredDatapack 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 (will be combined with plugin for the datapacks name)
|
||||||
|
+ * @param configurer a configurer for extra options
|
||||||
|
+ * @return the discovered datapack (or null if it failed)
|
||||||
|
+ * @throws IOException if any IO error occurs
|
||||||
|
+ */
|
||||||
|
+ @Nullable DiscoveredDatapack 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 (will be combined with plugin for the datapacks name)
|
||||||
|
+ * @param configurer a configurer for extra options
|
||||||
|
+ * @return the discovered datapack (or null if it failed)
|
||||||
|
+ * @throws IOException if any IO error occurs
|
||||||
|
+ */
|
||||||
|
+ @Nullable DiscoveredDatapack 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 once enabled. Marking
|
||||||
|
+ * a pack as required <b>does not</b> mean it will immediately be enabled
|
||||||
|
+ * upon discovery. It may be enabled if this event was fired
|
||||||
|
+ * due to a pending (re)load.
|
||||||
|
+ *
|
||||||
|
+ * @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/datapack/DiscoveredDatapack.java b/src/main/java/io/papermc/paper/datapack/DiscoveredDatapack.java
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000000000000000000000000000..f0ec90fd08e984995fd3fe48ae3219ce08e2d40a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/datapack/DiscoveredDatapack.java
|
||||||
|
@@ -0,0 +1,8 @@
|
||||||
|
+package io.papermc.paper.datapack;
|
||||||
|
+
|
||||||
|
+public interface DiscoveredDatapack {
|
||||||
|
+
|
||||||
|
+ String getName();
|
||||||
|
+
|
||||||
|
+ Datapack.Compatibility getCompatibility();
|
||||||
|
+}
|
||||||
|
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 720fe2546015838708ce794c291ca187cf7bca9c..6dce88760b954bc898bdc05a64081b1dd1737c3c 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;
|
||||||
|
@@ -30,6 +32,13 @@ public final class LifecycleEvents {
|
||||||
|
*/
|
||||||
|
public static final TagEventTypeProvider TAGS = LifecycleEventTypeProvider.provider().tagProvider();
|
||||||
|
|
||||||
|
+ /**
|
||||||
|
+ * 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 = bootstrapPrioritized("datapack_discovery");
|
||||||
|
+
|
||||||
|
//<editor-fold desc="helper methods" defaultstate="collapsed">
|
||||||
|
@ApiStatus.Internal
|
||||||
|
static <E extends LifecycleEvent> LifecycleEventType.Monitorable<Plugin, E> plugin(final String name) {
|
162
patches/api/0491-move-methods-to-DiscoveredDatapack.patch
Normal file
162
patches/api/0491-move-methods-to-DiscoveredDatapack.patch
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||||
|
Date: Mon, 23 Sep 2024 16:04:31 -0700
|
||||||
|
Subject: [PATCH] move methods to DiscoveredDatapack
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/datapack/Datapack.java b/src/main/java/io/papermc/paper/datapack/Datapack.java
|
||||||
|
index 436606dd81ff666d8378c41f45bbb6a674a477dd..073eaecc77c372c9d73a11a1e374be181d2de353 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/datapack/Datapack.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/datapack/Datapack.java
|
||||||
|
@@ -1,60 +1,16 @@
|
||||||
|
package io.papermc.paper.datapack;
|
||||||
|
|
||||||
|
-import java.util.Set;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
-import org.bukkit.FeatureFlag;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
-import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a snapshot of a datapack on the server. It
|
||||||
|
* won't be updated as datapacks are updated.
|
||||||
|
*/
|
||||||
|
-public interface Datapack {
|
||||||
|
-
|
||||||
|
- /**
|
||||||
|
- * Gets the name/id of this datapack.
|
||||||
|
- *
|
||||||
|
- * @return the name of the pack
|
||||||
|
- */
|
||||||
|
- @Contract(pure = true)
|
||||||
|
- @NonNull String getName();
|
||||||
|
-
|
||||||
|
- /**
|
||||||
|
- * Gets the title component of this datapack.
|
||||||
|
- *
|
||||||
|
- * @return the title
|
||||||
|
- */
|
||||||
|
- @NonNull Component getTitle();
|
||||||
|
-
|
||||||
|
- /**
|
||||||
|
- * Gets the description component of this datapack.
|
||||||
|
- *
|
||||||
|
- * @return the description
|
||||||
|
- */
|
||||||
|
- @NonNull Component getDescription();
|
||||||
|
-
|
||||||
|
- /**
|
||||||
|
- * Gets if this datapack is required to be enabled.
|
||||||
|
- *
|
||||||
|
- * @return true if the pack is required
|
||||||
|
- */
|
||||||
|
- boolean isRequired();
|
||||||
|
-
|
||||||
|
- /**
|
||||||
|
- * Gets the compatibility status of this pack.
|
||||||
|
- *
|
||||||
|
- * @return the compatibility of the pack
|
||||||
|
- */
|
||||||
|
- @NonNull Compatibility getCompatibility();
|
||||||
|
-
|
||||||
|
- /**
|
||||||
|
- * Gets the set of required features for this datapack.
|
||||||
|
- *
|
||||||
|
- * @return the set of required features
|
||||||
|
- */
|
||||||
|
- @NonNull @Unmodifiable Set<FeatureFlag> getRequiredFeatures();
|
||||||
|
+@ApiStatus.NonExtendable
|
||||||
|
+public interface Datapack extends DiscoveredDatapack {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the enabled state of this pack.
|
||||||
|
@@ -73,13 +29,6 @@ public interface Datapack {
|
||||||
|
*/
|
||||||
|
void setEnabled(boolean enabled);
|
||||||
|
|
||||||
|
- /**
|
||||||
|
- * Gets the source for this datapack.
|
||||||
|
- *
|
||||||
|
- * @return the pack source
|
||||||
|
- */
|
||||||
|
- @NonNull DatapackSource getSource();
|
||||||
|
-
|
||||||
|
/**
|
||||||
|
* Computes the component vanilla Minecraft uses
|
||||||
|
* to display this datapack. Includes the {@link #getSource()},
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/datapack/DiscoveredDatapack.java b/src/main/java/io/papermc/paper/datapack/DiscoveredDatapack.java
|
||||||
|
index f0ec90fd08e984995fd3fe48ae3219ce08e2d40a..8e1da7c41d7060a089c8b8c90f00e3bb47440bda 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/datapack/DiscoveredDatapack.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/datapack/DiscoveredDatapack.java
|
||||||
|
@@ -1,8 +1,67 @@
|
||||||
|
package io.papermc.paper.datapack;
|
||||||
|
|
||||||
|
+import java.util.Set;
|
||||||
|
+import net.kyori.adventure.text.Component;
|
||||||
|
+import org.bukkit.FeatureFlag;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.jetbrains.annotations.ApiStatus;
|
||||||
|
+import org.jetbrains.annotations.Contract;
|
||||||
|
+import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * This is a snapshot of a discovered datapack on the server. It
|
||||||
|
+ * won't be updated as datapacks are updated.
|
||||||
|
+ */
|
||||||
|
+@ApiStatus.NonExtendable
|
||||||
|
public interface DiscoveredDatapack {
|
||||||
|
|
||||||
|
- String getName();
|
||||||
|
+ /**
|
||||||
|
+ * Gets the name/id of this datapack.
|
||||||
|
+ *
|
||||||
|
+ * @return the name of the pack
|
||||||
|
+ */
|
||||||
|
+ @Contract(pure = true)
|
||||||
|
+ @NonNull String getName();
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Gets the title component of this datapack.
|
||||||
|
+ *
|
||||||
|
+ * @return the title
|
||||||
|
+ */
|
||||||
|
+ @NonNull Component getTitle();
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Gets the description component of this datapack.
|
||||||
|
+ *
|
||||||
|
+ * @return the description
|
||||||
|
+ */
|
||||||
|
+ @NonNull Component getDescription();
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Gets if this datapack is required to be enabled.
|
||||||
|
+ *
|
||||||
|
+ * @return true if the pack is required
|
||||||
|
+ */
|
||||||
|
+ boolean isRequired();
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Gets the compatibility status of this pack.
|
||||||
|
+ *
|
||||||
|
+ * @return the compatibility of the pack
|
||||||
|
+ */
|
||||||
|
+ Datapack.@NonNull Compatibility getCompatibility();
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Gets the set of required features for this datapack.
|
||||||
|
+ *
|
||||||
|
+ * @return the set of required features
|
||||||
|
+ */
|
||||||
|
+ @NonNull @Unmodifiable Set<FeatureFlag> getRequiredFeatures();
|
||||||
|
|
||||||
|
- Datapack.Compatibility getCompatibility();
|
||||||
|
+ /**
|
||||||
|
+ * Gets the source for this datapack.
|
||||||
|
+ *
|
||||||
|
+ * @return the pack source
|
||||||
|
+ */
|
||||||
|
+ @NonNull DatapackSource getSource();
|
||||||
|
}
|
|
@ -0,0 +1,394 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||||
|
Date: Sun, 12 May 2024 17:30:50 -0700
|
||||||
|
Subject: [PATCH] Add datapack registration lifecycle event
|
||||||
|
|
||||||
|
== AT ==
|
||||||
|
public net/minecraft/server/packs/repository/FolderRepositorySource$FolderPackDetector
|
||||||
|
public net/minecraft/server/packs/repository/FolderRepositorySource$FolderPackDetector <init>(Lnet/minecraft/world/level/validation/DirectoryValidator;)V
|
||||||
|
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapackRegistrar.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackRegistrar.java
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000000000000000000000000000..aa5c7dfddea67db036c066d5151821248b945550
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackRegistrar.java
|
||||||
|
@@ -0,0 +1,166 @@
|
||||||
|
+package io.papermc.paper.datapack;
|
||||||
|
+
|
||||||
|
+import com.google.common.base.Preconditions;
|
||||||
|
+import com.google.common.collect.ImmutableMap;
|
||||||
|
+import com.mojang.logging.LogUtils;
|
||||||
|
+import io.papermc.paper.adventure.PaperAdventure;
|
||||||
|
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||||
|
+import io.papermc.paper.plugin.configuration.PluginMeta;
|
||||||
|
+import io.papermc.paper.plugin.lifecycle.event.registrar.PaperRegistrar;
|
||||||
|
+import java.io.IOException;
|
||||||
|
+import java.net.URI;
|
||||||
|
+import java.nio.file.Path;
|
||||||
|
+import java.util.ArrayList;
|
||||||
|
+import java.util.List;
|
||||||
|
+import java.util.Map;
|
||||||
|
+import java.util.NoSuchElementException;
|
||||||
|
+import java.util.Optional;
|
||||||
|
+import java.util.function.Consumer;
|
||||||
|
+import net.kyori.adventure.text.Component;
|
||||||
|
+import net.minecraft.server.packs.PackLocationInfo;
|
||||||
|
+import net.minecraft.server.packs.PackSelectionConfig;
|
||||||
|
+import net.minecraft.server.packs.PackType;
|
||||||
|
+import net.minecraft.server.packs.VanillaPackResourcesBuilder;
|
||||||
|
+import net.minecraft.server.packs.repository.FolderRepositorySource;
|
||||||
|
+import net.minecraft.server.packs.repository.Pack;
|
||||||
|
+import net.minecraft.server.packs.repository.PackDetector;
|
||||||
|
+import net.minecraft.world.level.validation.ContentValidationException;
|
||||||
|
+import net.minecraft.world.level.validation.DirectoryValidator;
|
||||||
|
+import net.minecraft.world.level.validation.ForbiddenSymlinkInfo;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
+import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
+import org.slf4j.Logger;
|
||||||
|
+
|
||||||
|
+@DefaultQualifier(NonNull.class)
|
||||||
|
+public class PaperDatapackRegistrar implements PaperRegistrar<BootstrapContext>, DatapackRegistrar {
|
||||||
|
+
|
||||||
|
+ private static final Logger LOGGER = LogUtils.getClassLogger();
|
||||||
|
+
|
||||||
|
+ private final PackDetector<Pack.ResourcesSupplier> detector;
|
||||||
|
+ public final Map<String, Pack> discoveredPacks;
|
||||||
|
+ private @Nullable BootstrapContext owner;
|
||||||
|
+
|
||||||
|
+ public PaperDatapackRegistrar(final DirectoryValidator symlinkValidator, final Map<String, Pack> discoveredPacks) {
|
||||||
|
+ this.detector = new FolderRepositorySource.FolderPackDetector(symlinkValidator);
|
||||||
|
+ this.discoveredPacks = discoveredPacks;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void setCurrentContext(final @Nullable BootstrapContext owner) {
|
||||||
|
+ this.owner = owner;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean hasPackDiscovered(final String name) {
|
||||||
|
+ return this.discoveredPacks.containsKey(name);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @NonNull DiscoveredDatapack getDiscoveredPack(final String name) {
|
||||||
|
+ if (!this.hasPackDiscovered(name)) {
|
||||||
|
+ throw new NoSuchElementException("No pack with id " + name + " was discovered");
|
||||||
|
+ }
|
||||||
|
+ return new PaperDiscoveredDatapack(this.discoveredPacks.get(name));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean removeDiscoveredPack(final String name) {
|
||||||
|
+ return this.discoveredPacks.remove(name) != null;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @Unmodifiable Map<String, DiscoveredDatapack> getDiscoveredPacks() {
|
||||||
|
+ final ImmutableMap.Builder<String, DiscoveredDatapack> builder = ImmutableMap.builderWithExpectedSize(this.discoveredPacks.size());
|
||||||
|
+ for (final Map.Entry<String, Pack> entry : this.discoveredPacks.entrySet()) {
|
||||||
|
+ builder.put(entry.getKey(), new PaperDiscoveredDatapack(entry.getValue()));
|
||||||
|
+ }
|
||||||
|
+ return builder.build();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @Nullable DiscoveredDatapack discoverPack(final URI uri, final String id, final Consumer<Configurer> configurer) throws IOException {
|
||||||
|
+ Preconditions.checkState(this.owner != null, "Cannot register a datapack without specifying a PluginMeta yet");
|
||||||
|
+ return this.discoverPack(this.owner.getPluginMeta(), uri, id, configurer);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @Nullable DiscoveredDatapack discoverPack(final Path path, final String id, final Consumer<Configurer> configurer) throws IOException {
|
||||||
|
+ Preconditions.checkState(this.owner != null, "Cannot register a datapack without specifying a PluginMeta yet");
|
||||||
|
+ return this.discoverPack(this.owner.getPluginMeta(), path, id, configurer);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @Nullable DiscoveredDatapack discoverPack(final PluginMeta pluginMeta, final URI uri, final String id, final Consumer<Configurer> configurer) throws IOException {
|
||||||
|
+ return this.discoverPack(pluginMeta, VanillaPackResourcesBuilder.safeGetPath(uri), id, configurer);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @Nullable DiscoveredDatapack discoverPack(final PluginMeta pluginMeta, final Path path, final String id, final Consumer<Configurer> configurer) throws IOException {
|
||||||
|
+ final List<ForbiddenSymlinkInfo> badLinks = new ArrayList<>();
|
||||||
|
+ final Pack.@Nullable ResourcesSupplier resourcesSupplier = this.detector.detectPackResources(path, badLinks);
|
||||||
|
+ if (!badLinks.isEmpty()) {
|
||||||
|
+ LOGGER.warn("Ignoring potential pack entry: {}", ContentValidationException.getMessage(path, badLinks));
|
||||||
|
+ } else if (resourcesSupplier != null) {
|
||||||
|
+ final String packId = pluginMeta.getName() + "/" + id;
|
||||||
|
+ final ConfigurerImpl configurerImpl = new ConfigurerImpl(Component.text(packId));
|
||||||
|
+ configurer.accept(configurerImpl);
|
||||||
|
+ final PackLocationInfo locInfo = new PackLocationInfo(packId,
|
||||||
|
+ PaperAdventure.asVanilla(configurerImpl.title),
|
||||||
|
+ PluginPackSource.INSTANCE,
|
||||||
|
+ Optional.empty()
|
||||||
|
+ );
|
||||||
|
+ final @Nullable Pack pack = Pack.readMetaAndCreate(locInfo,
|
||||||
|
+ resourcesSupplier,
|
||||||
|
+ PackType.SERVER_DATA,
|
||||||
|
+ new PackSelectionConfig(
|
||||||
|
+ configurerImpl.required,
|
||||||
|
+ configurerImpl.position,
|
||||||
|
+ configurerImpl.fixedPosition
|
||||||
|
+ ));
|
||||||
|
+ if (pack != null) {
|
||||||
|
+ this.discoveredPacks.put(packId, pack);
|
||||||
|
+ return new PaperDiscoveredDatapack(pack);
|
||||||
|
+ }
|
||||||
|
+ return null;
|
||||||
|
+ } else {
|
||||||
|
+ LOGGER.info("Found non-pack entry '{}', ignoring", path);
|
||||||
|
+ }
|
||||||
|
+ return null;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ static final class ConfigurerImpl implements Configurer {
|
||||||
|
+
|
||||||
|
+ private Component title;
|
||||||
|
+ private boolean required = false;
|
||||||
|
+ private boolean fixedPosition = false;
|
||||||
|
+ private Pack.Position position = Pack.Position.TOP;
|
||||||
|
+
|
||||||
|
+ ConfigurerImpl(final Component title) {
|
||||||
|
+ this.title = title;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Configurer title(final Component title) {
|
||||||
|
+ this.title = title;
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Configurer required(final boolean required) {
|
||||||
|
+ this.required = required;
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Configurer position(final boolean fixed, final Datapack.Position position) {
|
||||||
|
+ this.fixedPosition = fixed;
|
||||||
|
+ this.position = switch (position) {
|
||||||
|
+ case TOP -> Pack.Position.TOP;
|
||||||
|
+ case BOTTOM -> Pack.Position.BOTTOM;
|
||||||
|
+ };
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/datapack/PaperDiscoveredDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDiscoveredDatapack.java
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000000000000000000000000000..572a62ceafcd066adfc0c2588cc43a0b61cedb7f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/datapack/PaperDiscoveredDatapack.java
|
||||||
|
@@ -0,0 +1,46 @@
|
||||||
|
+package io.papermc.paper.datapack;
|
||||||
|
+
|
||||||
|
+import java.util.Objects;
|
||||||
|
+import net.minecraft.server.packs.repository.Pack;
|
||||||
|
+
|
||||||
|
+public class PaperDiscoveredDatapack implements DiscoveredDatapack{
|
||||||
|
+
|
||||||
|
+ private final String name;
|
||||||
|
+ private final Datapack.Compatibility compatibility;
|
||||||
|
+
|
||||||
|
+ PaperDiscoveredDatapack(Pack pack) {
|
||||||
|
+ this.name = pack.getId();
|
||||||
|
+ this.compatibility = Datapack.Compatibility.valueOf(pack.getCompatibility().name());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public String getName() {
|
||||||
|
+ return this.name;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Datapack.Compatibility getCompatibility() {
|
||||||
|
+ return this.compatibility;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean equals(final Object o) {
|
||||||
|
+ if (this == o) return true;
|
||||||
|
+ if (o == null || this.getClass() != o.getClass()) return false;
|
||||||
|
+ final PaperDiscoveredDatapack that = (PaperDiscoveredDatapack) o;
|
||||||
|
+ return Objects.equals(this.name, that.name) && this.compatibility == that.compatibility;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public int hashCode() {
|
||||||
|
+ return Objects.hash(this.name, this.compatibility);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public String toString() {
|
||||||
|
+ return "PaperDiscoveredDatapack{" +
|
||||||
|
+ "name='" + this.name + '\'' +
|
||||||
|
+ ", compatibility=" + this.compatibility +
|
||||||
|
+ '}';
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/datapack/PluginPackSource.java b/src/main/java/io/papermc/paper/datapack/PluginPackSource.java
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000000000000000000000000000..dfea23ddde7b929f4d47c5de9539cf8bb96bcfff
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/datapack/PluginPackSource.java
|
||||||
|
@@ -0,0 +1,26 @@
|
||||||
|
+package io.papermc.paper.datapack;
|
||||||
|
+
|
||||||
|
+import net.minecraft.ChatFormatting;
|
||||||
|
+import net.minecraft.network.chat.Component;
|
||||||
|
+import net.minecraft.server.packs.repository.PackSource;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
+
|
||||||
|
+@DefaultQualifier(NonNull.class)
|
||||||
|
+final class PluginPackSource implements PackSource {
|
||||||
|
+
|
||||||
|
+ static final PackSource INSTANCE = new PluginPackSource();
|
||||||
|
+
|
||||||
|
+ private PluginPackSource() {
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Component decorate(final Component packDisplayName) {
|
||||||
|
+ return Component.translatable("pack.nameAndSource", packDisplayName, "plugin").withStyle(ChatFormatting.GRAY);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean shouldAddAutomatically() {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java
|
||||||
|
index cca76f2d1623952017a83fdb027f77a601c79b3e..9770bd30943b81d85e3ccdf1ebdbdf0524bff243 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java
|
||||||
|
@@ -27,7 +27,8 @@ public class LifecycleEventRunner {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogUtils.getClassLogger();
|
||||||
|
private static final Supplier<Set<LifecycleEventType<?, ?, ?>>> BLOCKS_RELOADING = Suppliers.memoize(() -> Set.of( // lazy due to cyclic initialization
|
||||||
|
- LifecycleEvents.COMMANDS
|
||||||
|
+ LifecycleEvents.COMMANDS,
|
||||||
|
+ LifecycleEvents.DATAPACK_DISCOVERY
|
||||||
|
));
|
||||||
|
public static final LifecycleEventRunner INSTANCE = new LifecycleEventRunner();
|
||||||
|
|
||||||
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||||
|
index 696d075ca2883f3c37e35f983c4d020e5db89d16..78a4dd6a6b5649fd42a729c98a8e03dd80349290 100644
|
||||||
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||||
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||||
|
@@ -2365,7 +2365,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
FeatureFlagSet featureflagset = initMode ? FeatureFlagSet.of() : dataConfiguration.enabledFeatures();
|
||||||
|
FeatureFlagSet featureflagset1 = initMode ? FeatureFlags.REGISTRY.allFlags() : dataConfiguration.enabledFeatures();
|
||||||
|
|
||||||
|
- resourcePackManager.reload();
|
||||||
|
+ resourcePackManager.reload(true); // Paper - will load resource packs
|
||||||
|
if (safeMode) {
|
||||||
|
return MinecraftServer.configureRepositoryWithSelection(resourcePackManager, List.of("vanilla"), featureflagset, false);
|
||||||
|
} else {
|
||||||
|
diff --git a/src/main/java/net/minecraft/server/commands/ReloadCommand.java b/src/main/java/net/minecraft/server/commands/ReloadCommand.java
|
||||||
|
index c020c86194723a5c89816f91e0b7c5eeaf132b7e..504040c031770e2b4b5111753b8ec6b3975ca937 100644
|
||||||
|
--- a/src/main/java/net/minecraft/server/commands/ReloadCommand.java
|
||||||
|
+++ b/src/main/java/net/minecraft/server/commands/ReloadCommand.java
|
||||||
|
@@ -28,7 +28,7 @@ public class ReloadCommand {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<String> discoverNewPacks(PackRepository dataPackManager, WorldData saveProperties, Collection<String> enabledDataPacks) {
|
||||||
|
- dataPackManager.reload();
|
||||||
|
+ dataPackManager.reload(true); // Paper - will perform a full reload
|
||||||
|
Collection<String> collection1 = Lists.newArrayList(enabledDataPacks);
|
||||||
|
Collection<String> collection2 = saveProperties.getDataConfiguration().dataPacks().getDisabled();
|
||||||
|
Iterator iterator = dataPackManager.getAvailableIds().iterator();
|
||||||
|
diff --git a/src/main/java/net/minecraft/server/packs/repository/PackRepository.java b/src/main/java/net/minecraft/server/packs/repository/PackRepository.java
|
||||||
|
index 7cae8350023fb138bfcc5af28af6d36a3433d063..75d98b8c0850906a51b519746f112cb0e45b2d77 100644
|
||||||
|
--- a/src/main/java/net/minecraft/server/packs/repository/PackRepository.java
|
||||||
|
+++ b/src/main/java/net/minecraft/server/packs/repository/PackRepository.java
|
||||||
|
@@ -21,8 +21,12 @@ public class PackRepository {
|
||||||
|
private final Set<RepositorySource> sources;
|
||||||
|
private Map<String, Pack> available = ImmutableMap.of();
|
||||||
|
private List<Pack> selected = ImmutableList.of();
|
||||||
|
+ private final net.minecraft.world.level.validation.DirectoryValidator validator; // Paper - add validator
|
||||||
|
|
||||||
|
- public PackRepository(RepositorySource... providers) {
|
||||||
|
+ // Paper start - add validator
|
||||||
|
+ public PackRepository(net.minecraft.world.level.validation.DirectoryValidator validator, RepositorySource... providers) {
|
||||||
|
+ this.validator = validator;
|
||||||
|
+ // Paper end - add validator
|
||||||
|
this.sources = ImmutableSet.copyOf(providers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -33,9 +37,14 @@ public class PackRepository {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload() {
|
||||||
|
+ // Paper start - perform a full reload
|
||||||
|
+ this.reload(false);
|
||||||
|
+ }
|
||||||
|
+ public void reload(boolean addRequiredPacks) {
|
||||||
|
+ // Paper end
|
||||||
|
List<String> list = this.selected.stream().map(Pack::getId).collect(ImmutableList.toImmutableList());
|
||||||
|
this.available = this.discoverAvailable();
|
||||||
|
- this.selected = this.rebuildSelected(list);
|
||||||
|
+ this.selected = this.rebuildSelected(list, addRequiredPacks); // Paper
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Pack> discoverAvailable() {
|
||||||
|
@@ -45,11 +54,18 @@ public class PackRepository {
|
||||||
|
repositorySource.loadPacks(profile -> map.put(profile.getId(), profile));
|
||||||
|
}
|
||||||
|
|
||||||
|
- return ImmutableMap.copyOf(map);
|
||||||
|
+ // Paper start - custom plugin-loaded datapacks
|
||||||
|
+ final io.papermc.paper.datapack.PaperDatapackRegistrar registrar = new io.papermc.paper.datapack.PaperDatapackRegistrar(this.validator, map);
|
||||||
|
+ io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.callStaticRegistrarEvent(io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents.DATAPACK_DISCOVERY,
|
||||||
|
+ registrar,
|
||||||
|
+ io.papermc.paper.plugin.bootstrap.BootstrapContext.class
|
||||||
|
+ );
|
||||||
|
+ return ImmutableMap.copyOf(registrar.discoveredPacks);
|
||||||
|
+ // Paper end - custom plugin-loaded datapacks
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelected(Collection<String> enabled) {
|
||||||
|
- this.selected = this.rebuildSelected(enabled);
|
||||||
|
+ this.selected = this.rebuildSelected(enabled, false); // Paper - add willReload boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addPack(String profile) {
|
||||||
|
@@ -76,11 +92,11 @@ public class PackRepository {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- private List<Pack> rebuildSelected(Collection<String> enabledNames) {
|
||||||
|
+ private List<Pack> rebuildSelected(Collection<String> enabledNames, boolean addRequiredPacks) { // Paper - add addRequiredPacks boolean
|
||||||
|
List<Pack> list = this.getAvailablePacks(enabledNames).collect(Util.toMutableList());
|
||||||
|
|
||||||
|
for (Pack pack : this.available.values()) {
|
||||||
|
- if (pack.isRequired() && !list.contains(pack)) {
|
||||||
|
+ if (pack.isRequired() && !list.contains(pack) && addRequiredPacks) { // Paper - add addRequiredPacks boolean
|
||||||
|
pack.getDefaultPosition().insert(list, pack, Pack::selectionConfig, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/src/main/java/net/minecraft/server/packs/repository/ServerPacksSource.java b/src/main/java/net/minecraft/server/packs/repository/ServerPacksSource.java
|
||||||
|
index 396ec10a76bdadbf5be2f0e15e88eed47619004d..ac9256a65fab2896fcb42808ad65105701eae6f4 100644
|
||||||
|
--- a/src/main/java/net/minecraft/server/packs/repository/ServerPacksSource.java
|
||||||
|
+++ b/src/main/java/net/minecraft/server/packs/repository/ServerPacksSource.java
|
||||||
|
@@ -83,13 +83,13 @@ public class ServerPacksSource extends BuiltInPackSource {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PackRepository createPackRepository(Path dataPacksPath, DirectoryValidator symlinkFinder) {
|
||||||
|
- return new PackRepository(
|
||||||
|
+ return new PackRepository(symlinkFinder, // Paper - add validator
|
||||||
|
new ServerPacksSource(symlinkFinder), new FolderRepositorySource(dataPacksPath, PackType.SERVER_DATA, PackSource.WORLD, symlinkFinder)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PackRepository createVanillaTrustedRepository() {
|
||||||
|
- return new PackRepository(new ServerPacksSource(new DirectoryValidator(path -> true)));
|
||||||
|
+ return new PackRepository(new DirectoryValidator(path -> true), new ServerPacksSource(new DirectoryValidator(path -> true))); // Paper - add validator
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PackRepository createPackRepository(LevelStorageSource.LevelStorageAccess session) {
|
|
@ -0,0 +1,189 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||||
|
Date: Mon, 23 Sep 2024 16:10:57 -0700
|
||||||
|
Subject: [PATCH] move methods to PaperDiscoveredDatapack
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java
|
||||||
|
index 8bd8263b51fb2bb364353565b1ba26b3b0d1d55e..5a78ce1bee122951a9346e99f1b05eef772912b5 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java
|
||||||
|
@@ -2,71 +2,27 @@ package io.papermc.paper.datapack;
|
||||||
|
|
||||||
|
import io.papermc.paper.adventure.PaperAdventure;
|
||||||
|
import io.papermc.paper.event.server.ServerResourcesReloadedEvent;
|
||||||
|
-import io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
-import java.util.Map;
|
||||||
|
-import java.util.Set;
|
||||||
|
-import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.packs.repository.Pack;
|
||||||
|
-import net.minecraft.server.packs.repository.PackSource;
|
||||||
|
-import org.bukkit.FeatureFlag;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
|
||||||
|
@DefaultQualifier(NonNull.class)
|
||||||
|
-public class PaperDatapack implements Datapack {
|
||||||
|
-
|
||||||
|
- private static final Map<PackSource, DatapackSource> PACK_SOURCES = new ConcurrentHashMap<>();
|
||||||
|
- static {
|
||||||
|
- PACK_SOURCES.put(PackSource.DEFAULT, DatapackSource.DEFAULT);
|
||||||
|
- PACK_SOURCES.put(PackSource.BUILT_IN, DatapackSource.BUILT_IN);
|
||||||
|
- PACK_SOURCES.put(PackSource.FEATURE, DatapackSource.FEATURE);
|
||||||
|
- PACK_SOURCES.put(PackSource.WORLD, DatapackSource.WORLD);
|
||||||
|
- PACK_SOURCES.put(PackSource.SERVER, DatapackSource.SERVER);
|
||||||
|
- }
|
||||||
|
+public class PaperDatapack extends PaperDiscoveredDatapack implements Datapack {
|
||||||
|
|
||||||
|
private final Pack pack;
|
||||||
|
private final boolean enabled;
|
||||||
|
|
||||||
|
PaperDatapack(final Pack pack, final boolean enabled) {
|
||||||
|
+ super(pack);
|
||||||
|
this.pack = pack;
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
- @Override
|
||||||
|
- public String getName() {
|
||||||
|
- return this.pack.getId();
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- @Override
|
||||||
|
- public Component getTitle() {
|
||||||
|
- return PaperAdventure.asAdventure(this.pack.getTitle());
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- @Override
|
||||||
|
- public Component getDescription() {
|
||||||
|
- return PaperAdventure.asAdventure(this.pack.getDescription());
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- @Override
|
||||||
|
- public boolean isRequired() {
|
||||||
|
- return this.pack.isRequired();
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- @Override
|
||||||
|
- public Compatibility getCompatibility() {
|
||||||
|
- return Datapack.Compatibility.valueOf(this.pack.getCompatibility().name());
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- @Override
|
||||||
|
- public Set<FeatureFlag> getRequiredFeatures() {
|
||||||
|
- return PaperFeatureFlagProviderImpl.fromNms(this.pack.getRequestedFeatures());
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return this.enabled;
|
||||||
|
@@ -91,11 +47,6 @@ public class PaperDatapack implements Datapack {
|
||||||
|
server.reloadResources(enabledPacks.stream().map(Pack::getId).toList(), ServerResourcesReloadedEvent.Cause.PLUGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
- @Override
|
||||||
|
- public DatapackSource getSource() {
|
||||||
|
- return PACK_SOURCES.computeIfAbsent(this.pack.location().source(), source -> new DatapackSourceImpl(source.toString()));
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
@Override
|
||||||
|
public Component computeDisplayName() {
|
||||||
|
return PaperAdventure.asAdventure(this.pack.getChatLink(this.enabled));
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/datapack/PaperDiscoveredDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDiscoveredDatapack.java
|
||||||
|
index 572a62ceafcd066adfc0c2588cc43a0b61cedb7f..711e6a8791a72e759ca777f66426ce12fc2230b0 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/datapack/PaperDiscoveredDatapack.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/datapack/PaperDiscoveredDatapack.java
|
||||||
|
@@ -1,46 +1,67 @@
|
||||||
|
package io.papermc.paper.datapack;
|
||||||
|
|
||||||
|
-import java.util.Objects;
|
||||||
|
+import io.papermc.paper.adventure.PaperAdventure;
|
||||||
|
+import io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl;
|
||||||
|
+import java.util.Map;
|
||||||
|
+import java.util.Set;
|
||||||
|
+import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
+import net.kyori.adventure.text.Component;
|
||||||
|
import net.minecraft.server.packs.repository.Pack;
|
||||||
|
+import net.minecraft.server.packs.repository.PackSource;
|
||||||
|
+import org.bukkit.FeatureFlag;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
|
||||||
|
-public class PaperDiscoveredDatapack implements DiscoveredDatapack{
|
||||||
|
+@DefaultQualifier(NonNull.class)
|
||||||
|
+public class PaperDiscoveredDatapack implements DiscoveredDatapack {
|
||||||
|
|
||||||
|
- private final String name;
|
||||||
|
- private final Datapack.Compatibility compatibility;
|
||||||
|
+ private static final Map<PackSource, DatapackSource> PACK_SOURCES = new ConcurrentHashMap<>();
|
||||||
|
+ static {
|
||||||
|
+ PACK_SOURCES.put(PackSource.DEFAULT, DatapackSource.DEFAULT);
|
||||||
|
+ PACK_SOURCES.put(PackSource.BUILT_IN, DatapackSource.BUILT_IN);
|
||||||
|
+ PACK_SOURCES.put(PackSource.FEATURE, DatapackSource.FEATURE);
|
||||||
|
+ PACK_SOURCES.put(PackSource.WORLD, DatapackSource.WORLD);
|
||||||
|
+ PACK_SOURCES.put(PackSource.SERVER, DatapackSource.SERVER);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private final Pack pack;
|
||||||
|
|
||||||
|
PaperDiscoveredDatapack(Pack pack) {
|
||||||
|
- this.name = pack.getId();
|
||||||
|
- this.compatibility = Datapack.Compatibility.valueOf(pack.getCompatibility().name());
|
||||||
|
+ this.pack = pack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
- return this.name;
|
||||||
|
+ return this.pack.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
- public Datapack.Compatibility getCompatibility() {
|
||||||
|
- return this.compatibility;
|
||||||
|
+ public Component getTitle() {
|
||||||
|
+ return PaperAdventure.asAdventure(this.pack.getTitle());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Component getDescription() {
|
||||||
|
+ return PaperAdventure.asAdventure(this.pack.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
- public boolean equals(final Object o) {
|
||||||
|
- if (this == o) return true;
|
||||||
|
- if (o == null || this.getClass() != o.getClass()) return false;
|
||||||
|
- final PaperDiscoveredDatapack that = (PaperDiscoveredDatapack) o;
|
||||||
|
- return Objects.equals(this.name, that.name) && this.compatibility == that.compatibility;
|
||||||
|
+ public boolean isRequired() {
|
||||||
|
+ return this.pack.isRequired();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Datapack.Compatibility getCompatibility() {
|
||||||
|
+ return Datapack.Compatibility.valueOf(this.pack.getCompatibility().name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
- public int hashCode() {
|
||||||
|
- return Objects.hash(this.name, this.compatibility);
|
||||||
|
+ public Set<FeatureFlag> getRequiredFeatures() {
|
||||||
|
+ return PaperFeatureFlagProviderImpl.fromNms(this.pack.getRequestedFeatures());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
- public String toString() {
|
||||||
|
- return "PaperDiscoveredDatapack{" +
|
||||||
|
- "name='" + this.name + '\'' +
|
||||||
|
- ", compatibility=" + this.compatibility +
|
||||||
|
- '}';
|
||||||
|
+ public DatapackSource getSource() {
|
||||||
|
+ return PACK_SOURCES.computeIfAbsent(this.pack.location().source(), source -> new DatapackSourceImpl(source.toString()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,14 @@
|
||||||
package io.papermc.testplugin;
|
package io.papermc.testplugin;
|
||||||
|
|
||||||
|
import io.papermc.paper.datapack.DatapackRegistrar;
|
||||||
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||||
import io.papermc.paper.plugin.bootstrap.PluginBootstrap;
|
import io.papermc.paper.plugin.bootstrap.PluginBootstrap;
|
||||||
|
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
|
||||||
|
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Objects;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class TestPluginBootstrap implements PluginBootstrap {
|
public class TestPluginBootstrap implements PluginBootstrap {
|
||||||
|
@ -9,6 +16,16 @@ public class TestPluginBootstrap implements PluginBootstrap {
|
||||||
@Override
|
@Override
|
||||||
public void bootstrap(@NotNull BootstrapContext context) {
|
public void bootstrap(@NotNull BootstrapContext context) {
|
||||||
// io.papermc.testplugin.brigtests.Registration.registerViaBootstrap(context);
|
// io.papermc.testplugin.brigtests.Registration.registerViaBootstrap(context);
|
||||||
|
final LifecycleEventManager<BootstrapContext> manager = context.getLifecycleManager();
|
||||||
|
manager.registerEventHandler(LifecycleEvents.DATAPACK_DISCOVERY, event -> {
|
||||||
|
final DatapackRegistrar registrar = event.registrar();
|
||||||
|
try {
|
||||||
|
final URI uri = Objects.requireNonNull(TestPluginBootstrap.class.getResource("/pack")).toURI();
|
||||||
|
registrar.discoverPack(uri, "test");
|
||||||
|
} catch (final URISyntaxException | IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"values": [
|
||||||
|
"minecraft:zombie",
|
||||||
|
"minecraft:spider"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"values": [
|
||||||
|
"minecraft:stone_bricks",
|
||||||
|
"minecraft:string"
|
||||||
|
]
|
||||||
|
}
|
6
test-plugin/src/main/resources/pack/pack.mcmeta
Normal file
6
test-plugin/src/main/resources/pack/pack.mcmeta
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"pack":{
|
||||||
|
"pack_format": 41,
|
||||||
|
"description": "Test datapack for tags"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue