From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Connor Linfoot Date: Sun, 16 May 2021 15:07:34 +0100 Subject: [PATCH] Add basic Datapack API Co-authored-by: Jake Potrebic diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java new file mode 100644 index 0000000000000000000000000000000000000000..8bd8263b51fb2bb364353565b1ba26b3b0d1d55e --- /dev/null +++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java @@ -0,0 +1,103 @@ +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 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; + private final boolean enabled; + + PaperDatapack(final Pack pack, final boolean enabled) { + 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 getRequiredFeatures() { + return PaperFeatureFlagProviderImpl.fromNms(this.pack.getRequestedFeatures()); + } + + @Override + public boolean isEnabled() { + return this.enabled; + } + + @Override + public void setEnabled(final boolean enabled) { + final MinecraftServer server = MinecraftServer.getServer(); + final List enabledPacks = new ArrayList<>(server.getPackRepository().getSelectedPacks()); + final @Nullable Pack packToChange = server.getPackRepository().getPack(this.getName()); + if (packToChange == null) { + throw new IllegalStateException("Cannot toggle state of pack that doesn't exist: " + this.getName()); + } + if (enabled == enabledPacks.contains(packToChange)) { + return; + } + if (enabled) { + packToChange.getDefaultPosition().insert(enabledPacks, packToChange, Pack::selectionConfig, false); // modeled off the default /datapack enable logic + } else { + enabledPacks.remove(packToChange); + } + 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/PaperDatapackManager.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java new file mode 100644 index 0000000000000000000000000000000000000000..caa41c525d2b36b5a9f9942380f06c97d5781a93 --- /dev/null +++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java @@ -0,0 +1,55 @@ +package io.papermc.paper.datapack; + +import com.google.common.collect.Collections2; +import java.util.Collection; +import java.util.Collections; +import java.util.function.Predicate; +import net.minecraft.server.packs.repository.Pack; +import net.minecraft.server.packs.repository.PackRepository; +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 PaperDatapackManager implements DatapackManager { + + private final PackRepository repository; + + public PaperDatapackManager(final PackRepository repository) { + this.repository = repository; + } + + @Override + public void refreshPacks() { + this.repository.reload(); + } + + @Override + public @Nullable Datapack getPack(final @NonNull String name) { + final @Nullable Pack pack = this.repository.getPack(name); + if (pack == null) { + return null; + } + return new PaperDatapack(pack, this.repository.getSelectedPacks().contains(pack)); + } + + @Override + public Collection getPacks() { + final Collection enabledPacks = this.repository.getSelectedPacks(); + return this.transformPacks(this.repository.getAvailablePacks(), enabledPacks::contains); + } + + @Override + public Collection getEnabledPacks() { + return this.transformPacks(this.repository.getSelectedPacks(), pack -> true); + } + + private Collection transformPacks(final Collection packs, final Predicate enabled) { + return Collections.unmodifiableCollection( + Collections2.transform( + packs, + pack -> new PaperDatapack(pack, enabled.test(pack)) + ) + ); + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 617eb11d17ef8791a8a8b0fddc19b6a3a8d0af36..10d7186b96038b03de8684c0ad09732a2f82e46f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -308,6 +308,7 @@ public final class CraftServer implements Server { private final List playerView; public int reloadCount; public Set activeCompatibilities = Collections.emptySet(); + private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper public static Exception excessiveVelEx; // Paper - Velocity warnings static { @@ -392,6 +393,7 @@ public final class CraftServer implements Server { if (this.configuration.getBoolean("settings.use-map-color-cache")) { MapPalette.setMapColorCache(new CraftMapColorCache(this.logger)); } + datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper } public boolean getCommandBlockOverride(String command) { @@ -3036,5 +3038,11 @@ public final class CraftServer implements Server { public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { return mobGoals; } + + @Override + public io.papermc.paper.datapack.PaperDatapackManager getDatapackManager() { + return datapackManager; + } + // Paper end }