Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

2,672 changes: 2,672 additions & 0 deletions paper-api/src/main/java/io/papermc/paper/loot/LootTables.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.bukkit.inventory.MenuType;
import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.bukkit.inventory.meta.trim.TrimPattern;
import org.bukkit.loot.LootTable;
import org.bukkit.map.MapCursor;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
Expand Down Expand Up @@ -231,6 +232,11 @@ public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
* @see io.papermc.paper.registry.keys.DialogKeys
*/
RegistryKey<Dialog> DIALOG = create("dialog");
/**
* Data-driven registry for loot-tables.
* @see io.papermc.paper.registry.keys.LootTableKeys
*/
RegistryKey<LootTable> LOOT_TABLE = create("loot_table");


/* ******************* *
Expand Down
4 changes: 4 additions & 0 deletions paper-api/src/main/java/org/bukkit/Bukkit.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import java.util.function.Consumer;
import java.util.logging.Logger;
import io.papermc.paper.configuration.ServerConfiguration;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import net.kyori.adventure.text.Component;
import org.bukkit.Warning.WarningState;
import org.bukkit.advancement.Advancement;
Expand Down Expand Up @@ -2575,8 +2577,10 @@ public static <T extends Keyed> Iterable<Tag<T>> getTags(@NotNull String registr
*
* @param key the name of the LootTable
* @return the LootTable, or null if no LootTable is found with that name
* @deprecated loot table is now a proper registry, use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#LOOT_TABLE}
*/
@Nullable
@Deprecated(since = "1.21.11")
public static LootTable getLootTable(@NotNull NamespacedKey key) {
return server.getLootTable(key);
}
Expand Down
2 changes: 2 additions & 0 deletions paper-api/src/main/java/org/bukkit/Registry.java
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ public Iterator<KeyedBossBar> iterator() {
* Default server loot tables.
*
* @see LootTables
* @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#LOOT_TABLE}
*/
@Deprecated(since = "1.21.11", forRemoval = true)
Registry<LootTables> LOOT_TABLES = new SimpleRegistry<>(LootTables.class);
/**
* Server materials.
Expand Down
4 changes: 4 additions & 0 deletions paper-api/src/main/java/org/bukkit/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import java.util.function.Consumer;
import java.util.logging.Logger;
import io.papermc.paper.configuration.ServerConfiguration;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
Expand Down Expand Up @@ -2304,8 +2306,10 @@ default int getAmbientSpawnLimit() {
*
* @param key the name of the LootTable
* @return the LootTable, or null if no LootTable is found with that name
* @deprecated loot table is now a proper registry, use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#LOOT_TABLE}
*/
@Nullable
@Deprecated(since = "1.21.11")
LootTable getLootTable(@NotNull NamespacedKey key);

/**
Expand Down
8 changes: 8 additions & 0 deletions paper-api/src/main/java/org/bukkit/block/BlockType.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
import org.bukkit.block.data.type.WallSign;
import org.bukkit.block.data.type.WallSkull;
import org.bukkit.inventory.ItemType;
import org.bukkit.loot.LootTable;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
Expand Down Expand Up @@ -2744,4 +2745,11 @@ private static <B extends BlockType> B getBlockType(@KeyPattern.Value final Stri
* @return false if this block never has collision, true if it <b>might</b> have collision
*/
boolean hasCollision();

/**
* Gets the associated loot table if defined
*
* @return the loot table associated
*/
@Nullable LootTable getLootTable();
}
22 changes: 21 additions & 1 deletion paper-api/src/main/java/org/bukkit/loot/LootTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

import java.util.Collection;
import java.util.Random;
import net.kyori.adventure.key.Key;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* LootTables are technical files that represent what items should be in
* Loot tables are technical files that represent what items should be in
* naturally generated containers, what items should be dropped when killing a
* mob, or what items can be fished.
* <br>
Expand All @@ -18,6 +20,24 @@
*/
public interface LootTable extends Keyed {

/**
* @deprecated use {@link org.bukkit.Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)},
* and {@link io.papermc.paper.registry.RegistryKey#LOOT_TABLE}. Loot tables can exist without a key.
*/
@Deprecated(since = "1.21.11", forRemoval = true)
@Override
NamespacedKey getKey();

/**
* @deprecated use {@link org.bukkit.Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)},
* and {@link io.papermc.paper.registry.RegistryKey#LOOT_TABLE}. Loot tables can exist without a key.
*/
@Deprecated(since = "1.21.11", forRemoval = true)
@Override
default Key key() {
return Keyed.super.key();
}

/**
* Returns a mutable list of loot generated by this LootTable.
*
Expand Down
3 changes: 3 additions & 0 deletions paper-api/src/main/java/org/bukkit/loot/LootTables.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
* See the
* <a href="https://minecraft.wiki/w/Loot_table#List_of_loot_tables">
* Minecraft Wiki</a> for more information on loot tables.
*
* @deprecated loot table is now a proper registry, see {@link io.papermc.paper.loot.LootTables}
*/
@Deprecated(since = "1.21.11")
public enum LootTables implements Keyed {

// Chests/Dispensers - treasure chests
Expand Down
10 changes: 4 additions & 6 deletions paper-generator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ dependencies {
val gameVersion = providers.gradleProperty("mcVersion")

val rewriteApi = tasks.registerGenerationTask("rewriteApi", true, "api", {
bootstrapTags = true
sourceSet = rootProject.layout.projectDirectory.dir("paper-api")
}) {
description = "Rewrite existing API classes"
Expand All @@ -58,7 +57,6 @@ tasks.register("rewrite") {


val generateApi = tasks.registerGenerationTask("generateApi", false, "api", {
bootstrapTags = true
sourceSet = rootProject.layout.projectDirectory.dir("paper-api")
}) {
description = "Generate new API classes"
Expand Down Expand Up @@ -126,10 +124,10 @@ abstract class GenerationArgumentProvider : CommandLineArgumentProvider {

@get:Input
@get:Optional
abstract val bootstrapTags: Property<Boolean>
abstract val bootstrapResources: Property<Boolean>

init {
bootstrapTags.convention(false)
bootstrapResources.convention(true)
}

override fun asArguments(): Iterable<String> {
Expand All @@ -143,8 +141,8 @@ abstract class GenerationArgumentProvider : CommandLineArgumentProvider {
args.add("--rewrite")
}

if (bootstrapTags.get()) {
args.add("--bootstrap-tags")
if (bootstrapResources.get()) {
args.add("--bootstrap-resources")
}
return args.toList()
}
Expand Down
29 changes: 20 additions & 9 deletions paper-generator/src/main/java/io/papermc/generator/Main.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.papermc.generator;

import com.mojang.logging.LogUtils;
import io.papermc.generator.registry.RegistryEntries;
import io.papermc.generator.rewriter.registration.PaperPatternSourceSetRewriter;
import io.papermc.generator.rewriter.registration.PatternSourceSetRewriter;
import io.papermc.generator.types.SourceGenerator;
Expand All @@ -15,16 +16,17 @@
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.minecraft.SharedConstants;
import net.minecraft.util.Util;
import net.minecraft.commands.Commands;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.LayeredRegistryAccess;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.RegistryDataLoader;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.RegistryDataLoader;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.Bootstrap;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.RegistryLayer;
Expand All @@ -37,10 +39,12 @@
import net.minecraft.server.permissions.LevelBasedPermissionSet;
import net.minecraft.tags.TagKey;
import net.minecraft.tags.TagLoader;
import net.minecraft.util.Util;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.level.DataPackConfig;
import net.minecraft.world.level.WorldDataConfiguration;
import net.minecraft.world.level.storage.loot.LootDataType;
import org.apache.commons.io.file.PathUtils;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.slf4j.Logger;
Expand All @@ -64,15 +68,15 @@ public class Main implements Callable<Integer> {
@CommandLine.Option(names = {"--side"}, required = true)
String side;

@CommandLine.Option(names = {"--bootstrap-tags"})
boolean tagBootstrap;
@CommandLine.Option(names = {"--bootstrap-resources"})
boolean loadResources;

private static final Logger LOGGER = LogUtils.getLogger();

public static RegistryAccess.@MonotonicNonNull Frozen REGISTRY_ACCESS;
public static HolderLookup.Provider REGISTRIES;
public static @MonotonicNonNull Map<TagKey<?>, String> EXPERIMENTAL_TAGS;

public static CompletableFuture<Void> bootStrap(boolean withTags) {
public static CompletableFuture<Void> bootStrap(boolean withResources) {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
Bootstrap.validate();
Expand All @@ -90,8 +94,8 @@ public static CompletableFuture<Void> bootStrap(boolean withTags) {
List<HolderLookup.RegistryLookup<?>> staticAndWorldgenLookups = Stream.concat(worldGenLayer.stream(), frozenWorldgenRegistries.listRegistries()).toList();
RegistryAccess.Frozen dimensionRegistries = RegistryDataLoader.load(resourceManager, staticAndWorldgenLookups, RegistryDataLoader.DIMENSION_REGISTRIES);
layers = layers.replaceFrom(RegistryLayer.DIMENSIONS, dimensionRegistries);
REGISTRY_ACCESS = layers.compositeAccess().freeze();
if (withTags) {
REGISTRIES = layers.compositeAccess().freeze();
if (withResources) {
return ReloadableServerResources.loadResources(
resourceManager,
layers,
Expand All @@ -107,6 +111,13 @@ public static CompletableFuture<Void> bootStrap(boolean withTags) {
}
}).thenAccept(resources -> {
resources.updateStaticRegistryTags();
Set<ResourceKey<? extends Registry<?>>> reloadableRegistries = LootDataType.values().map(LootDataType::registryKey).collect(Collectors.toSet());
/*REGISTRIES = HolderLookup.Provider.create(RegistryEntries.stream().map(entry -> {
return (reloadableRegistries.contains(entry.registryKey()) ? resources.fullRegistries().lookup() : REGISTRIES).lookupOrThrow(entry.registryKey());
}));*/
REGISTRIES = HolderLookup.Provider.create(RegistryEntries.streamLegacy().map(key -> {
return (reloadableRegistries.contains(key) ? resources.fullRegistries().lookup() : REGISTRIES).lookupOrThrow(key);
}));
EXPERIMENTAL_TAGS = ExperimentalCollector.collectTags(resourceManager);
});
} else {
Expand All @@ -117,7 +128,7 @@ public static CompletableFuture<Void> bootStrap(boolean withTags) {

@Override
public Integer call() {
bootStrap(this.tagBootstrap).join();
bootStrap(this.loadResources).join();

try {
if (this.isRewrite) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import io.papermc.paper.datacomponent.item.SwingAnimation;
import io.papermc.paper.datacomponent.item.consumable.ItemUseAnimation;
import io.papermc.paper.dialog.Dialog;
import io.papermc.paper.loot.LootTables;
import io.papermc.paper.world.WeatheringCopperState;
import io.papermc.typewriter.preset.EnumCloneRewriter;
import io.papermc.typewriter.preset.model.EnumValue;
Expand Down Expand Up @@ -223,6 +224,7 @@ protected String rewriteFieldType(Holder.Reference<net.minecraft.world.level.gam
.register("PigVariant", Pig.Variant.class, new RegistryFieldRewriter<>(Registries.PIG_VARIANT, "getVariant"))
.register("ZombieNautilusVariant", ZombieNautilus.Variant.class, new RegistryFieldRewriter<>(Registries.ZOMBIE_NAUTILUS_VARIANT, "getVariant"))
.register("Dialog", Dialog.class, new RegistryFieldRewriter<>(Registries.DIALOG, "getDialog"))
.register("LootTables", LootTables.class, new RegistryFieldRewriter<>(Registries.LOOT_TABLE, "getTable"))
.register("MemoryKey", MemoryKey.class, new MemoryKeyRewriter())
// .register("ItemType", org.bukkit.inventory.ItemType.class, new io.papermc.generator.rewriter.types.simple.ItemTypeRewriter()) - disable for now, lynx want the generic type
.register("BlockType", BlockType.class, new BlockTypeRewriter())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.papermc.paper.datacomponent.DataComponentType;
import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.dialog.Dialog;
import io.papermc.paper.loot.LootTables;
import io.papermc.paper.registry.data.BannerPatternRegistryEntry;
import io.papermc.paper.registry.data.CatTypeRegistryEntry;
import io.papermc.paper.registry.data.ChickenVariantRegistryEntry;
Expand Down Expand Up @@ -32,6 +33,7 @@
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.minecraft.core.Registry;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.particles.ParticleTypes;
Expand All @@ -43,12 +45,12 @@
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.animal.feline.CatVariants;
import net.minecraft.world.entity.animal.chicken.ChickenVariants;
import net.minecraft.world.entity.animal.cow.CowVariants;
import net.minecraft.world.entity.animal.pig.PigVariants;
import net.minecraft.world.entity.animal.nautilus.ZombieNautilusVariants;
import net.minecraft.world.entity.animal.feline.CatVariants;
import net.minecraft.world.entity.animal.frog.FrogVariants;
import net.minecraft.world.entity.animal.nautilus.ZombieNautilusVariants;
import net.minecraft.world.entity.animal.pig.PigVariants;
import net.minecraft.world.entity.animal.wolf.WolfSoundVariants;
import net.minecraft.world.entity.animal.wolf.WolfVariants;
import net.minecraft.world.entity.decoration.painting.PaintingVariants;
Expand All @@ -68,6 +70,7 @@
import net.minecraft.world.level.levelgen.structure.BuiltinStructures;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.saveddata.maps.MapDecorationTypes;
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
import org.bukkit.Art;
import org.bukkit.Fluid;
import org.bukkit.GameEvent;
Expand Down Expand Up @@ -99,6 +102,7 @@
import org.bukkit.inventory.MenuType;
import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.bukkit.inventory.meta.trim.TrimPattern;
import org.bukkit.loot.LootTable;
import org.bukkit.map.MapCursor;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
Expand Down Expand Up @@ -192,7 +196,8 @@ private static <T> RegistryEntry<T> inconsistentEntry(ResourceKey<? extends Regi
entry(Registries.COW_VARIANT, CowVariants.class, Cow.Variant.class).writableApiRegistryBuilder(CowVariantRegistryEntry.Builder.class, "PaperCowVariantRegistryEntry.PaperBuilder"),
entry(Registries.PIG_VARIANT, PigVariants.class, Pig.Variant.class).writableApiRegistryBuilder(PigVariantRegistryEntry.Builder.class, "PaperPigVariantRegistryEntry.PaperBuilder"),
entry(Registries.ZOMBIE_NAUTILUS_VARIANT, ZombieNautilusVariants.class, ZombieNautilus.Variant.class).writableApiRegistryBuilder(ZombieNautilusVariantRegistryEntry.Builder.class, "PaperZombieNautilusVariantRegistryEntry.PaperBuilder"),
entry(Registries.DIALOG, Dialogs.class, Dialog.class, "Paper").allowDirect().writableApiRegistryBuilder(DialogRegistryEntry.Builder.class, "PaperDialogRegistryEntry.PaperBuilder")
entry(Registries.DIALOG, Dialogs.class, Dialog.class, "Paper").allowDirect().writableApiRegistryBuilder(DialogRegistryEntry.Builder.class, "PaperDialogRegistryEntry.PaperBuilder"),
entry(Registries.LOOT_TABLE, BuiltInLootTables.class, LootTable.class).allowDirect().preload(LootTables.class)
);

public static final List<RegistryEntry<?>> API_ONLY = List.of(
Expand All @@ -217,6 +222,19 @@ public static <T> RegistryEntry<T> byRegistryKey(ResourceKey<? extends Registry<
}

// real registries
public static Stream<RegistryEntry<?>> stream() {
return Stream.concat(RegistryEntries.BUILT_IN.stream(), RegistryEntries.DATA_DRIVEN.stream());
}

@Deprecated(forRemoval = true)
public static Stream<ResourceKey<? extends Registry<?>>> streamLegacy() { // todo remove once all the api only registry are migrated
Stream<ResourceKey<? extends Registry<?>>> injectedKeys = Stream.of( // todo remove once stats is a proper registry
Registries.STAT_TYPE,
Registries.CUSTOM_STAT
);
return Stream.concat(Stream.concat(stream(), RegistryEntries.API_ONLY.stream()).map(RegistryEntry::registryKey), injectedKeys);
}

public static void forEach(Consumer<RegistryEntry<?>> callback) {
forEach(callback, RegistryEntries.BUILT_IN, RegistryEntries.DATA_DRIVEN);
}
Expand Down
Loading