From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Mon, 22 Jul 2024 09:05:56 +0000 Subject: [PATCH] Leaves plugins diff --git a/build.gradle.kts b/build.gradle.kts index ecc29f64b5cbd2849f86d22aee8a76d172b3def0..881896b9f25afc530f4c04096ee364b80f8e8e0c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { implementation("com.github.luben:zstd-jni:1.5.6-3") implementation("org.lz4:lz4-java:1.8.0") // Leaves end - Linear format + implementation("org.spongepowered:configurate-hocon:4.2.0-SNAPSHOT") // Leaves - leaves plugins implementation("org.apache.logging.log4j:log4j-iostreams:2.22.1") // Paper - remove exclusion implementation("org.ow2.asm:asm-commons:9.7.1") implementation("org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT") // Paper - config files diff --git a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java index f0fce4113fb07c64adbec029d177c236cbdcbae8..f3cb913f29e1aff46233af2f086d205a51ac582d 100644 --- a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java +++ b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java @@ -63,6 +63,7 @@ public class PaperPluginsCommand extends BukkitCommand { private static final Component LEGACY_PLUGIN_STAR = Component.text('*', TextColor.color(255, 212, 42)).hoverEvent(LEGACY_PLUGIN_INFO); private static final Component INFO_ICON_START = Component.text("ℹ ", INFO_COLOR); + private static final Component LEAVES_HEADER = Component.text("Leaves Plugins:", TextColor.color(55, 209, 171)); // Leaves - leaves plugin private static final Component PAPER_HEADER = Component.text("Paper Plugins:", TextColor.color(2, 136, 209)); private static final Component BUKKIT_HEADER = Component.text("Bukkit Plugins:", TextColor.color(237, 129, 6)); private static final Component PLUGIN_TICK = Component.text("- ", NamedTextColor.DARK_GRAY); @@ -170,6 +171,8 @@ public class PaperPluginsCommand extends BukkitCommand { TreeMap> paperPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); TreeMap> spigotPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + // Leaves start - leaves plugin + TreeMap> leavesPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); for (PluginProvider provider : LaunchEntryPointHandler.INSTANCE.get(Entrypoint.PLUGIN).getRegisteredProviders()) { @@ -178,14 +181,23 @@ public class PaperPluginsCommand extends BukkitCommand { if (provider instanceof SpigotPluginProvider) { spigotPlugins.put(configuration.getDisplayName(), provider); } else if (provider instanceof PaperPluginParent.PaperServerPluginProvider) { - paperPlugins.put(configuration.getDisplayName(), provider); + if(provider.getMeta() instanceof org.leavesmc.leaves.plugin.provider.configuration.LeavesPluginMeta) leavesPlugins.put(configuration.getDisplayName(), provider); + else paperPlugins.put(configuration.getDisplayName(), provider); } } - Component infoMessage = Component.text("Server Plugins (%s):".formatted(paperPlugins.size() + spigotPlugins.size()), NamedTextColor.WHITE); + Component infoMessage = Component.text("Server Plugins (%s):".formatted(paperPlugins.size() + spigotPlugins.size() + leavesPlugins.size()), NamedTextColor.WHITE); //.append(INFO_ICON_START.hoverEvent(SERVER_PLUGIN_INFO)); TODO: Add docs sender.sendMessage(infoMessage); + if (!leavesPlugins.isEmpty()) { + sender.sendMessage(LEAVES_HEADER); + } + + for (Component component : formatProviders(leavesPlugins)) { + sender.sendMessage(component); + } + // Leaves end - leaves plugin if (!paperPlugins.isEmpty()) { sender.sendMessage(PAPER_HEADER); diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java index 8cd649c977172f6b757d68565fcbb9eb8ae100a3..390625fbf54139b205a23b94d89a860fbb2c92d9 100644 --- a/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java +++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java @@ -18,7 +18,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -class LegacyPaperMeta { +public class LegacyPaperMeta { // Leaves - leaves plugins private static final TypeToken>> TYPE_TOKEN = new TypeToken<>() { diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java index d3b3a8baca013909fa9c6204d964d7d7efeb2719..cdde16a4999fbf56c334c65e23d995b7a3604518 100644 --- a/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java +++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java @@ -55,7 +55,7 @@ public class PaperPluginMeta implements PluginMeta { @Required private String version; private String description; - private List authors = List.of(); + protected List authors = List.of(); // Leaves - leaves plugins private List contributors = List.of(); private String website; private String prefix; diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java b/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java index 8d0da6e46d4eb5eb05c3144510c4ef083559d0ec..72a69ed1d4cdeecd25bfa4fddc3ecc2b21550bad 100644 --- a/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java +++ b/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java @@ -23,6 +23,7 @@ import java.util.jar.JarFile; public abstract class PluginFileType { public static final String PAPER_PLUGIN_YML = "paper-plugin.yml"; + public static final String LEAVES_PLUGIN_CONF = "leaves-plugin.conf"; // Leaves - leaves plugins private static final List CONFIG_TYPES = new ArrayList<>(); public static final PluginFileType PAPER = new PluginFileType<>(PAPER_PLUGIN_YML, PaperPluginParent.FACTORY) { @@ -43,8 +44,21 @@ public abstract class PluginFileType { entrypointHandler.register(Entrypoint.PLUGIN, provider); } }; + // Leaves start - leaves plugins + public static final PluginFileType LEAVES = new PluginFileType<>(LEAVES_PLUGIN_CONF, PaperPluginParent.LEAVES_FACTORY) { + @Override + protected void register(EntrypointHandler entrypointHandler, PaperPluginParent parent) { + PaperPluginParent.PaperBootstrapProvider bootstrapPluginProvider = null; + if (parent.shouldCreateBootstrap()) { + bootstrapPluginProvider = parent.createBootstrapProvider(); + entrypointHandler.register(Entrypoint.BOOTSTRAPPER, bootstrapPluginProvider); + } + entrypointHandler.register(Entrypoint.PLUGIN, parent.createPluginProvider(bootstrapPluginProvider)); + } + }; - private static final List> VALUES = List.of(PAPER, SPIGOT); + private static final List> VALUES = List.of(LEAVES, PAPER, SPIGOT); + // Leaves end - leaves plugins private final String config; private final PluginTypeFactory factory; diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java index 55a6898e95704cddafda1ca5dc0951c7102fe10b..ebde8a79143a5e314d5054f2d125d276eaa1e734 100644 --- a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java +++ b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java @@ -27,6 +27,7 @@ import java.util.jar.JarFile; public class PaperPluginParent { public static final PluginTypeFactory FACTORY = new PaperPluginProviderFactory(); + public static final PluginTypeFactory LEAVES_FACTORY = new org.leavesmc.leaves.plugin.provider.LeavesPluginProviderFactory(); // Leaves - leaves plugins private final Path path; private final JarFile jarFile; private final PaperPluginMeta description; diff --git a/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java b/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java index 28857d0c9b53f2068d51b8f09ef40df7a2b97502..b4d2d7280237a9ad7df095e26773e01211201b84 100644 --- a/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java +++ b/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java @@ -333,7 +333,13 @@ public final class PluginRemapper { } index.skip(inputFile); return CompletableFuture.completedFuture(inputFile); - } + } else if (ns == null && Files.exists(fs.getPath(PluginFileType.LEAVES_PLUGIN_CONF))) { // Leaves start - leaves plugins + if (DEBUG_LOGGING) { + LOGGER.info("Plugin '{}' is a Leaves plugin with no namespace specified.", inputFile); + } + index.skip(inputFile); + return CompletableFuture.completedFuture(inputFile); + } // Leaves end - leaves plugins } } catch (final IOException ex) { return CompletableFuture.failedFuture(new RuntimeException("Failed to open plugin jar " + inputFile, ex)); diff --git a/src/main/java/org/leavesmc/leaves/plugin/provider/LeavesPluginProviderFactory.java b/src/main/java/org/leavesmc/leaves/plugin/provider/LeavesPluginProviderFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..35fe2f6a1785d525a46c4bc4d61c5043a056daef --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/plugin/provider/LeavesPluginProviderFactory.java @@ -0,0 +1,57 @@ +package org.leavesmc.leaves.plugin.provider; + +import com.destroystokyo.paper.utils.PaperPluginLogger; +import io.papermc.paper.plugin.bootstrap.PluginProviderContext; +import io.papermc.paper.plugin.bootstrap.PluginProviderContextImpl; +import io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader; +import io.papermc.paper.plugin.entrypoint.classloader.PaperSimplePluginClassLoader; +import io.papermc.paper.plugin.loader.PaperClasspathBuilder; +import io.papermc.paper.plugin.loader.PluginLoader; +import io.papermc.paper.plugin.provider.type.PluginTypeFactory; +import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent; +import io.papermc.paper.plugin.provider.util.ProviderUtil; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.plugin.provider.configuration.LeavesPluginMeta; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Path; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.logging.Logger; + +public class LeavesPluginProviderFactory implements PluginTypeFactory { + @Override + public PaperPluginParent build(JarFile file, LeavesPluginMeta configuration, Path source) { + Logger jul = PaperPluginLogger.getLogger(configuration); + ComponentLogger logger = ComponentLogger.logger(jul.getName()); + PluginProviderContext context = PluginProviderContextImpl.create(configuration, logger, source); + + PaperClasspathBuilder builder = new PaperClasspathBuilder(context); + + if (configuration.getLoader() != null) { + try ( + PaperSimplePluginClassLoader simplePluginClassLoader = new PaperSimplePluginClassLoader(source, file, configuration, this.getClass().getClassLoader()) + ) { + PluginLoader loader = ProviderUtil.loadClass(configuration.getLoader(), PluginLoader.class, simplePluginClassLoader); + loader.classloader(builder); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + PaperPluginClassLoader classLoader = builder.buildClassLoader(jul, source, file, configuration); + return new PaperPluginParent(source, file, configuration, classLoader, context); + } + + @Override + public LeavesPluginMeta create(@NotNull JarFile file, JarEntry config) throws IOException { + LeavesPluginMeta configuration; + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(file.getInputStream(config)))) { + configuration = LeavesPluginMeta.create(bufferedReader); + } + return configuration; + } +} \ No newline at end of file diff --git a/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/LeavesPluginMeta.java b/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/LeavesPluginMeta.java new file mode 100644 index 0000000000000000000000000000000000000000..4eb3396fd82e3d32ecb4ee4af4ffa28ab86f34b7 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/LeavesPluginMeta.java @@ -0,0 +1,90 @@ +package org.leavesmc.leaves.plugin.provider.configuration; + +import com.google.common.collect.ImmutableList; +import io.papermc.paper.configuration.constraint.Constraint; +import io.papermc.paper.configuration.serializer.ComponentSerializer; +import io.papermc.paper.configuration.serializer.EnumValueSerializer; +import io.papermc.paper.plugin.provider.configuration.FlattenedResolver; +import io.papermc.paper.plugin.provider.configuration.LegacyPaperMeta; +import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; +import io.papermc.paper.plugin.provider.configuration.serializer.PermissionConfigurationSerializer; +import io.papermc.paper.plugin.provider.configuration.serializer.constraints.PluginConfigConstraints; +import io.papermc.paper.plugin.provider.configuration.type.PermissionConfiguration; +import org.bukkit.craftbukkit.util.ApiVersion; +import org.spongepowered.configurate.CommentedConfigurationNode; +import org.spongepowered.configurate.ConfigurateException; +import org.spongepowered.configurate.hocon.HoconConfigurationLoader; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; +import org.spongepowered.configurate.objectmapping.ObjectMapper; +import org.spongepowered.configurate.serialize.ScalarSerializer; +import org.spongepowered.configurate.serialize.SerializationException; + +import java.io.BufferedReader; +import java.lang.reflect.Type; +import java.util.List; +import java.util.function.Predicate; + +@ConfigSerializable +public class LeavesPluginMeta extends PaperPluginMeta { + private List mixins; + static final ApiVersion MINIMUM = ApiVersion.getOrCreateVersion("1.21"); + + public static LeavesPluginMeta create(BufferedReader reader) throws ConfigurateException { + HoconConfigurationLoader loader = HoconConfigurationLoader.builder() + .prettyPrinting(true) + .emitComments(true) + .emitJsonCompatible(true) + .source(() -> reader) + .defaultOptions((options) -> + options.serializers((serializers) -> + serializers.register(new ScalarSerializer<>(ApiVersion.class) { + @Override + public ApiVersion deserialize(final Type type, final Object obj) throws SerializationException { + try { + final ApiVersion version = ApiVersion.getOrCreateVersion(obj.toString()); + if (version.isOlderThan(MINIMUM)) { + throw new SerializationException(version + " is too old for a leaves plugin!"); + } + return version; + } catch (final IllegalArgumentException e) { + throw new SerializationException(e); + } + } + + @Override + protected Object serialize(final ApiVersion item, final Predicate> typeSupported) { + return item.getVersionString(); + } + }) + .register(new EnumValueSerializer()) + .register(PermissionConfiguration.class, PermissionConfigurationSerializer.SERIALIZER) + .register(new ComponentSerializer()) + .registerAnnotatedObjects( + ObjectMapper.factoryBuilder() + .addConstraint(Constraint.class, new Constraint.Factory()) + .addConstraint(PluginConfigConstraints.PluginName.class, String.class, new PluginConfigConstraints.PluginName.Factory()) + .addConstraint(PluginConfigConstraints.PluginNameSpace.class, String.class, new PluginConfigConstraints.PluginNameSpace.Factory()) + .addNodeResolver(new FlattenedResolver.Factory()) + .build() + ) + ) + ) + .build(); + CommentedConfigurationNode node = loader.load(); + LegacyPaperMeta.migrate(node); + LeavesPluginMeta pluginConfiguration = node.require(LeavesPluginMeta.class); + + if (!node.node("author").virtual()) { + pluginConfiguration.authors = ImmutableList.builder() + .addAll(pluginConfiguration.authors) + .add(node.node("author").getString()) + .build(); + } + + return pluginConfiguration; + } + + public List getMixins() { + return mixins; + } +}