Add basic Datapack API

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
This commit is contained in:
Connor Linfoot 2021-05-16 15:07:34 +01:00
parent 637bb9a05d
commit f283a61ad3
3 changed files with 166 additions and 0 deletions

View file

@ -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<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;
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<FeatureFlag> 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<Pack> 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));
}
}

View file

@ -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<Datapack> getPacks() {
final Collection<Pack> enabledPacks = this.repository.getSelectedPacks();
return this.transformPacks(this.repository.getAvailablePacks(), enabledPacks::contains);
}
@Override
public Collection<Datapack> getEnabledPacks() {
return this.transformPacks(this.repository.getSelectedPacks(), pack -> true);
}
private Collection<Datapack> transformPacks(final Collection<Pack> packs, final Predicate<Pack> enabled) {
return Collections.unmodifiableCollection(
Collections2.transform(
packs,
pack -> new PaperDatapack(pack, enabled.test(pack))
)
);
}
}

View file

@ -308,6 +308,7 @@ public final class CraftServer implements Server {
private final List<CraftPlayer> playerView; private final List<CraftPlayer> playerView;
public int reloadCount; public int reloadCount;
public Set<String> activeCompatibilities = Collections.emptySet(); public Set<String> activeCompatibilities = Collections.emptySet();
private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper
public static Exception excessiveVelEx; // Paper - Velocity warnings public static Exception excessiveVelEx; // Paper - Velocity warnings
static { static {
@ -392,6 +393,7 @@ public final class CraftServer implements Server {
if (this.configuration.getBoolean("settings.use-map-color-cache")) { if (this.configuration.getBoolean("settings.use-map-color-cache")) {
MapPalette.setMapColorCache(new CraftMapColorCache(this.logger)); MapPalette.setMapColorCache(new CraftMapColorCache(this.logger));
} }
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
} }
public boolean getCommandBlockOverride(String command) { public boolean getCommandBlockOverride(String command) {
@ -3036,5 +3038,11 @@ public final class CraftServer implements Server {
public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() {
return mobGoals; return mobGoals;
} }
@Override
public io.papermc.paper.datapack.PaperDatapackManager getDatapackManager() {
return datapackManager;
}
// Paper end // Paper end
} }