Add FeatureFlag API

This commit is contained in:
Jake Potrebic
2024-05-29 19:50:21 -07:00
parent e29ea45639
commit 90bc5f1e0b
15 changed files with 197 additions and 67 deletions

View File

@@ -0,0 +1,17 @@
package io.papermc.paper.world.flag;
import java.util.Set;
import net.minecraft.world.flag.FeatureElement;
import org.bukkit.FeatureFlag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.Unmodifiable;
public interface PaperFeatureDependent extends FeatureDependant {
<M extends FeatureElement> M getHandle();
@Override
default @Unmodifiable @NonNull Set<FeatureFlag> requiredFeatures() {
return PaperFeatureFlagProviderImpl.fromNms(this.getHandle().requiredFeatures());
}
}

View File

@@ -0,0 +1,54 @@
package io.papermc.paper.world.flag;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.world.flag.FeatureElement;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.FeatureFlag;
import org.bukkit.craftbukkit.entity.CraftEntityType;
import org.bukkit.craftbukkit.entity.CraftEntityTypes;
import org.bukkit.craftbukkit.potion.CraftPotionType;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.entity.EntityType;
import org.bukkit.potion.PotionType;
public class PaperFeatureFlagProviderImpl implements FeatureFlagProvider {
public static final BiMap<FeatureFlag, net.minecraft.world.flag.FeatureFlag> FLAGS = ImmutableBiMap.of(
FeatureFlag.VANILLA, FeatureFlags.VANILLA,
FeatureFlag.TRADE_REBALANCE, FeatureFlags.TRADE_REBALANCE,
FeatureFlag.MINECART_IMPROVEMENTS, FeatureFlags.MINECART_IMPROVEMENTS,
FeatureFlag.REDSTONE_EXPERIMENTS, FeatureFlags.REDSTONE_EXPERIMENTS
);
@Override
public Set<FeatureFlag> requiredFeatures(final FeatureDependant dependant) {
final FeatureFlagSet requiredFeatures = getFeatureElement(dependant).requiredFeatures();
return fromNms(requiredFeatures);
}
public static Set<FeatureFlag> fromNms(final FeatureFlagSet flagSet) {
final Set<FeatureFlag> flags = new HashSet<>();
for (final net.minecraft.world.flag.FeatureFlag nmsFlag : FeatureFlags.REGISTRY.names.values()) {
if (flagSet.contains(nmsFlag)) {
flags.add(FLAGS.inverse().get(nmsFlag));
}
}
return Collections.unmodifiableSet(flags);
}
static FeatureElement getFeatureElement(final FeatureDependant dependant) {
if (dependant instanceof final EntityType entityType) {
// TODO remove when EntityType is server-backed
return CraftEntityType.bukkitToMinecraft(entityType);
} else if (dependant instanceof final PotionType potionType) {
return CraftPotionType.bukkitToMinecraft(potionType);
} else {
throw new IllegalArgumentException(dependant + " is not a valid feature dependant");
}
}
}

View File

@@ -1,51 +0,0 @@
package org.bukkit.craftbukkit;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.FeatureFlag;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.jetbrains.annotations.NotNull;
public class CraftFeatureFlag implements FeatureFlag {
private final NamespacedKey namespacedKey;
private final net.minecraft.world.flag.FeatureFlag featureFlag;
public CraftFeatureFlag(ResourceLocation minecraftKey, net.minecraft.world.flag.FeatureFlag featureFlag) {
this.namespacedKey = CraftNamespacedKey.fromMinecraft(minecraftKey);
this.featureFlag = featureFlag;
}
public net.minecraft.world.flag.FeatureFlag getHandle() {
return this.featureFlag;
}
@NotNull
@Override
public NamespacedKey getKey() {
return this.namespacedKey;
}
@Override
public String toString() {
return "CraftFeatureFlag{key=" + this.getKey() + ",keyUniverse=" + this.getHandle().universe.toString() + "}";
}
public static Set<CraftFeatureFlag> getFromNMS(FeatureFlagSet featureFlagSet) {
Set<CraftFeatureFlag> set = new HashSet<>();
FeatureFlags.REGISTRY.names.forEach((minecraftkey, featureflag) -> {
if (featureFlagSet.contains(featureflag)) {
set.add(new CraftFeatureFlag(minecraftkey, featureflag));
}
});
return set;
}
public static CraftFeatureFlag getFromNMS(NamespacedKey namespacedKey) {
return FeatureFlags.REGISTRY.names.entrySet().stream().filter(entry -> CraftNamespacedKey.fromMinecraft(entry.getKey()).equals(namespacedKey)).findFirst().map(entry -> new CraftFeatureFlag(entry.getKey(), entry.getValue())).orElse(null);
}
}

View File

@@ -564,4 +564,11 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
return !this.getHandle().noCollision(aabb);
}
// Paper end
// Paper start - feature flag API
@Override
public java.util.Set<org.bukkit.FeatureFlag> getFeatureFlags() {
return io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl.fromNms(this.getHandle().enabledFeatures());
}
// Paper end - feature flag API
}

View File

@@ -2359,10 +2359,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return this.persistentDataContainer;
}
@Override
public Set<FeatureFlag> getFeatureFlags() {
return CraftFeatureFlag.getFromNMS(this.getHandle().enabledFeatures()).stream().map(FeatureFlag.class::cast).collect(Collectors.toUnmodifiableSet());
}
// Paper - replace feature flag API
public void storeBukkitValues(CompoundTag c) {
if (!this.persistentDataContainer.isEmpty()) {

View File

@@ -33,7 +33,7 @@ import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.inventory.ItemType;
import org.jetbrains.annotations.NotNull;
public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>, Handleable<Block> {
public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>, Handleable<Block>, io.papermc.paper.world.flag.PaperFeatureDependent { // Paper - feature flag API
private final NamespacedKey key;
private final Block block;

View File

@@ -17,6 +17,7 @@ public class CraftWorldInfo implements WorldInfo {
private final long seed;
private final int minHeight;
private final int maxHeight;
private final net.minecraft.world.flag.FeatureFlagSet enabledFeatures; // Paper - feature flag API
// Paper start
private final net.minecraft.world.level.chunk.ChunkGenerator vanillaChunkGenerator;
private final net.minecraft.core.RegistryAccess.Frozen registryAccess;
@@ -31,6 +32,7 @@ public class CraftWorldInfo implements WorldInfo {
this.seed = ((PrimaryLevelData) worldDataServer).worldGenOptions().seed();
this.minHeight = dimensionManager.minY();
this.maxHeight = dimensionManager.minY() + dimensionManager.height();
this.enabledFeatures = worldDataServer.enabledFeatures(); // Paper - feature flag API
}
@Override
@@ -92,4 +94,11 @@ public class CraftWorldInfo implements WorldInfo {
};
}
// Paper end
// Paper start - feature flag API
@Override
public java.util.Set<org.bukkit.FeatureFlag> getFeatureFlags() {
return io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl.fromNms(this.enabledFeatures);
}
// Paper end - feature flag API
}

View File

@@ -36,7 +36,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Handleable<Item> {
public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Handleable<Item>, io.papermc.paper.world.flag.PaperFeatureDependent { // Paper - feature flag API
private final NamespacedKey key;
private final Item item;

View File

@@ -18,7 +18,7 @@ import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.MenuType;
public class CraftMenuType<V extends InventoryView> implements MenuType.Typed<V>, Handleable<net.minecraft.world.inventory.MenuType<?>> {
public class CraftMenuType<V extends InventoryView> implements MenuType.Typed<V>, Handleable<net.minecraft.world.inventory.MenuType<?>>, io.papermc.paper.world.flag.PaperFeatureDependent { // Paper - make FeatureDependant
private final NamespacedKey key;
private final net.minecraft.world.inventory.MenuType<?> handle;

View File

@@ -11,7 +11,7 @@ import net.minecraft.util.InclusiveRange;
import org.bukkit.Bukkit;
import org.bukkit.FeatureFlag;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftFeatureFlag;
// import org.bukkit.craftbukkit.CraftFeatureFlag; // Paper - replace feature flag API
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.packs.DataPack;
@@ -98,7 +98,7 @@ public class CraftDataPack implements DataPack {
@Override
public Set<FeatureFlag> getRequestedFeatures() {
return CraftFeatureFlag.getFromNMS(this.getHandle().getRequestedFeatures()).stream().map(FeatureFlag.class::cast).collect(Collectors.toUnmodifiableSet());
return io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl.fromNms(this.getHandle().getRequestedFeatures()); // Paper - replace feature flag API
}
@Override

View File

@@ -13,7 +13,7 @@ import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionEffectTypeCategory;
import org.jetbrains.annotations.NotNull;
public class CraftPotionEffectType extends PotionEffectType implements Handleable<MobEffect> {
public class CraftPotionEffectType extends PotionEffectType implements Handleable<MobEffect>, io.papermc.paper.world.flag.PaperFeatureDependent { // Paper - feature flag API
public static PotionEffectType minecraftHolderToBukkit(Holder<MobEffect> minecraft) {
return CraftPotionEffectType.minecraftToBukkit(minecraft.value());

View File

@@ -48,7 +48,7 @@ import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.CraftFeatureFlag;
// import org.bukkit.craftbukkit.CraftFeatureFlag; // Paper
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.block.CraftBiome;
@@ -456,11 +456,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
return attribute.getTranslationKey();
}
@Override
public FeatureFlag getFeatureFlag(NamespacedKey namespacedKey) {
Preconditions.checkArgument(namespacedKey != null, "NamespaceKey cannot be null");
return CraftFeatureFlag.getFromNMS(namespacedKey);
}
// Paper - replace feature flag API
@Override
public PotionType.InternalPotionData getInternalPotionData(NamespacedKey namespacedKey) {