From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Fri, 26 May 2023 18:14:44 -0700 Subject: [PATCH] Code Generation Currently includes generated key holder classes for types used in the Registry Modification API diff --git a/build.gradle.kts b/build.gradle.kts index 73aaa8a341565626556327cda6a73f98c318863a..a214483db535890a4b89e35a8c50cfd709df36d4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ plugins { `java-library` `maven-publish` + idea // Paper } java { @@ -61,6 +62,22 @@ dependencies { mockitoAgent("org.mockito:mockito-core:5.14.1") { isTransitive = false } // Paper - configure mockito agent that is needed in newer java versions } +// Paper start +val generatedApiPath: java.nio.file.Path = rootProject.projectDir.toPath().resolve("paper-api-generator/generated") +idea { + module { + generatedSourceDirs.add(generatedApiPath.toFile()) + } +} +sourceSets { + main { + java { + srcDir(generatedApiPath) + } + } +} +// Paper end + configure { publications.create("maven") { from(components["java"]) @@ -143,3 +160,14 @@ tasks.check { dependsOn(scanJar) } // Paper end +// Paper start +val scanJarForOldGeneratedCode = tasks.register("scanJarForOldGeneratedCode", io.papermc.paperweight.tasks.ScanJarForOldGeneratedCode::class) { + mcVersion.set(providers.gradleProperty("mcVersion")) + annotation.set("Lio/papermc/paper/generated/GeneratedFrom;") + jarToScan.set(tasks.jar.flatMap { it.archiveFile }) + classpath.from(configurations.compileClasspath) +} +tasks.check { + dependsOn(scanJarForOldGeneratedCode) +} +// Paper end diff --git a/src/main/java/io/papermc/paper/generated/GeneratedFrom.java b/src/main/java/io/papermc/paper/generated/GeneratedFrom.java new file mode 100644 index 0000000000000000000000000000000000000000..2512dba27edfdccbc4430815b6cba048e3d93484 --- /dev/null +++ b/src/main/java/io/papermc/paper/generated/GeneratedFrom.java @@ -0,0 +1,21 @@ +package io.papermc.paper.generated; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.jetbrains.annotations.ApiStatus; + +/** + * Used to mark classes which are generated from + * a specific version of minecraft. + */ +@ApiStatus.Internal +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface GeneratedFrom { + + String value(); +} diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java new file mode 100644 index 0000000000000000000000000000000000000000..647f6a1ec1f9d3c203b41f90a99bfd415bf67366 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java @@ -0,0 +1,196 @@ +package io.papermc.paper.registry; + +import net.kyori.adventure.key.Keyed; +import org.bukkit.Art; +import org.bukkit.Fluid; +import org.bukkit.GameEvent; +import org.bukkit.JukeboxSong; +import org.bukkit.MusicInstrument; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.attribute.Attribute; +import org.bukkit.block.Biome; +import org.bukkit.block.BlockType; +import org.bukkit.block.banner.PatternType; +import org.bukkit.damage.DamageType; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Cat; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Frog; +import org.bukkit.entity.Villager; +import org.bukkit.entity.Wolf; +import org.bukkit.entity.memory.MemoryKey; +import org.bukkit.generator.structure.Structure; +import org.bukkit.generator.structure.StructureType; +import org.bukkit.inventory.ItemType; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.trim.TrimMaterial; +import org.bukkit.inventory.meta.trim.TrimPattern; +import org.bukkit.map.MapCursor; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionType; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +import static io.papermc.paper.registry.RegistryKeyImpl.create; + +/** + * Identifier for a specific registry. For use with + * {@link TypedKey} and the registry modification API. + *

+ * There are 2 types of registries, identified as "built-in" + * or "data-driven". The former are not changeable by datapacks (which + * doesn't necessarily mean they aren't changeable in the API) and + * are loaded first. "Data-driven" registries are all created by + * reading in data from the vanilla and other datapacks. + * + * @param the value type + */ +@SuppressWarnings("unused") +@NullMarked +public sealed interface RegistryKey extends Keyed permits RegistryKeyImpl { + + /* ******************* * + * Built-in Registries * + * ******************* */ + /** + * Built-in registry for game events + * @see io.papermc.paper.registry.keys.GameEventKeys + */ + RegistryKey GAME_EVENT = create("game_event"); + /** + * Built-in registry for structure types. + * @see io.papermc.paper.registry.keys.StructureTypeKeys + */ + RegistryKey STRUCTURE_TYPE = create("worldgen/structure_type"); + /** + * Built-in registry for potion effect types (mob effects). + * @see io.papermc.paper.registry.keys.MobEffectKeys + */ + RegistryKey MOB_EFFECT = create("mob_effect"); + /** + * @apiNote DO NOT USE + */ + @ApiStatus.Internal + RegistryKey BLOCK = create("block"); + /** + * @apiNote DO NOT USE + */ + @ApiStatus.Internal + RegistryKey ITEM = create("item"); + /** + * Built-in registry for cat variants. + * @see io.papermc.paper.registry.keys.CatVariantKeys + */ + RegistryKey CAT_VARIANT = create("cat_variant"); + /** + * Built-in registry for frog variants. + * @see io.papermc.paper.registry.keys.FrogVariantKeys + */ + RegistryKey FROG_VARIANT = create("frog_variant"); + /** + * Built-in registry for villager professions. + * @see io.papermc.paper.registry.keys.VillagerProfessionKeys + */ + RegistryKey VILLAGER_PROFESSION = create("villager_profession"); + /** + * Built-in registry for villager types. + * @see io.papermc.paper.registry.keys.VillagerTypeKeys + */ + RegistryKey VILLAGER_TYPE = create("villager_type"); + /** + * Built-in registry for map decoration types. + * @see io.papermc.paper.registry.keys.MapDecorationTypeKeys + */ + RegistryKey MAP_DECORATION_TYPE = create("map_decoration_type"); + /** + * Built-in registry for menu types. + * @see io.papermc.paper.registry.keys.MenuTypeKeys + */ + RegistryKey MENU = create("menu"); + /** + * Built-in registry for attributes. + * @see io.papermc.paper.registry.keys.AttributeKeys + */ + RegistryKey ATTRIBUTE = create("attribute"); + /** + * Built-in registry for fluids. + * @see io.papermc.paper.registry.keys.FluidKeys + */ + RegistryKey FLUID = create("fluid"); + /** + * Built-in registry for sound events. + * @see io.papermc.paper.registry.keys.SoundEventKeys + */ + RegistryKey SOUND_EVENT = create("sound_event"); + + + + /* ********************** * + * Data-driven Registries * + * ********************** */ + /** + * Data-driven registry for biomes. + * @see io.papermc.paper.registry.keys.BiomeKeys + */ + RegistryKey BIOME = create("worldgen/biome"); + /** + * Data-driven registry for structures. + * @see io.papermc.paper.registry.keys.StructureKeys + */ + RegistryKey STRUCTURE = create("worldgen/structure"); + /** + * Data-driven registry for trim materials. + * @see io.papermc.paper.registry.keys.TrimMaterialKeys + */ + RegistryKey TRIM_MATERIAL = create("trim_material"); + /** + * Data-driven registry for trim patterns. + * @see io.papermc.paper.registry.keys.TrimPatternKeys + */ + RegistryKey TRIM_PATTERN = create("trim_pattern"); + /** + * Data-driven registry for damage types. + * @see io.papermc.paper.registry.keys.DamageTypeKeys + */ + RegistryKey DAMAGE_TYPE = create("damage_type"); + /** + * Data-driven registry for wolf variants. + * @see io.papermc.paper.registry.keys.WolfVariantKeys + */ + RegistryKey WOLF_VARIANT = create("wolf_variant"); + /** + * Data-driven registry for enchantments. + * @see io.papermc.paper.registry.keys.EnchantmentKeys + */ + RegistryKey ENCHANTMENT = create("enchantment"); + /** + * Data-driven registry for jukebox songs. + * @see io.papermc.paper.registry.keys.JukeboxSongKeys + */ + RegistryKey JUKEBOX_SONG = create("jukebox_song"); + /** + * Data-driven registry for banner patterns. + * @see io.papermc.paper.registry.keys.BannerPatternKeys + */ + RegistryKey BANNER_PATTERN = create("banner_pattern"); + /** + * Data-driven registry for painting variants. + * @see io.papermc.paper.registry.keys.PaintingVariantKeys + */ + RegistryKey PAINTING_VARIANT = create("painting_variant"); + /** + * Data-driven registry for instruments. + * @see io.papermc.paper.registry.keys.InstrumentKeys + */ + RegistryKey INSTRUMENT = create("instrument"); + + + /* ******************* * + * API-only Registries * + * ******************* */ + RegistryKey ENTITY_TYPE = create("entity_type"); + RegistryKey PARTICLE_TYPE = create("particle_type"); + RegistryKey POTION = create("potion"); + RegistryKey> MEMORY_MODULE_TYPE = create("memory_module_type"); +} diff --git a/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..80e3e64f47ac55a4978c9e5b430e2f2d1c871d1b --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java @@ -0,0 +1,26 @@ +package io.papermc.paper.registry; + +import com.google.common.collect.Sets; +import java.util.Set; +import net.kyori.adventure.key.Key; +import org.intellij.lang.annotations.Subst; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +@NullMarked +record RegistryKeyImpl(Key key) implements RegistryKey { + + static final Set> REGISTRY_KEYS = Sets.newIdentityHashSet(); + + static RegistryKey create(@Subst("some_key") final String key) { + final RegistryKey registryKey = createInternal(key); + REGISTRY_KEYS.add(registryKey); + return registryKey; + } + + // creates the key without adding to the internal set of keys + static RegistryKey createInternal(@Subst("some_key") final String key) { + return new RegistryKeyImpl<>(Key.key(Key.MINECRAFT_NAMESPACE, key)); + } + +} diff --git a/src/main/java/io/papermc/paper/registry/TypedKey.java b/src/main/java/io/papermc/paper/registry/TypedKey.java new file mode 100644 index 0000000000000000000000000000000000000000..81bee5224196008662ddda528b5dcb8dd7cb9f21 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/TypedKey.java @@ -0,0 +1,45 @@ +package io.papermc.paper.registry; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.key.Keyed; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Represents a key for a value in a specific registry. + * + * @param the value type for the registry + */ +@ApiStatus.Experimental +@NullMarked +public sealed interface TypedKey extends Key permits TypedKeyImpl { + + /** + * Gets the key for the value in the registry. + * + * @return the value's key + */ + @Override + Key key(); + + /** + * Gets the registry key for the value this key + * represents. + * + * @return the registry key + */ + RegistryKey registryKey(); + + /** + * Create a typed key from a key and a registry key. + * + * @param registryKey the registry this key is for + * @param key the key for the value in the registry + * @param value type + * @return a new key for the value key and registry key + */ + @ApiStatus.Experimental + static TypedKey create(final RegistryKey registryKey, final Key key) { + return new TypedKeyImpl<>(key, registryKey); + } +} diff --git a/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..3e29f7007500582cdc3f84b91f11ebeb58f68bbf --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java @@ -0,0 +1,23 @@ +package io.papermc.paper.registry; + +import net.kyori.adventure.key.Key; +import org.jspecify.annotations.NullMarked; + +@NullMarked +record TypedKeyImpl(Key key, RegistryKey registryKey) implements TypedKey { + // Wrap key methods to make this easier to use + @Override + public String namespace() { + return this.key.namespace(); + } + + @Override + public String value() { + return this.key.value(); + } + + @Override + public String asString() { + return this.key.asString(); + } +} diff --git a/src/main/java/org/bukkit/MinecraftExperimental.java b/src/main/java/org/bukkit/MinecraftExperimental.java index a86b87e4c3332202e40e484c3f9c6562b419c70f..e996a758fc1e4ecfec68641733d69665f30792e8 100644 --- a/src/main/java/org/bukkit/MinecraftExperimental.java +++ b/src/main/java/org/bukkit/MinecraftExperimental.java @@ -47,5 +47,10 @@ public @interface MinecraftExperimental { @ApiStatus.Internal public enum Requires { + // Paper start + TRADE_REBALANCE, + REDSTONE_EXPERIMENTS, + MINECART_IMPROVEMENTS + // Paper end } }