From 632f5c3800f91d411a047f4ceedbd0c3a7e8f442 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Tue, 23 Jul 2024 13:03:16 +0800 Subject: [PATCH] Leaves Plugin (#271) * Create devcontainer.json * feat: leaves plugins base * Show leaves plugins in /plugins * Fix LeavesPluginMeta * Delete .devcontainer directory --- patches/server/0130-Leaves-plugins.patch | 317 +++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 patches/server/0130-Leaves-plugins.patch diff --git a/patches/server/0130-Leaves-plugins.patch b/patches/server/0130-Leaves-plugins.patch new file mode 100644 index 00000000..0b8b0c93 --- /dev/null +++ b/patches/server/0130-Leaves-plugins.patch @@ -0,0 +1,317 @@ +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 0ce1157599acfe8181839955ae76697b4ac6474d..17ce9a3cc5263635bb83b6d65d7f6d13feae5a12 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") + 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 c685871155c8dff1d57ff151d7a5ec70350e5390..e911f320610fdb09382231548002b4fe0eb2c211 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 f2bc4d0b55d4c9877a442529e0b144656497dae6..b43872d65d7d59348bd09f7f1439b51871e60196 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 265c636abfd63f9ba0b0f0198867a10401c14da1..0e2487490537034c875c132d94bb4f012084d85f 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) { + throw 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; ++ } ++}