Add datapack registration lifecycle event (#11804)
This commit is contained in:
@ -1,10 +1,8 @@
|
||||
package io.papermc.paper.datapack;
|
||||
|
||||
import java.util.Set;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.FeatureFlag;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
@ -12,50 +10,8 @@ import org.jspecify.annotations.NullMarked;
|
||||
* won't be updated as datapacks are updated.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface Datapack {
|
||||
|
||||
/**
|
||||
* Gets the name/id of this datapack.
|
||||
*
|
||||
* @return the name of the pack
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets the title component of this datapack.
|
||||
*
|
||||
* @return the title
|
||||
*/
|
||||
Component getTitle();
|
||||
|
||||
/**
|
||||
* Gets the description component of this datapack.
|
||||
*
|
||||
* @return the description
|
||||
*/
|
||||
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
|
||||
*/
|
||||
Compatibility getCompatibility();
|
||||
|
||||
/**
|
||||
* Gets the set of required features for this datapack.
|
||||
*
|
||||
* @return the set of required features
|
||||
*/
|
||||
@Unmodifiable Set<FeatureFlag> getRequiredFeatures();
|
||||
@ApiStatus.NonExtendable
|
||||
public interface Datapack extends DiscoveredDatapack {
|
||||
|
||||
/**
|
||||
* Gets the enabled state of this pack.
|
||||
@ -74,13 +30,6 @@ public interface Datapack {
|
||||
*/
|
||||
void setEnabled(boolean enabled);
|
||||
|
||||
/**
|
||||
* Gets the source for this datapack.
|
||||
*
|
||||
* @return the pack source
|
||||
*/
|
||||
DatapackSource getSource();
|
||||
|
||||
/**
|
||||
* Computes the component vanilla Minecraft uses
|
||||
* to display this datapack. Includes the {@link #getSource()},
|
||||
@ -96,4 +45,11 @@ public interface Datapack {
|
||||
TOO_NEW,
|
||||
COMPATIBLE,
|
||||
}
|
||||
|
||||
/**
|
||||
* Position of the pack in the load order.
|
||||
*/
|
||||
enum Position {
|
||||
TOP, BOTTOM
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,202 @@
|
||||
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.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@NullMarked
|
||||
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(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)
|
||||
DiscoveredDatapack getDiscoveredPack(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(String name);
|
||||
|
||||
/**
|
||||
* Gets all discovered datapacks.
|
||||
*
|
||||
* @return an unmodifiable map of discovered packs
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
@Unmodifiable 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 URI uri, final 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(URI uri, String id, 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 Path path, final 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(Path path, String id, 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(PluginMeta pluginMeta, URI uri, String id, 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(PluginMeta pluginMeta, Path path, String id, 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")
|
||||
Configurer title(Component title);
|
||||
|
||||
/**
|
||||
* Sets whether this pack is going to be automatically enabled on server starts even if previously disabled.
|
||||
* Defaults to false.
|
||||
*
|
||||
* @param autoEnableOnServerStart true to ensure the pack is enabled on server starts.
|
||||
* @return the configurer for chaining
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Configurer autoEnableOnServerStart(boolean autoEnableOnServerStart);
|
||||
|
||||
/**
|
||||
* 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")
|
||||
Configurer position(boolean fixed, Datapack.Position position);
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,7 @@ public sealed interface DatapackSource permits DatapackSourceImpl {
|
||||
DatapackSource FEATURE = create("feature");
|
||||
DatapackSource WORLD = create("world");
|
||||
DatapackSource SERVER = create("server");
|
||||
DatapackSource PLUGIN = create("plugin");
|
||||
|
||||
private static DatapackSource create(final String name) {
|
||||
return new DatapackSourceImpl(name);
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
package io.papermc.paper.datapack;
|
||||
|
||||
import java.util.Set;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.FeatureFlag;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* This is a snapshot of a discovered datapack on the server. It
|
||||
* won't be updated as datapacks are updated.
|
||||
*/
|
||||
@NullMarked
|
||||
@ApiStatus.NonExtendable
|
||||
public interface DiscoveredDatapack {
|
||||
|
||||
/**
|
||||
* Gets the name/id of this datapack.
|
||||
*
|
||||
* @return the name of the pack
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets the title component of this datapack.
|
||||
*
|
||||
* @return the title
|
||||
*/
|
||||
Component getTitle();
|
||||
|
||||
/**
|
||||
* Gets the description component of this datapack.
|
||||
*
|
||||
* @return the description
|
||||
*/
|
||||
Component getDescription();
|
||||
|
||||
/**
|
||||
* Gets if this datapack is required.
|
||||
* <p>
|
||||
* A "required" datapack will always be enabled on server startup, even if previously disabled.
|
||||
*
|
||||
* @return true if the pack is required
|
||||
*/
|
||||
boolean isRequired();
|
||||
|
||||
/**
|
||||
* Gets the compatibility status of this pack.
|
||||
*
|
||||
* @return the compatibility of the pack
|
||||
*/
|
||||
Datapack.Compatibility getCompatibility();
|
||||
|
||||
/**
|
||||
* Gets the set of required features for this datapack.
|
||||
*
|
||||
* @return the set of required features
|
||||
*/
|
||||
@Unmodifiable
|
||||
Set<FeatureFlag> getRequiredFeatures();
|
||||
|
||||
/**
|
||||
* Gets the source for this datapack.
|
||||
*
|
||||
* @return the pack source
|
||||
*/
|
||||
DatapackSource getSource();
|
||||
}
|
||||
@ -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;
|
||||
@ -32,6 +34,14 @@ 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) {
|
||||
|
||||
Reference in New Issue
Block a user