From 61d6ec49736d2004c5e70ce856f6d3471eaa954b Mon Sep 17 00:00:00 2001 From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> Date: Mon, 31 Mar 2025 22:41:01 +0200 Subject: [PATCH] remove paper-api dependency Remove the needs to compile paper-api while running rewriters. Allow to rewrite test source set for implementation (rewriteImplTest). Some other changes: - item type generics is now supported - generate CraftItemMetas#getItemMetaData - registry test data are now generated to generalize registry handling - generate Pose and Attribute (trial) - print removed fields from Tag while updating the game --- .../paper/registry/keys/DialogKeys.java | 2 +- .../registry/keys/tags/DialogTagKeys.java | 5 +- .../block/property/BlockProperties.java.dump | 133 ++++++ .../java/io/papermc/paper/dialog/Dialog.java | 2 +- .../src/main/java/org/bukkit/Material.java | 1 - paper-api/src/main/java/org/bukkit/Tag.java | 16 +- .../java/org/bukkit/attribute/Attribute.java | 245 ++++++----- .../java/org/bukkit/entity/EntityType.java | 2 - .../src/main/java/org/bukkit/entity/Pose.java | 1 + .../java/org/bukkit/inventory/ItemType.java | 5 +- paper-generator/.editorconfig | 3 + paper-generator/build.gradle.kts | 83 ++-- .../java/io/papermc/generator/Generators.java | 3 +- .../main/java/io/papermc/generator/Main.java | 33 +- .../java/io/papermc/generator/Rewriters.java | 269 ++++++------ .../registry/RegistryBootstrapper.java | 10 +- .../generator/registry/RegistryEntries.java | 217 ++++------ .../generator/registry/RegistryEntry.java | 169 ++------ .../registry/RegistryIdentifiable.java | 11 + .../generator/registry/RegistryIntern.java | 22 + .../papermc/generator/resources/DataFile.java | 182 ++++++++ .../generator/resources/DataFileLoader.java | 218 ++++++++++ .../generator/resources/DataFiles.java | 44 ++ .../resources/FlattenSliceResult.java | 6 + .../resources/ParameterizedClass.java | 99 +++++ .../generator/resources/SliceResult.java | 19 + .../generator/resources/Transmuter.java | 11 + .../resources/data/EntityClassData.java | 28 ++ .../resources/data/EntityTypeData.java | 31 ++ .../resources/data/ItemMetaData.java | 15 + .../resources/data/RegistryData.java | 160 +++++++ .../generator/resources/package-info.java | 4 + .../resources/predicate/BlockPredicate.java | 146 +++++++ .../predicate/BlockPropertyPredicate.java | 112 +++++ .../resources/predicate/ItemPredicate.java | 112 +++++ .../PaperPatternSourceSetRewriter.java | 4 +- .../PatternSourceSetRewriter.java | 10 +- .../rewriter/registration/RewriterHolder.java | 9 +- .../generator/rewriter/types/Types.java | 141 ++++++- .../types/registry/EnumRegistryRewriter.java | 37 +- .../types/registry/FeatureFlagRewriter.java | 22 +- .../registry/PaperFeatureFlagMapping.java | 6 +- .../registry/PaperRegistriesRewriter.java | 93 ++-- .../RegistriesArgumentProviderRewriter.java | 37 ++ .../RegistryConversionTestRewriter.java | 22 + .../registry/RegistryEventsRewriter.java | 26 +- .../types/registry/RegistryFieldRewriter.java | 41 +- .../types/registry/RegistryTagRewriter.java | 43 +- .../rewriter/types/registry/TagRewriter.java | 90 +++- .../rewriter/types/registry/package-info.java | 4 + .../types/simple/BlockPropertiesRewriter.java | 141 +++++++ .../types/simple/BlockTypeRewriter.java | 11 +- .../types/simple/CraftBlockDataMapping.java | 6 +- .../types/simple/CraftItemMetasRewriter.java | 92 ++++ .../types/simple/CraftPotionUtilRewriter.java | 7 +- .../types/simple/EntityTypeRewriter.java | 161 +------ .../types/simple/ItemTypeRewriter.java | 27 +- .../types/simple/MapPaletteRewriter.java | 4 +- .../types/simple/MaterialRewriter.java | 41 +- .../types/simple/MemoryKeyRewriter.java | 20 +- .../types/simple/StatisticRewriter.java | 66 +-- .../types/simple/trial/AttributeRewriter.java | 80 ++++ .../types/simple/trial/PoseRewriter.java | 14 +- .../trial/VillagerProfessionRewriter.java | 41 +- .../generator/rewriter/utils/Annotations.java | 25 +- .../generator/tasks/PrepareInputFiles.java | 46 ++ .../ScanOldGeneratedSourceCode.java | 15 +- .../types/OverriddenClassGenerator.java | 21 +- .../generator/types/SimpleEnumGenerator.java | 8 +- .../io/papermc/generator/types/Types.java | 56 ++- .../CraftBlockDataBootstrapper.java | 9 +- .../CraftBlockDataGenerator.java | 61 +-- .../property/EnumPropertyWriter.java | 13 +- .../property/IntegerPropertyWriter.java | 4 +- .../property/PropertyWriter.java | 19 +- .../property/appender/AppenderBase.java | 2 +- .../property/appender/EnumValuesAppender.java | 14 +- .../property/appender/PropertyAppender.java | 5 +- .../property/appender/PropertyAppenders.java | 20 +- .../property/converter/Converter.java | 5 +- .../property/converter/ConverterBase.java | 3 +- .../property/converter/NoteConverter.java | 9 +- .../property/converter/RotationConverter.java | 12 +- .../property/holder/DataPropertyMaker.java | 3 +- .../property/holder/DataPropertyWriter.java | 29 +- .../holder/DataPropertyWriterBase.java | 5 +- .../holder/VirtualDataPropertyWriter.java | 26 +- .../property/holder/VirtualField.java | 13 +- .../holder/appender/ArrayAppender.java | 5 +- .../holder/appender/DataAppender.java | 2 +- .../holder/appender/ListAppender.java | 7 +- .../property/holder/appender/MapAppender.java | 73 ++-- .../papermc/generator/types/goal/GoalKey.java | 7 + .../types/goal/MobGoalGenerator.java | 26 +- .../generator/types/goal/MobGoalNames.java | 292 ++----------- .../types/registry/GeneratedKeyType.java | 27 +- .../types/registry/GeneratedTagKeyType.java | 30 +- .../papermc/generator/utils/Annotations.java | 10 +- .../papermc/generator/utils/BasePackage.java | 33 ++ .../generator/utils/BlockEntityMapping.java | 2 - .../generator/utils/BlockStateMapping.java | 378 +++++------------ .../papermc/generator/utils/ClassHelper.java | 25 -- .../generator/utils/CommonVariable.java | 3 - .../papermc/generator/utils/Formatting.java | 48 +-- .../io/papermc/generator/utils/Javadocs.java | 11 +- .../generator/utils/NamingManager.java | 14 +- .../papermc/generator/utils/SourceCodecs.java | 140 ++++++ .../experimental/ExperimentalCollector.java | 4 +- .../utils/experimental/FlagHolders.java | 12 - .../utils/experimental/SingleFlagHolder.java | 10 +- .../papermc/generator/utils/package-info.java | 4 + .../data/block_state/ambiguous_names.json | 15 + .../data/block_state/enum_property_types.json | 29 ++ .../data/block_state/predicates.json | 135 ++++++ .../resources/data/entity_class_names.json | 127 ++++++ .../src/main/resources/data/entity_types.json | 399 ++++++++++++++++++ .../main/resources/data/item_meta/bridge.json | 106 +++++ .../resources/data/item_meta/predicates.json | 103 +++++ .../resources/data/registry/built_in.json | 136 ++++++ .../resources/data/registry/data_driven.json | 189 +++++++++ .../generator/BlockStatePropertyTest.java | 59 +-- .../io/papermc/generator/BootstrapTest.java | 8 + .../io/papermc/generator/DataFileTest.java | 31 ++ .../generator/MobGoalConverterTest.java | 35 -- .../generator/RegistryMigrationTest.java | 50 --- .../papermc/generator/RoundtripCodecTest.java | 253 +++++++++++ paper-generator/wideners.at | 1 - paper-server/build.gradle.kts | 8 - .../craftbukkit/block/impl/CraftButton.java | 8 +- .../impl/CraftCalibratedSculkSensor.java | 7 +- .../block/impl/CraftDetectorRail.java | 13 +- .../craftbukkit/block/impl/CraftDoor.java | 7 +- .../block/impl/CraftGrindstone.java | 8 +- .../craftbukkit/block/impl/CraftLever.java | 8 +- .../block/impl/CraftMossyCarpet.java | 8 +- .../block/impl/CraftPistonHead.java | 7 +- .../block/impl/CraftPitcherCrop.java | 7 +- .../block/impl/CraftPoweredRail.java | 13 +- .../block/impl/CraftSmallDripleaf.java | 7 +- .../block/impl/CraftWeatheringCopperDoor.java | 7 +- .../paper/entity/ai/MobGoalHelper.java | 154 +++---- .../craftbukkit/inventory/CraftItemMetas.java | 197 +++++---- .../src/test/java/org/bukkit/SoundTest.java | 24 -- .../craftbukkit/inventory/ItemMetaTest.java | 64 +-- .../registry/RegistryConversionTest.java | 28 +- .../provider/RegistriesArgumentProvider.java | 73 ++-- 146 files changed, 5244 insertions(+), 2381 deletions(-) create mode 100644 paper-api/src/main/java/io/papermc/paper/block/property/BlockProperties.java.dump create mode 100644 paper-generator/src/main/java/io/papermc/generator/registry/RegistryIdentifiable.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/registry/RegistryIntern.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/DataFile.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/DataFileLoader.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/DataFiles.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/FlattenSliceResult.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/ParameterizedClass.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/SliceResult.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/Transmuter.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/data/EntityClassData.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/data/EntityTypeData.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/data/ItemMetaData.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/data/RegistryData.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/package-info.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/predicate/BlockPredicate.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/predicate/BlockPropertyPredicate.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/resources/predicate/ItemPredicate.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistriesArgumentProviderRewriter.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryConversionTestRewriter.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/package-info.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/BlockPropertiesRewriter.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftItemMetasRewriter.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/AttributeRewriter.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/tasks/PrepareInputFiles.java rename paper-generator/src/main/java/io/papermc/generator/{rewriter/utils => tasks}/ScanOldGeneratedSourceCode.java (88%) create mode 100644 paper-generator/src/main/java/io/papermc/generator/types/goal/GoalKey.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/utils/BasePackage.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/utils/SourceCodecs.java create mode 100644 paper-generator/src/main/java/io/papermc/generator/utils/package-info.java create mode 100644 paper-generator/src/main/resources/data/block_state/ambiguous_names.json create mode 100644 paper-generator/src/main/resources/data/block_state/enum_property_types.json create mode 100644 paper-generator/src/main/resources/data/block_state/predicates.json create mode 100644 paper-generator/src/main/resources/data/entity_class_names.json create mode 100644 paper-generator/src/main/resources/data/entity_types.json create mode 100644 paper-generator/src/main/resources/data/item_meta/bridge.json create mode 100644 paper-generator/src/main/resources/data/item_meta/predicates.json create mode 100644 paper-generator/src/main/resources/data/registry/built_in.json create mode 100644 paper-generator/src/main/resources/data/registry/data_driven.json create mode 100644 paper-generator/src/test/java/io/papermc/generator/BootstrapTest.java create mode 100644 paper-generator/src/test/java/io/papermc/generator/DataFileTest.java delete mode 100644 paper-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java delete mode 100644 paper-generator/src/test/java/io/papermc/generator/RegistryMigrationTest.java create mode 100644 paper-generator/src/test/java/io/papermc/generator/RoundtripCodecTest.java delete mode 100644 paper-server/src/test/java/org/bukkit/SoundTest.java diff --git a/paper-api/src/generated/java/io/papermc/paper/registry/keys/DialogKeys.java b/paper-api/src/generated/java/io/papermc/paper/registry/keys/DialogKeys.java index ab57b44fb7..9c2203b5b5 100644 --- a/paper-api/src/generated/java/io/papermc/paper/registry/keys/DialogKeys.java +++ b/paper-api/src/generated/java/io/papermc/paper/registry/keys/DialogKeys.java @@ -23,7 +23,7 @@ import org.jspecify.annotations.NullMarked; "SpellCheckingInspection" }) @NullMarked -@GeneratedFrom("1.21.7-rc2") +@GeneratedFrom("1.21.7") public final class DialogKeys { /** * {@code minecraft:custom_options} diff --git a/paper-api/src/generated/java/io/papermc/paper/registry/keys/tags/DialogTagKeys.java b/paper-api/src/generated/java/io/papermc/paper/registry/keys/tags/DialogTagKeys.java index 64d41d763f..55ca6a44ab 100644 --- a/paper-api/src/generated/java/io/papermc/paper/registry/keys/tags/DialogTagKeys.java +++ b/paper-api/src/generated/java/io/papermc/paper/registry/keys/tags/DialogTagKeys.java @@ -7,7 +7,6 @@ import io.papermc.paper.generated.GeneratedFrom; import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.registry.tag.TagKey; import net.kyori.adventure.key.Key; -import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; /** @@ -24,8 +23,7 @@ import org.jspecify.annotations.NullMarked; "SpellCheckingInspection" }) @NullMarked -@GeneratedFrom("1.21.7-rc2") -@ApiStatus.Experimental +@GeneratedFrom("1.21.7") public final class DialogTagKeys { /** * {@code #minecraft:pause_screen_additions} @@ -50,7 +48,6 @@ public final class DialogTagKeys { * @param key the tag key's key * @return a new tag key */ - @ApiStatus.Experimental public static TagKey create(final Key key) { return TagKey.create(RegistryKey.DIALOG, key); } diff --git a/paper-api/src/main/java/io/papermc/paper/block/property/BlockProperties.java.dump b/paper-api/src/main/java/io/papermc/paper/block/property/BlockProperties.java.dump new file mode 100644 index 0000000000..caaf840ce4 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/block/property/BlockProperties.java.dump @@ -0,0 +1,133 @@ +Dump of the rewriters that apply to the file: io/papermc/paper/block/property/BlockProperties.java + +Configuration: +Indent unit: " " (4 char) +Indent char: ' ' (U+0020) + +Name: BlockProperties +Start comment marker: Start generate - BlockProperties +End comment marker: End generate - BlockProperties + +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + public static final BooleanBlockProperty ATTACHED = bool("attached"); + public static final BooleanBlockProperty BERRIES = bool("berries"); + public static final BooleanBlockProperty BLOOM = bool("bloom"); + public static final BooleanBlockProperty BOTTOM = bool("bottom"); + public static final BooleanBlockProperty CAN_SUMMON = bool("can_summon"); + public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_0_OCCUPIED = bool("slot_0_occupied"); + public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_1_OCCUPIED = bool("slot_1_occupied"); + public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_2_OCCUPIED = bool("slot_2_occupied"); + public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_3_OCCUPIED = bool("slot_3_occupied"); + public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_4_OCCUPIED = bool("slot_4_occupied"); + public static final BooleanBlockProperty CHISELED_BOOKSHELF_SLOT_5_OCCUPIED = bool("slot_5_occupied"); + public static final BooleanBlockProperty CONDITIONAL = bool("conditional"); + public static final BooleanBlockProperty CRACKED = bool("cracked"); + public static final BooleanBlockProperty CRAFTING = bool("crafting"); + public static final BooleanBlockProperty DISARMED = bool("disarmed"); + public static final BooleanBlockProperty DOWN = bool("down"); + public static final BooleanBlockProperty DRAG = bool("drag"); + public static final BooleanBlockProperty EAST = bool("east"); + public static final BooleanBlockProperty ENABLED = bool("enabled"); + public static final BooleanBlockProperty EXTENDED = bool("extended"); + public static final BooleanBlockProperty EYE = bool("eye"); + public static final BooleanBlockProperty FALLING = bool("falling"); + public static final BooleanBlockProperty HANGING = bool("hanging"); + public static final BooleanBlockProperty HAS_BOOK = bool("has_book"); + public static final BooleanBlockProperty HAS_BOTTLE_0 = bool("has_bottle_0"); + public static final BooleanBlockProperty HAS_BOTTLE_1 = bool("has_bottle_1"); + public static final BooleanBlockProperty HAS_BOTTLE_2 = bool("has_bottle_2"); + public static final BooleanBlockProperty HAS_RECORD = bool("has_record"); + public static final BooleanBlockProperty INVERTED = bool("inverted"); + public static final BooleanBlockProperty IN_WALL = bool("in_wall"); + public static final BooleanBlockProperty LIT = bool("lit"); + public static final BooleanBlockProperty LOCKED = bool("locked"); + public static final BooleanBlockProperty MAP = bool("map"); + public static final BooleanBlockProperty NATURAL = bool("natural"); + public static final BooleanBlockProperty NORTH = bool("north"); + public static final BooleanBlockProperty OCCUPIED = bool("occupied"); + public static final BooleanBlockProperty OMINOUS = bool("ominous"); + public static final BooleanBlockProperty OPEN = bool("open"); + public static final BooleanBlockProperty PERSISTENT = bool("persistent"); + public static final BooleanBlockProperty POWERED = bool("powered"); + public static final BooleanBlockProperty SHORT = bool("short"); + public static final BooleanBlockProperty SHRIEKING = bool("shrieking"); + public static final BooleanBlockProperty SIGNAL_FIRE = bool("signal_fire"); + public static final BooleanBlockProperty SNOWY = bool("snowy"); + public static final BooleanBlockProperty SOUTH = bool("south"); + public static final BooleanBlockProperty TIP = bool("tip"); + public static final BooleanBlockProperty TRIGGERED = bool("triggered"); + public static final BooleanBlockProperty UNSTABLE = bool("unstable"); + public static final BooleanBlockProperty UP = bool("up"); + public static final BooleanBlockProperty WATERLOGGED = bool("waterlogged"); + public static final BooleanBlockProperty WEST = bool("west"); + public static final EnumBlockProperty ATTACH_FACE = enumeration("face", FaceAttachable.AttachedFace.class); + public static final EnumBlockProperty AXIS = enumeration("axis", Axis.class); + public static final EnumBlockProperty BAMBOO_LEAVES = enumeration("leaves", Bamboo.Leaves.class); + public static final EnumBlockProperty BED_PART = enumeration("part", Bed.Part.class); + public static final EnumBlockProperty BELL_ATTACHMENT = enumeration("attachment", Bell.Attachment.class); + public static final EnumBlockProperty CHEST_TYPE = enumeration("type", Chest.Type.class); + public static final EnumBlockProperty CREAKING_HEART_STATE = enumeration("creaking_heart_state", CreakingHeart.State.class); + public static final EnumBlockProperty DOOR_HINGE = enumeration("hinge", Door.Hinge.class); + public static final EnumBlockProperty DOUBLE_BLOCK_HALF = enumeration("half", Bisected.Half.class); + public static final EnumBlockProperty DRIPSTONE_THICKNESS = enumeration("thickness", PointedDripstone.Thickness.class); + public static final EnumBlockProperty EAST_REDSTONE = enumeration("east", RedstoneWire.Connection.class); + public static final EnumBlockProperty EAST_WALL = enumeration("east", Wall.Height.class); + public static final EnumBlockProperty FACING = enumeration("facing", BlockFace.class, org.bukkit.block.BlockFace::isCartesian); + public static final EnumBlockProperty FACING_HOPPER = enumeration("facing", BlockFace.class, ((Predicate) org.bukkit.block.BlockFace::isCartesian).and(face -> face != org.bukkit.block.BlockFace.UP)); + public static final EnumBlockProperty HALF = enumeration("half", Bisected.Half.class); + public static final EnumBlockProperty HORIZONTAL_AXIS = enumeration("axis", Axis.class, org.bukkit.Axis::isHorizontal); + public static final EnumBlockProperty HORIZONTAL_FACING = enumeration("facing", BlockFace.class, org.bukkit.block.BlockFace::isCardinal); + public static final EnumBlockProperty MODE_COMPARATOR = enumeration("mode", Comparator.Mode.class); + public static final EnumBlockProperty NORTH_REDSTONE = enumeration("north", RedstoneWire.Connection.class); + public static final EnumBlockProperty NORTH_WALL = enumeration("north", Wall.Height.class); + public static final EnumBlockProperty NOTEBLOCK_INSTRUMENT = enumeration("instrument", Instrument.class); + public static final EnumBlockProperty ORIENTATION = enumeration("orientation", Orientation.class); + public static final EnumBlockProperty PISTON_TYPE = enumeration("type", TechnicalPiston.Type.class); + public static final EnumBlockProperty RAIL_SHAPE = enumeration("shape", Rail.Shape.class); + public static final EnumBlockProperty RAIL_SHAPE_STRAIGHT = enumeration("shape", Rail.Shape.class, org.bukkit.block.data.Rail.Shape::isStraight); + public static final EnumBlockProperty SCULK_SENSOR_PHASE = enumeration("sculk_sensor_phase", SculkSensor.Phase.class); + public static final EnumBlockProperty SLAB_TYPE = enumeration("type", Slab.Type.class); + public static final EnumBlockProperty SOUTH_REDSTONE = enumeration("south", RedstoneWire.Connection.class); + public static final EnumBlockProperty SOUTH_WALL = enumeration("south", Wall.Height.class); + public static final EnumBlockProperty STAIRS_SHAPE = enumeration("shape", Stairs.Shape.class); + public static final EnumBlockProperty STRUCTUREBLOCK_MODE = enumeration("mode", StructureBlock.Mode.class); + public static final EnumBlockProperty TEST_BLOCK_MODE = enumeration("mode", TestBlock.Mode.class); + public static final EnumBlockProperty TILT = enumeration("tilt", BigDripleaf.Tilt.class); + public static final EnumBlockProperty TRIAL_SPAWNER_STATE = enumeration("trial_spawner_state", TrialSpawner.State.class); + public static final EnumBlockProperty VAULT_STATE = enumeration("vault_state", Vault.State.class); + public static final EnumBlockProperty VERTICAL_DIRECTION = enumeration("vertical_direction", BlockFace.class, face -> face.getModY() != 0); + public static final EnumBlockProperty WEST_REDSTONE = enumeration("west", RedstoneWire.Connection.class); + public static final EnumBlockProperty WEST_WALL = enumeration("west", Wall.Height.class); + public static final IntegerBlockProperty AGE_1 = integer("age", 0, 1); + public static final IntegerBlockProperty AGE_15 = integer("age", 0, 15); + public static final IntegerBlockProperty AGE_2 = integer("age", 0, 2); + public static final IntegerBlockProperty AGE_25 = integer("age", 0, 25); + public static final IntegerBlockProperty AGE_3 = integer("age", 0, 3); + public static final IntegerBlockProperty AGE_4 = integer("age", 0, 4); + public static final IntegerBlockProperty AGE_5 = integer("age", 0, 5); + public static final IntegerBlockProperty AGE_7 = integer("age", 0, 7); + public static final IntegerBlockProperty BITES = integer("bites", 0, 6); + public static final IntegerBlockProperty CANDLES = integer("candles", 1, 4); + public static final IntegerBlockProperty DELAY = integer("delay", 1, 4); + public static final IntegerBlockProperty DISTANCE = integer("distance", 1, 7); + public static final IntegerBlockProperty DRIED_GHAST_HYDRATION_LEVELS = integer("hydration", 0, 3); + public static final IntegerBlockProperty DUSTED = integer("dusted", 0, 3); + public static final IntegerBlockProperty EGGS = integer("eggs", 1, 4); + public static final IntegerBlockProperty FLOWER_AMOUNT = integer("flower_amount", 1, 4); + public static final IntegerBlockProperty HATCH = integer("hatch", 0, 2); + public static final IntegerBlockProperty LAYERS = integer("layers", 1, 8); + public static final IntegerBlockProperty LEVEL = integer("level", 0, 15); + public static final IntegerBlockProperty LEVEL_CAULDRON = integer("level", 1, 3); + public static final IntegerBlockProperty LEVEL_COMPOSTER = integer("level", 0, 8); + public static final IntegerBlockProperty LEVEL_FLOWING = integer("level", 1, 8); + public static final IntegerBlockProperty LEVEL_HONEY = integer("honey_level", 0, 5); + public static final IntegerBlockProperty MOISTURE = integer("moisture", 0, 7); + public static final BlockProperty NOTE = register(new NoteBlockProperty("note")); + public static final IntegerBlockProperty PICKLES = integer("pickles", 1, 4); + public static final IntegerBlockProperty POWER = integer("power", 0, 15); + public static final IntegerBlockProperty RESPAWN_ANCHOR_CHARGES = integer("charges", 0, 4); + public static final EnumBlockProperty ROTATION_16 = register(new RotationBlockProperty("rotation")); + public static final IntegerBlockProperty SEGMENT_AMOUNT = integer("segment_amount", 1, 4); + public static final IntegerBlockProperty STABILITY_DISTANCE = integer("distance", 0, 7); + public static final IntegerBlockProperty STAGE = integer("stage", 0, 1); +<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/paper-api/src/main/java/io/papermc/paper/dialog/Dialog.java b/paper-api/src/main/java/io/papermc/paper/dialog/Dialog.java index a77c23ab0a..e7ab79fcfb 100644 --- a/paper-api/src/main/java/io/papermc/paper/dialog/Dialog.java +++ b/paper-api/src/main/java/io/papermc/paper/dialog/Dialog.java @@ -32,7 +32,7 @@ public interface Dialog extends Keyed, DialogLike { } // Start generate - Dialog - // @GeneratedFrom 1.21.7-rc2 + // @GeneratedFrom 1.21.7 Dialog CUSTOM_OPTIONS = getDialog("custom_options"); Dialog QUICK_ACTIONS = getDialog("quick_actions"); diff --git a/paper-api/src/main/java/org/bukkit/Material.java b/paper-api/src/main/java/org/bukkit/Material.java index 899c288e12..9f97331ff5 100644 --- a/paper-api/src/main/java/org/bukkit/Material.java +++ b/paper-api/src/main/java/org/bukkit/Material.java @@ -89,7 +89,6 @@ import org.bukkit.block.data.type.MangrovePropagule; import org.bukkit.block.data.type.MossyCarpet; import org.bukkit.block.data.type.NoteBlock; import org.bukkit.block.data.type.Observer; -import org.bukkit.block.data.type.PinkPetals; import org.bukkit.block.data.type.Piston; import org.bukkit.block.data.type.PistonHead; import org.bukkit.block.data.type.PitcherCrop; diff --git a/paper-api/src/main/java/org/bukkit/Tag.java b/paper-api/src/main/java/org/bukkit/Tag.java index 747f146866..f050ecc869 100644 --- a/paper-api/src/main/java/org/bukkit/Tag.java +++ b/paper-api/src/main/java/org/bukkit/Tag.java @@ -19,10 +19,14 @@ import org.jetbrains.annotations.NotNull; */ public interface Tag extends Keyed { + String REGISTRY_BLOCKS = "blocks"; + String REGISTRY_ITEMS = "items"; + String REGISTRY_FLUIDS = "fluids"; + String REGISTRY_ENTITY_TYPES = "entity_types"; + String REGISTRY_GAME_EVENTS = "game_events"; + // Start generate - Tag // @GeneratedFrom 1.21.7 - String REGISTRY_BLOCKS = "blocks"; - Tag ACACIA_LOGS = Bukkit.getTag(REGISTRY_BLOCKS, NamespacedKey.minecraft("acacia_logs"), Material.class); Tag AIR = Bukkit.getTag(REGISTRY_BLOCKS, NamespacedKey.minecraft("air"), Material.class); @@ -411,8 +415,6 @@ public interface Tag extends Keyed { Tag WOOL_CARPETS = Bukkit.getTag(REGISTRY_BLOCKS, NamespacedKey.minecraft("wool_carpets"), Material.class); - String REGISTRY_ITEMS = "items"; - Tag ITEMS_ACACIA_LOGS = Bukkit.getTag(REGISTRY_ITEMS, NamespacedKey.minecraft("acacia_logs"), Material.class); Tag ITEMS_ANVIL = Bukkit.getTag(REGISTRY_ITEMS, NamespacedKey.minecraft("anvil"), Material.class); @@ -771,14 +773,10 @@ public interface Tag extends Keyed { Tag ITEMS_WOOL_CARPETS = Bukkit.getTag(REGISTRY_ITEMS, NamespacedKey.minecraft("wool_carpets"), Material.class); - String REGISTRY_FLUIDS = "fluids"; - Tag FLUIDS_LAVA = Bukkit.getTag(REGISTRY_FLUIDS, NamespacedKey.minecraft("lava"), Fluid.class); Tag FLUIDS_WATER = Bukkit.getTag(REGISTRY_FLUIDS, NamespacedKey.minecraft("water"), Fluid.class); - String REGISTRY_ENTITY_TYPES = "entity_types"; - Tag ENTITY_TYPES_AQUATIC = Bukkit.getTag(REGISTRY_ENTITY_TYPES, NamespacedKey.minecraft("aquatic"), EntityType.class); Tag ENTITY_TYPES_ARROWS = Bukkit.getTag(REGISTRY_ENTITY_TYPES, NamespacedKey.minecraft("arrows"), EntityType.class); @@ -857,8 +855,6 @@ public interface Tag extends Keyed { Tag ENTITY_TYPES_ZOMBIES = Bukkit.getTag(REGISTRY_ENTITY_TYPES, NamespacedKey.minecraft("zombies"), EntityType.class); - String REGISTRY_GAME_EVENTS = "game_events"; - Tag GAME_EVENT_ALLAY_CAN_LISTEN = Bukkit.getTag(REGISTRY_GAME_EVENTS, NamespacedKey.minecraft("allay_can_listen"), GameEvent.class); Tag GAME_EVENT_IGNORE_VIBRATIONS_SNEAKING = Bukkit.getTag(REGISTRY_GAME_EVENTS, NamespacedKey.minecraft("ignore_vibrations_sneaking"), GameEvent.class); diff --git a/paper-api/src/main/java/org/bukkit/attribute/Attribute.java b/paper-api/src/main/java/org/bukkit/attribute/Attribute.java index 78361d62fd..1b17d624fa 100644 --- a/paper-api/src/main/java/org/bukkit/attribute/Attribute.java +++ b/paper-api/src/main/java/org/bukkit/attribute/Attribute.java @@ -17,147 +17,184 @@ import org.jetbrains.annotations.NotNull; */ public interface Attribute extends OldEnum, Keyed, Translatable, net.kyori.adventure.translation.Translatable { // Paper - Adventure translations - /** - * Maximum health of an Entity. - */ - Attribute MAX_HEALTH = getAttribute("max_health"); - /** - * Range at which an Entity will follow others. - */ - Attribute FOLLOW_RANGE = getAttribute("follow_range"); - /** - * Resistance of an Entity to knockback. - */ - Attribute KNOCKBACK_RESISTANCE = getAttribute("knockback_resistance"); - /** - * Movement speed of an Entity. - */ - Attribute MOVEMENT_SPEED = getAttribute("movement_speed"); - /** - * Flying speed of an Entity. - */ - Attribute FLYING_SPEED = getAttribute("flying_speed"); - /** - * Attack damage of an Entity. - */ - Attribute ATTACK_DAMAGE = getAttribute("attack_damage"); - /** - * Attack knockback of an Entity. - */ - Attribute ATTACK_KNOCKBACK = getAttribute("attack_knockback"); - /** - * Attack speed of an Entity. - */ - Attribute ATTACK_SPEED = getAttribute("attack_speed"); + // Start generate - Attribute + // @GeneratedFrom 1.21.7 /** * Armor bonus of an Entity. */ Attribute ARMOR = getAttribute("armor"); + /** * Armor durability bonus of an Entity. */ Attribute ARMOR_TOUGHNESS = getAttribute("armor_toughness"); + /** - * The fall damage multiplier of an Entity. + * Attack damage of an Entity. */ - Attribute FALL_DAMAGE_MULTIPLIER = getAttribute("fall_damage_multiplier"); + Attribute ATTACK_DAMAGE = getAttribute("attack_damage"); + /** - * Luck bonus of an Entity. + * Attack knockback of an Entity. */ - Attribute LUCK = getAttribute("luck"); + Attribute ATTACK_KNOCKBACK = getAttribute("attack_knockback"); + /** - * Maximum absorption of an Entity. + * Attack speed of an Entity. */ - Attribute MAX_ABSORPTION = getAttribute("max_absorption"); - /** - * The distance which an Entity can fall without damage. - */ - Attribute SAFE_FALL_DISTANCE = getAttribute("safe_fall_distance"); - /** - * The relative scale of an Entity. - */ - Attribute SCALE = getAttribute("scale"); - /** - * The height which an Entity can walk over. - */ - Attribute STEP_HEIGHT = getAttribute("step_height"); - /** - * The gravity applied to an Entity. - */ - Attribute GRAVITY = getAttribute("gravity"); - /** - * Strength with which an Entity will jump. - */ - Attribute JUMP_STRENGTH = getAttribute("jump_strength"); - /** - * How long an entity remains burning after ignition. - */ - Attribute BURNING_TIME = getAttribute("burning_time"); - /** - * The camera distance of a player to their own entity. - */ - Attribute CAMERA_DISTANCE = getAttribute("camera_distance"); - /** - * Resistance to knockback from explosions. - */ - Attribute EXPLOSION_KNOCKBACK_RESISTANCE = getAttribute("explosion_knockback_resistance"); - /** - * Movement speed through difficult terrain. - */ - Attribute MOVEMENT_EFFICIENCY = getAttribute("movement_efficiency"); - /** - * Oxygen use underwater. - */ - Attribute OXYGEN_BONUS = getAttribute("oxygen_bonus"); - /** - * Movement speed through water. - */ - Attribute WATER_MOVEMENT_EFFICIENCY = getAttribute("water_movement_efficiency"); - /** - * Range at which mobs will be tempted by items. - */ - Attribute TEMPT_RANGE = getAttribute("tempt_range"); - /** - * The block reach distance of a Player. - */ - Attribute BLOCK_INTERACTION_RANGE = getAttribute("block_interaction_range"); - /** - * The entity reach distance of a Player. - */ - Attribute ENTITY_INTERACTION_RANGE = getAttribute("entity_interaction_range"); + Attribute ATTACK_SPEED = getAttribute("attack_speed"); + /** * Block break speed of a Player. */ Attribute BLOCK_BREAK_SPEED = getAttribute("block_break_speed"); + + /** + * The block reach distance of a Player. + */ + Attribute BLOCK_INTERACTION_RANGE = getAttribute("block_interaction_range"); + + /** + * How long an entity remains burning after ignition. + */ + Attribute BURNING_TIME = getAttribute("burning_time"); + + /** + * The camera distance of a player to their own entity. + */ + Attribute CAMERA_DISTANCE = getAttribute("camera_distance"); + + /** + * The entity reach distance of a Player. + */ + Attribute ENTITY_INTERACTION_RANGE = getAttribute("entity_interaction_range"); + + /** + * Resistance to knockback from explosions. + */ + Attribute EXPLOSION_KNOCKBACK_RESISTANCE = getAttribute("explosion_knockback_resistance"); + + /** + * The fall damage multiplier of an Entity. + */ + Attribute FALL_DAMAGE_MULTIPLIER = getAttribute("fall_damage_multiplier"); + + /** + * Flying speed of an Entity. + */ + Attribute FLYING_SPEED = getAttribute("flying_speed"); + + /** + * Range at which an Entity will follow others. + */ + Attribute FOLLOW_RANGE = getAttribute("follow_range"); + + /** + * The gravity applied to an Entity. + */ + Attribute GRAVITY = getAttribute("gravity"); + + /** + * Strength with which an Entity will jump. + */ + Attribute JUMP_STRENGTH = getAttribute("jump_strength"); + + /** + * Resistance of an Entity to knockback. + */ + Attribute KNOCKBACK_RESISTANCE = getAttribute("knockback_resistance"); + + /** + * Luck bonus of an Entity. + */ + Attribute LUCK = getAttribute("luck"); + + /** + * Maximum absorption of an Entity. + */ + Attribute MAX_ABSORPTION = getAttribute("max_absorption"); + + /** + * Maximum health of an Entity. + */ + Attribute MAX_HEALTH = getAttribute("max_health"); + /** * Mining speed for correct tools. */ Attribute MINING_EFFICIENCY = getAttribute("mining_efficiency"); + + /** + * Movement speed through difficult terrain. + */ + Attribute MOVEMENT_EFFICIENCY = getAttribute("movement_efficiency"); + + /** + * Movement speed of an Entity. + */ + Attribute MOVEMENT_SPEED = getAttribute("movement_speed"); + + /** + * Oxygen use underwater. + */ + Attribute OXYGEN_BONUS = getAttribute("oxygen_bonus"); + + /** + * The distance which an Entity can fall without damage. + */ + Attribute SAFE_FALL_DISTANCE = getAttribute("safe_fall_distance"); + + /** + * The relative scale of an Entity. + */ + Attribute SCALE = getAttribute("scale"); + /** * Sneaking speed. */ Attribute SNEAKING_SPEED = getAttribute("sneaking_speed"); - /** - * Underwater mining speed. - */ - Attribute SUBMERGED_MINING_SPEED = getAttribute("submerged_mining_speed"); - /** - * Sweeping damage. - */ - Attribute SWEEPING_DAMAGE_RATIO = getAttribute("sweeping_damage_ratio"); + /** * Chance of a zombie to spawn reinforcements. */ Attribute SPAWN_REINFORCEMENTS = getAttribute("spawn_reinforcements"); + /** - * Attribute controlling the range an entity transmits itself as a waypoint. + * The height which an Entity can walk over. */ - Attribute WAYPOINT_TRANSMIT_RANGE = getAttribute("waypoint_transmit_range"); + Attribute STEP_HEIGHT = getAttribute("step_height"); + + /** + * Underwater mining speed. + */ + Attribute SUBMERGED_MINING_SPEED = getAttribute("submerged_mining_speed"); + + /** + * Sweeping damage. + */ + Attribute SWEEPING_DAMAGE_RATIO = getAttribute("sweeping_damage_ratio"); + + /** + * Range at which mobs will be tempted by items. + */ + Attribute TEMPT_RANGE = getAttribute("tempt_range"); + + /** + * Movement speed through water. + */ + Attribute WATER_MOVEMENT_EFFICIENCY = getAttribute("water_movement_efficiency"); + /** * Attribute controlling the range an entity receives other waypoints from. */ Attribute WAYPOINT_RECEIVE_RANGE = getAttribute("waypoint_receive_range"); + /** + * Attribute controlling the range an entity transmits itself as a waypoint. + */ + Attribute WAYPOINT_TRANSMIT_RANGE = getAttribute("waypoint_transmit_range"); + // End generate - Attribute + @NotNull private static Attribute getAttribute(@NotNull String key) { return Registry.ATTRIBUTE.getOrThrow(NamespacedKey.minecraft(key)); diff --git a/paper-api/src/main/java/org/bukkit/entity/EntityType.java b/paper-api/src/main/java/org/bukkit/entity/EntityType.java index 2b661dbf1d..b85e547a77 100644 --- a/paper-api/src/main/java/org/bukkit/entity/EntityType.java +++ b/paper-api/src/main/java/org/bukkit/entity/EntityType.java @@ -37,8 +37,6 @@ import org.bukkit.entity.minecart.PoweredMinecart; import org.bukkit.entity.minecart.RideableMinecart; import org.bukkit.entity.minecart.SpawnerMinecart; import org.bukkit.entity.minecart.StorageMinecart; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/paper-api/src/main/java/org/bukkit/entity/Pose.java b/paper-api/src/main/java/org/bukkit/entity/Pose.java index 1a6dd2a36a..507b08cf72 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Pose.java +++ b/paper-api/src/main/java/org/bukkit/entity/Pose.java @@ -6,6 +6,7 @@ package org.bukkit.entity; public enum Pose { // Start generate - Pose + // @GeneratedFrom 1.21.7 /** * Entity is standing normally. */ diff --git a/paper-api/src/main/java/org/bukkit/inventory/ItemType.java b/paper-api/src/main/java/org/bukkit/inventory/ItemType.java index 8941b158d8..6fe8f79cb3 100644 --- a/paper-api/src/main/java/org/bukkit/inventory/ItemType.java +++ b/paper-api/src/main/java/org/bukkit/inventory/ItemType.java @@ -1,5 +1,6 @@ package org.bukkit.inventory; +import com.destroystokyo.paper.inventory.meta.ArmorStandMeta; import com.google.common.collect.Multimap; import io.papermc.paper.datacomponent.DataComponentType; import java.util.Set; @@ -94,7 +95,7 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans // // Start generate - ItemType - // @GeneratedFrom 1.21.7-rc1 + // @GeneratedFrom 1.21.7 ItemType.Typed ACACIA_BOAT = getItemType("acacia_boat"); ItemType.Typed ACACIA_BUTTON = getItemType("acacia_button"); @@ -165,7 +166,7 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans ItemType.Typed ARMADILLO_SPAWN_EGG = getItemType("armadillo_spawn_egg"); - ItemType.Typed ARMOR_STAND = getItemType("armor_stand"); + ItemType.Typed ARMOR_STAND = getItemType("armor_stand"); ItemType.Typed ARMS_UP_POTTERY_SHERD = getItemType("arms_up_pottery_sherd"); diff --git a/paper-generator/.editorconfig b/paper-generator/.editorconfig index 71c3cd0c32..b17dc83c73 100644 --- a/paper-generator/.editorconfig +++ b/paper-generator/.editorconfig @@ -1,3 +1,6 @@ [*.java] ij_java_generate_final_locals = false ij_java_generate_final_parameters = false + +[*.json] +indent_size = 2 diff --git a/paper-generator/build.gradle.kts b/paper-generator/build.gradle.kts index acd69cc8df..8478aae225 100644 --- a/paper-generator/build.gradle.kts +++ b/paper-generator/build.gradle.kts @@ -9,64 +9,63 @@ paperweight { atFile.set(layout.projectDirectory.file("wideners.at")) } -val serverRuntimeClasspath by configurations.registering { // resolvable? - isCanBeConsumed = false - isCanBeResolved = true -} - dependencies { minecraftJar(project(":paper-server", "mappedJarOutgoing")) implementation(project(":paper-server", "macheMinecraftLibraries")) implementation("com.squareup:javapoet:1.13.0") - implementation(project(":paper-api")) - implementation("io.papermc.typewriter:typewriter:1.0.1") { - isTransitive = false // paper-api already have everything - } + implementation("io.papermc.typewriter:typewriter:1.0.2-20250601.125803-3") implementation("info.picocli:picocli:4.7.6") - implementation("io.github.classgraph:classgraph:4.8.47") - implementation("org.jetbrains:annotations:26.0.1") - testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") + implementation("io.github.classgraph:classgraph:4.8.179") + implementation("org.jetbrains:annotations:26.0.2") + implementation("org.jspecify:jspecify:1.0.0") - serverRuntimeClasspath(project(":paper-server", "runtimeConfiguration")) + testImplementation("org.junit.jupiter:junit-jupiter:5.12.2") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") } val gameVersion = providers.gradleProperty("mcVersion") val rewriteApi = tasks.registerGenerationTask("rewriteApi", true, "api", { bootstrapTags = true - sourceSet = rootProject.layout.projectDirectory.dir("paper-api") + sourceSet = "paper-api/src/main/java" }) { description = "Rewrite existing API classes" classpath(sourceSets.main.map { it.runtimeClasspath }) } val rewriteImpl = tasks.registerGenerationTask("rewriteImpl", true, "impl", { - sourceSet = rootProject.layout.projectDirectory.dir("paper-server") - serverClassPath.from(serverRuntimeClasspath) + bootstrapTags = true // needed for CraftItemMetasRewriter, remove once item meta is gone + sourceSet = "paper-server/src/main/java" }) { description = "Rewrite existing implementation classes" classpath(sourceSets.main.map { it.runtimeClasspath }) } +val rewriteImplTest = tasks.registerGenerationTask("rewriteImplTest", true, "impl-test", { + sourceSet = "paper-server/src/test/java" +}) { + description = "Rewrite existing implementation test classes" + classpath(sourceSets.main.map { it.runtimeClasspath }) +} + tasks.register("rewrite") { group = "generation" description = "Rewrite existing API classes and its implementation" - dependsOn(rewriteApi, rewriteImpl) + dependsOn(rewriteApi, rewriteImpl, rewriteImplTest) } val generateApi = tasks.registerGenerationTask("generateApi", false, "api", { bootstrapTags = true - sourceSet = rootProject.layout.projectDirectory.dir("paper-api") + sourceSet = "paper-api/src/generated/java" }) { description = "Generate new API classes" classpath(sourceSets.main.map { it.runtimeClasspath }) } val generateImpl = tasks.registerGenerationTask("generateImpl", false, "impl", { - sourceSet = rootProject.layout.projectDirectory.dir("paper-server") + sourceSet = "paper-server/src/generated/java" }) { description = "Generate new implementation classes" classpath(sourceSets.main.map { it.runtimeClasspath }) @@ -78,21 +77,34 @@ tasks.register("generate") { dependsOn(generateApi, generateImpl) } +tasks.register("prepareInputFiles") { + group = "generation" + description = "Prepare input files by sorting them (and updating them if possible)" + javaLauncher = javaToolchains.defaultJavaLauncher(project) + mainClass.set("io.papermc.generator.tasks.PrepareInputFiles") + classpath(sourceSets.main.map { it.runtimeClasspath }) + + inputs.property("gameVersion", gameVersion) + val resourceDir = layout.projectDirectory.dir("src/main/resources") + args(resourceDir.asFile.absolutePath) + inputs.dir(resourceDir) + outputs.dir(resourceDir) +} + if (providers.gradleProperty("updatingMinecraft").getOrElse("false").toBoolean()) { val scanOldGeneratedSourceCode by tasks.registering(JavaExec::class) { group = "verification" description = "Scan source code to detect outdated generated code" javaLauncher = javaToolchains.defaultJavaLauncher(project) - mainClass.set("io.papermc.generator.rewriter.utils.ScanOldGeneratedSourceCode") + mainClass.set("io.papermc.generator.tasks.ScanOldGeneratedSourceCode") classpath(sourceSets.main.map { it.runtimeClasspath }) val projectDirs = listOf("paper-api", "paper-server").map { rootProject.layout.projectDirectory.dir(it) } args(projectDirs.map { it.asFile.absolutePath }) - val workDirs = projectDirs.map { it.dir("src/main/java") } + val workDirs = projectDirs.map { it.dir("src/main/java") }.plus(rootProject.layout.projectDirectory.dir("paper-server/src/test/java")) workDirs.forEach { inputs.dir(it) } inputs.property("gameVersion", gameVersion) - outputs.dirs(workDirs) } tasks.check { dependsOn(scanOldGeneratedSourceCode) @@ -110,20 +122,19 @@ fun TaskContainer.registerGenerationTask( dependsOn(project.tasks.test) javaLauncher = project.javaToolchains.defaultJavaLauncher(project) inputs.property("gameVersion", gameVersion) - inputs.dir(layout.projectDirectory.dir("src/main/java")).withPathSensitivity(PathSensitivity.RELATIVE) + inputs.dir(layout.projectDirectory.dir("src/main/")).withPathSensitivity(PathSensitivity.RELATIVE) mainClass.set("io.papermc.generator.Main") systemProperty("paper.updatingMinecraft", providers.gradleProperty("updatingMinecraft").getOrElse("false").toBoolean()) val provider = objects.newInstance() provider.side = side provider.rewrite = rewrite + provider.rootDir = rootProject.layout.projectDirectory if (args != null) { args(provider) } argumentProviders.add(provider) - - val targetDir = if (rewrite) "src/main/java" else "src/generated/java" - outputs.dir(provider.sourceSet.dir(targetDir)) + // outputs.dir(provider.sourceSet) block(this) } @@ -133,7 +144,10 @@ abstract class GenerationArgumentProvider : CommandLineArgumentProvider { @get:PathSensitive(PathSensitivity.NONE) @get:InputDirectory - abstract val sourceSet: DirectoryProperty + abstract val rootDir: DirectoryProperty + + @get:Input + abstract val sourceSet: Property @get:Input abstract val rewrite: Property @@ -141,9 +155,6 @@ abstract class GenerationArgumentProvider : CommandLineArgumentProvider { @get:Input abstract val side: Property - @get:CompileClasspath - abstract val serverClassPath: ConfigurableFileCollection - @get:Input @get:Optional abstract val bootstrapTags: Property @@ -155,17 +166,18 @@ abstract class GenerationArgumentProvider : CommandLineArgumentProvider { override fun asArguments(): Iterable { val args = mutableListOf() - args.add("--sourceset=${sourceSet.get().asFile.absolutePath}") + args.add("--root-dir=${rootDir.get().asFile.absolutePath}") + args.add("--sourceset=${rootDir.get().dir(sourceSet.get()).asFile.absolutePath}") args.add("--side=${side.get()}") - args.add("--classpath=${serverClassPath.asPath}") if (rewrite.get()) { args.add("--rewrite") } if (bootstrapTags.get()) { - args.add(("--bootstrap-tags")) + args.add("--bootstrap-tags") } + return args.toList() } } @@ -173,6 +185,9 @@ abstract class GenerationArgumentProvider : CommandLineArgumentProvider { tasks.test { useJUnitPlatform() } +tasks.compileTestJava { + options.compilerArgs.add("-parameters") +} group = "io.papermc.paper" version = "1.0-SNAPSHOT" diff --git a/paper-generator/src/main/java/io/papermc/generator/Generators.java b/paper-generator/src/main/java/io/papermc/generator/Generators.java index ae7353b5b4..ec9a8a0351 100644 --- a/paper-generator/src/main/java/io/papermc/generator/Generators.java +++ b/paper-generator/src/main/java/io/papermc/generator/Generators.java @@ -4,6 +4,7 @@ import io.papermc.generator.registry.RegistryBootstrapper; import io.papermc.generator.types.SourceGenerator; import io.papermc.generator.types.craftblockdata.CraftBlockDataBootstrapper; import io.papermc.generator.types.goal.MobGoalGenerator; +import io.papermc.generator.utils.BasePackage; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -15,7 +16,7 @@ public interface Generators { List API = Collections.unmodifiableList(Util.make(new ArrayList<>(), list -> { RegistryBootstrapper.bootstrap(list); - list.add(new MobGoalGenerator("VanillaGoal", "com.destroystokyo.paper.entity.ai")); + list.add(new MobGoalGenerator("VanillaGoal", BasePackage.PAPER_LEGACY.name() + ".entity.ai")); // todo extract fields for registry based api })); diff --git a/paper-generator/src/main/java/io/papermc/generator/Main.java b/paper-generator/src/main/java/io/papermc/generator/Main.java index a96fe8398a..cd4b73ddd6 100644 --- a/paper-generator/src/main/java/io/papermc/generator/Main.java +++ b/paper-generator/src/main/java/io/papermc/generator/Main.java @@ -11,7 +11,6 @@ import java.nio.file.Path; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; @@ -44,12 +43,12 @@ import picocli.CommandLine; ) public class Main implements Callable { + @CommandLine.Option(names = {"--root-dir"}, required = true) + Path rootDir; + @CommandLine.Option(names = {"--sourceset"}, required = true) Path sourceSet; - @CommandLine.Option(names = {"-cp", "--classpath"}, split = "[;:]", required = true) - Set classpath; - @CommandLine.Option(names = {"--rewrite"}) boolean isRewrite; @@ -61,17 +60,19 @@ public class Main implements Callable { private static final Logger LOGGER = LogUtils.getLogger(); + public static @MonotonicNonNull Path ROOT_DIR; public static RegistryAccess.@MonotonicNonNull Frozen REGISTRY_ACCESS; public static @MonotonicNonNull Map, String> EXPERIMENTAL_TAGS; + public static final boolean IS_UPDATING = Boolean.getBoolean("paper.updatingMinecraft"); public static CompletableFuture bootStrap(boolean withTags) { SharedConstants.tryDetectVersion(); Bootstrap.bootStrap(); Bootstrap.validate(); - PackRepository resourceRepository = ServerPacksSource.createVanillaTrustedRepository(); - resourceRepository.reload(); - MultiPackResourceManager resourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, resourceRepository.getAvailablePacks().stream().map(Pack::open).toList()); + PackRepository packRepository = ServerPacksSource.createVanillaTrustedRepository(); + packRepository.reload(); + MultiPackResourceManager resourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, packRepository.getAvailablePacks().stream().map(Pack::open).toList()); LayeredRegistryAccess layers = RegistryLayer.createRegistryAccess(); List> pendingTags = TagLoader.loadTagsForExistingRegistries(resourceManager, layers.getLayer(RegistryLayer.STATIC)); List> worldGenLayer = TagLoader.buildUpdatedLookups(layers.getAccessForLoading(RegistryLayer.WORLDGEN), pendingTags); @@ -106,9 +107,10 @@ public class Main implements Callable { public Integer call() { bootStrap(this.tagBootstrap).join(); + ROOT_DIR = this.rootDir; try { if (this.isRewrite) { - rewrite(this.sourceSet, this.classpath, this.side.equals("api") ? Rewriters.API : Rewriters.SERVER); + rewrite(this.sourceSet, Rewriters.VALUES.get(this.side)); } else { generate(this.sourceSet, this.side.equals("api") ? Generators.API : Generators.SERVER); } @@ -120,22 +122,21 @@ public class Main implements Callable { return 0; } - private static void rewrite(Path sourceSet, Set classpath, Consumer rewriters) throws IOException { - PatternSourceSetRewriter sourceSetRewriter = new PaperPatternSourceSetRewriter(classpath); + private static void rewrite(Path sourceSet, Consumer rewriters) throws IOException { + PatternSourceSetRewriter sourceSetRewriter = new PaperPatternSourceSetRewriter(); rewriters.accept(sourceSetRewriter); - sourceSetRewriter.apply(sourceSet.resolve("src/main/java")); + sourceSetRewriter.apply(sourceSet); } private static void generate(Path sourceSet, Collection generators) throws IOException { - Path output = sourceSet.resolve("src/generated/java"); - if (Files.exists(output)) { - PathUtils.deleteDirectory(output); + if (Files.exists(sourceSet)) { + PathUtils.deleteDirectory(sourceSet); } for (SourceGenerator generator : generators) { - generator.writeToFile(output); + generator.writeToFile(sourceSet); } - LOGGER.info("Files written to {}", output.toAbsolutePath()); + LOGGER.info("Files written to {}", sourceSet.toAbsolutePath()); } public static void main(String[] args) { diff --git a/paper-generator/src/main/java/io/papermc/generator/Rewriters.java b/paper-generator/src/main/java/io/papermc/generator/Rewriters.java index 5570229d13..1fb69ae939 100644 --- a/paper-generator/src/main/java/io/papermc/generator/Rewriters.java +++ b/paper-generator/src/main/java/io/papermc/generator/Rewriters.java @@ -2,159 +2,144 @@ package io.papermc.generator; import io.papermc.generator.registry.RegistryBootstrapper; import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; +import io.papermc.generator.resources.data.EntityClassData; import io.papermc.generator.rewriter.registration.PatternSourceSetRewriter; import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.rewriter.types.registry.EnumRegistryRewriter; import io.papermc.generator.rewriter.types.registry.FeatureFlagRewriter; import io.papermc.generator.rewriter.types.registry.PaperFeatureFlagMapping; +import io.papermc.generator.rewriter.types.registry.RegistriesArgumentProviderRewriter; +import io.papermc.generator.rewriter.types.registry.RegistryConversionTestRewriter; import io.papermc.generator.rewriter.types.registry.RegistryFieldRewriter; import io.papermc.generator.rewriter.types.registry.RegistryTagRewriter; import io.papermc.generator.rewriter.types.registry.TagRewriter; +import io.papermc.generator.rewriter.types.simple.BlockPropertiesRewriter; import io.papermc.generator.rewriter.types.simple.BlockTypeRewriter; import io.papermc.generator.rewriter.types.simple.CraftBlockDataMapping; import io.papermc.generator.rewriter.types.simple.CraftBlockEntityStateMapping; +import io.papermc.generator.rewriter.types.simple.CraftItemMetasRewriter; import io.papermc.generator.rewriter.types.simple.CraftPotionUtilRewriter; import io.papermc.generator.rewriter.types.simple.EntityTypeRewriter; +import io.papermc.generator.rewriter.types.simple.ItemTypeRewriter; import io.papermc.generator.rewriter.types.simple.MapPaletteRewriter; import io.papermc.generator.rewriter.types.simple.MaterialRewriter; import io.papermc.generator.rewriter.types.simple.MemoryKeyRewriter; import io.papermc.generator.rewriter.types.simple.StatisticRewriter; +import io.papermc.generator.rewriter.types.simple.trial.AttributeRewriter; +import io.papermc.generator.rewriter.types.simple.trial.PoseRewriter; import io.papermc.generator.rewriter.types.simple.trial.VillagerProfessionRewriter; -import io.papermc.generator.types.goal.MobGoalNames; import io.papermc.generator.utils.Formatting; -import io.papermc.paper.datacomponent.item.consumable.ItemUseAnimation; -import io.papermc.paper.dialog.Dialog; import io.papermc.typewriter.preset.EnumCloneRewriter; -import io.papermc.typewriter.preset.model.EnumValue; +import io.papermc.typewriter.preset.model.EnumConstant; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Consumer; import javax.lang.model.SourceVersion; -import net.kyori.adventure.text.format.NamedTextColor; +import net.minecraft.Util; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.sounds.SoundSource; import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.animal.Fox; +import net.minecraft.world.entity.animal.Panda; +import net.minecraft.world.entity.animal.Salmon; +import net.minecraft.world.entity.animal.TropicalFish; +import net.minecraft.world.entity.animal.armadillo.Armadillo; +import net.minecraft.world.entity.animal.sniffer.Sniffer; +import net.minecraft.world.entity.vehicle.AbstractBoat; +import net.minecraft.world.item.ItemUseAnimation; +import net.minecraft.world.item.JukeboxSong; import net.minecraft.world.item.Rarity; -import org.bukkit.Art; -import org.bukkit.FeatureFlag; -import org.bukkit.Fluid; -import org.bukkit.GameEvent; -import org.bukkit.JukeboxSong; -import org.bukkit.Material; -import org.bukkit.MusicInstrument; -import org.bukkit.Sound; -import org.bukkit.SoundCategory; -import org.bukkit.Statistic; -import org.bukkit.Tag; -import org.bukkit.block.Biome; -import org.bukkit.block.BlockType; -import org.bukkit.block.banner.PatternType; -import org.bukkit.damage.DamageType; -import org.bukkit.entity.Armadillo; -import org.bukkit.entity.Boat; -import org.bukkit.entity.Cat; -import org.bukkit.entity.Chicken; -import org.bukkit.entity.Cow; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Fox; -import org.bukkit.entity.Frog; -import org.bukkit.entity.Panda; -import org.bukkit.entity.Pig; -import org.bukkit.entity.Salmon; -import org.bukkit.entity.Sniffer; -import org.bukkit.entity.TropicalFish; -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.ItemRarity; -import org.bukkit.inventory.meta.trim.TrimMaterial; -import org.bukkit.inventory.meta.trim.TrimPattern; -import org.bukkit.inventory.recipe.CookingBookCategory; -import org.bukkit.inventory.recipe.CraftingBookCategory; -import org.bukkit.map.MapCursor; -import org.bukkit.map.MapPalette; -import org.bukkit.potion.PotionType; -import org.bukkit.scoreboard.DisplaySlot; -import org.bukkit.tag.DamageTypeTags; +import net.minecraft.world.item.crafting.CookingBookCategory; +import net.minecraft.world.item.crafting.CraftingBookCategory; +import net.minecraft.world.scores.DisplaySlot; import org.jspecify.annotations.NullMarked; import static io.papermc.generator.rewriter.registration.PaperPatternSourceSetRewriter.composite; import static io.papermc.generator.rewriter.registration.RewriterHolder.holder; +import static io.papermc.generator.rewriter.registration.RewriterHolder.sameHolder; import static io.papermc.generator.utils.Formatting.quoted; @NullMarked public final class Rewriters { - public static void bootstrap(PatternSourceSetRewriter apiSourceSet, PatternSourceSetRewriter serverSourceSet) { - bootstrapApi(apiSourceSet); - bootstrapServer(serverSourceSet); + public static void bootstrap(PatternSourceSetRewriter... sourceSets) { + Iterator> values = VALUES.values().iterator(); + for (PatternSourceSetRewriter sourceSetRewriter : sourceSets) { + values.next().accept(sourceSetRewriter); + } } - public static final Consumer API = Rewriters::bootstrapApi; - public static final Consumer SERVER = Rewriters::bootstrapServer; + public static final Map> VALUES = Util.make(new LinkedHashMap<>(), map -> { + map.put("api", Rewriters::bootstrapApi); + map.put("impl", Rewriters::bootstrapImpl); + map.put("impl-test", Rewriters::bootstrapImplTest); + }); private static void bootstrapApi(PatternSourceSetRewriter sourceSet) { sourceSet - .register("PotionType", PotionType.class, new EnumRegistryRewriter<>(Registries.POTION)) - .register("EntityType", EntityType.class, new EntityTypeRewriter()) - .register("DisplaySlot", DisplaySlot.class, new EnumCloneRewriter<>(net.minecraft.world.scores.DisplaySlot.class) { + .register("PotionType", new EnumRegistryRewriter<>(Registries.POTION)) + .register("EntityType", new EntityTypeRewriter()) + .register("DisplaySlot", Types.DISPLAY_SLOT, new EnumCloneRewriter<>(DisplaySlot.class) { + @Override - protected EnumValue.Builder rewriteEnumValue(net.minecraft.world.scores.DisplaySlot slot) { - final String name; - if (slot == net.minecraft.world.scores.DisplaySlot.LIST) { - name = "PLAYER_LIST"; - } else { - name = Formatting.formatKeyAsField(slot.getSerializedName()); + protected EnumConstant.Builder constantPrototype(DisplaySlot slot) { + return EnumConstant.builder(Formatting.formatKeyAsField(slot.getSerializedName())); + } + + @Override + protected void rewriteConstant(EnumConstant.Builder builder, DisplaySlot slot) { + if (slot == DisplaySlot.LIST) { + builder.rename(name -> "PLAYER_LIST"); } + builder.argument(quoted(slot.getSerializedName())); + } + }) + .register("Pose", Types.POSE, new PoseRewriter()) + .register("SnifferState", Types.SNIFFER_STATE, new EnumCloneRewriter<>(Sniffer.State.class)) + .register("PandaGene", Types.PANDA_GENE, new EnumCloneRewriter<>(Panda.Gene.class) { + @Override + protected void rewriteConstant(EnumConstant.Builder builder, Panda.Gene gene) { + builder.argument(String.valueOf(gene.isRecessive())); + } + }) + .register("CookingBookCategory", Types.COOKING_BOOK_CATEGORY, new EnumCloneRewriter<>(CookingBookCategory.class)) + .register("CraftingBookCategory", Types.CRAFTING_BOOK_CATEGORY, new EnumCloneRewriter<>(CraftingBookCategory.class)) + .register("TropicalFishPattern", Types.TROPICAL_FISH_PATTERN, new EnumCloneRewriter<>(TropicalFish.Pattern.class)) + .register("BoatStatus", Types.BOAT_STATUS, new EnumCloneRewriter<>(AbstractBoat.Status.class)) + .register("FoxType", Types.FOX_TYPE, new EnumCloneRewriter<>(Fox.Variant.class)) + .register("SalmonVariant", Types.SALMON_VARIANT, new EnumCloneRewriter<>(Salmon.Variant.class)) + .register("ArmadilloState", Types.ARMADILLO_STATE, new EnumCloneRewriter<>(Armadillo.ArmadilloState.class)) + .register("SoundCategory", Types.SOUND_CATEGORY, new EnumCloneRewriter<>(SoundSource.class)) + .register("ItemUseAnimation", Types.ITEM_USE_ANIMATION, new EnumCloneRewriter<>(ItemUseAnimation.class)) + .register("ItemRarity", Types.ITEM_RARITY, new EnumCloneRewriter<>(Rarity.class) { + @Override + protected void rewriteConstant(EnumConstant.Builder builder, Rarity rarity) { + builder.argument("%s.%s".formatted(Types.NAMED_TEXT_COLOR.simpleName(), rarity.color().name())); + } + }) + .register(Types.MATERIAL, composite( + sameHolder("Blocks", new MaterialRewriter.Blocks()), + //sameHolder("Material#isTransparent", MaterialRewriter.IsTransparent()), - return EnumValue.builder(name).argument(quoted(slot.getSerializedName())); - } - }) - .register("SnifferState", Sniffer.State.class, new EnumCloneRewriter<>(net.minecraft.world.entity.animal.sniffer.Sniffer.State.class)) - .register("PandaGene", Panda.Gene.class, new EnumCloneRewriter<>(net.minecraft.world.entity.animal.Panda.Gene.class) { - @Override - protected EnumValue.Builder rewriteEnumValue(net.minecraft.world.entity.animal.Panda.Gene gene) { - return super.rewriteEnumValue(gene).argument(String.valueOf(gene.isRecessive())); - } - }) - .register("CookingBookCategory", CookingBookCategory.class, new EnumCloneRewriter<>(net.minecraft.world.item.crafting.CookingBookCategory.class)) - .register("CraftingBookCategory", CraftingBookCategory.class, new EnumCloneRewriter<>(net.minecraft.world.item.crafting.CraftingBookCategory.class)) - .register("TropicalFishPattern", TropicalFish.Pattern.class, new EnumCloneRewriter<>(net.minecraft.world.entity.animal.TropicalFish.Pattern.class)) - .register("BoatStatus", Boat.Status.class, new EnumCloneRewriter<>(net.minecraft.world.entity.vehicle.Boat.Status.class)) - .register("FoxType", Fox.Type.class, new EnumCloneRewriter<>(net.minecraft.world.entity.animal.Fox.Variant.class)) - .register("SalmonVariant", Salmon.Variant.class, new EnumCloneRewriter<>(net.minecraft.world.entity.animal.Salmon.Variant.class)) - .register("ArmadilloState", Armadillo.State.class, new EnumCloneRewriter<>(net.minecraft.world.entity.animal.armadillo.Armadillo.ArmadilloState.class)) - .register("SoundCategory", SoundCategory.class, new EnumCloneRewriter<>(SoundSource.class)) - .register("ItemUseAnimation", ItemUseAnimation.class, new EnumCloneRewriter<>(net.minecraft.world.item.ItemUseAnimation.class)) - .register("ItemRarity", ItemRarity.class, new EnumCloneRewriter<>(Rarity.class) { - @Override - protected EnumValue.Builder rewriteEnumValue(Rarity rarity) { - return super.rewriteEnumValue(rarity).argument( - "%s.%s".formatted(NamedTextColor.class.getSimpleName(), rarity.color().name()) - ); - } - }) - .register(Material.class, composite( - holder("Blocks", new MaterialRewriter.Blocks()), - //holder("Material#isTransparent", MaterialRewriter.IsTransparent()), - - holder("Items", new MaterialRewriter.Items()) + sameHolder("Items", new MaterialRewriter.Items()) )) - .register(Statistic.class, composite( - holder("StatisticCustom", new StatisticRewriter.Custom()), - holder("StatisticType", new StatisticRewriter.Type()) + .register(Types.STATISTIC, composite( + sameHolder("StatisticCustom", new StatisticRewriter.Custom()), + sameHolder("StatisticType", new StatisticRewriter.Type()) )) - .register(Villager.class, composite( - holder("VillagerType", Villager.Type.class, new RegistryFieldRewriter<>(Registries.VILLAGER_TYPE, "getType")), - holder("VillagerProfession", Villager.Profession.class, new VillagerProfessionRewriter()) + .register(Types.VILLAGER, composite( + holder("VillagerType", new RegistryFieldRewriter<>(Registries.VILLAGER_TYPE, "getType")), + holder("VillagerProfession", new VillagerProfessionRewriter()) )) - .register("JukeboxSong", JukeboxSong.class, new RegistryFieldRewriter<>(Registries.JUKEBOX_SONG, "get") { + .register("JukeboxSong", new RegistryFieldRewriter<>(Registries.JUKEBOX_SONG, "get") { @Override - protected String rewriteFieldName(Holder.Reference reference) { + protected String rewriteFieldName(Holder.Reference reference) { String keyedName = super.rewriteFieldName(reference); if (!SourceVersion.isIdentifier(keyedName)) { // fallback to field names for invalid identifier (happens for 5, 11, 13 etc.) @@ -163,57 +148,59 @@ public final class Rewriters { return keyedName; } }) - .register("DamageTypeTags", DamageTypeTags.class, new RegistryTagRewriter<>(Registries.DAMAGE_TYPE, DamageType.class)) - .register("MapCursorType", MapCursor.Type.class, new RegistryFieldRewriter<>(Registries.MAP_DECORATION_TYPE, "getType")) - .register("Structure", Structure.class, new RegistryFieldRewriter<>(Registries.STRUCTURE, "getStructure")) - .register("StructureType", StructureType.class, new RegistryFieldRewriter<>(Registries.STRUCTURE_TYPE, "getStructureType")) - .register("TrimPattern", TrimPattern.class, new RegistryFieldRewriter<>(Registries.TRIM_PATTERN, "getTrimPattern")) - .register("TrimMaterial", TrimMaterial.class, new RegistryFieldRewriter<>(Registries.TRIM_MATERIAL, "getTrimMaterial")) - .register("DamageType", DamageType.class, new RegistryFieldRewriter<>(Registries.DAMAGE_TYPE, "getDamageType")) - .register("GameEvent", GameEvent.class, new RegistryFieldRewriter<>(Registries.GAME_EVENT, "getEvent")) - .register("MusicInstrument", MusicInstrument.class, new RegistryFieldRewriter<>(Registries.INSTRUMENT, "getInstrument")) - .register("WolfVariant", Wolf.Variant.class, new RegistryFieldRewriter<>(Registries.WOLF_VARIANT, "getVariant")) - .register("WolfSoundVariant", Wolf.SoundVariant.class, new RegistryFieldRewriter<>(Registries.WOLF_SOUND_VARIANT, "getSoundVariant")) - .register("CatType", Cat.Type.class, new RegistryFieldRewriter<>(Registries.CAT_VARIANT, "getType")) - .register("FrogVariant", Frog.Variant.class, new RegistryFieldRewriter<>(Registries.FROG_VARIANT, "getVariant")) - .register("PatternType", PatternType.class, new RegistryFieldRewriter<>(Registries.BANNER_PATTERN, "getType")) - .register("Biome", Biome.class, new RegistryFieldRewriter<>(Registries.BIOME, "getBiome")) - .register("Fluid", Fluid.class, new RegistryFieldRewriter<>(Registries.FLUID, "getFluid")) - // .register("Attribute", Attribute.class, new RegistryFieldRewriter<>(Registries.ATTRIBUTE, "getAttribute")) - disable for now (javadocs) - .register("Sound", Sound.class, new RegistryFieldRewriter<>(Registries.SOUND_EVENT, "getSound")) - .register("Art", Art.class, new RegistryFieldRewriter<>(Registries.PAINTING_VARIANT, "getArt")) - .register("ChickenVariant", Chicken.Variant.class, new RegistryFieldRewriter<>(Registries.CHICKEN_VARIANT, "getVariant")) - .register("CowVariant", Cow.Variant.class, new RegistryFieldRewriter<>(Registries.COW_VARIANT, "getVariant")) - .register("PigVariant", Pig.Variant.class, new RegistryFieldRewriter<>(Registries.PIG_VARIANT, "getVariant")) - .register("Dialog", Dialog.class, new RegistryFieldRewriter<>(Registries.DIALOG, "getDialog")) - .register("MemoryKey", MemoryKey.class, new MemoryKeyRewriter()) - // .register("ItemType", ItemType.class, new ItemTypeRewriter()) - disable for now, lynx want the generic type - .register("BlockType", BlockType.class, new BlockTypeRewriter()) - .register("FeatureFlag", FeatureFlag.class, new FeatureFlagRewriter()) - .register("Tag", Tag.class, new TagRewriter()) - .register("MapPalette#colors", MapPalette.class, new MapPaletteRewriter()); + .register("DamageTypeTags", Types.DAMAGE_TYPE_TAGS, new RegistryTagRewriter<>(Registries.DAMAGE_TYPE)) + .register("MapCursorType", new RegistryFieldRewriter<>(Registries.MAP_DECORATION_TYPE, "getType")) + .register("Structure", new RegistryFieldRewriter<>(Registries.STRUCTURE, "getStructure")) + .register("StructureType", new RegistryFieldRewriter<>(Registries.STRUCTURE_TYPE, "getStructureType")) + .register("TrimPattern", new RegistryFieldRewriter<>(Registries.TRIM_PATTERN, "getTrimPattern")) + .register("TrimMaterial", new RegistryFieldRewriter<>(Registries.TRIM_MATERIAL, "getTrimMaterial")) + .register("DamageType", new RegistryFieldRewriter<>(Registries.DAMAGE_TYPE, "getDamageType")) + .register("GameEvent", new RegistryFieldRewriter<>(Registries.GAME_EVENT, "getEvent")) + .register("MusicInstrument", new RegistryFieldRewriter<>(Registries.INSTRUMENT, "getInstrument")) + .register("WolfVariant", new RegistryFieldRewriter<>(Registries.WOLF_VARIANT, "getVariant")) + .register("WolfSoundVariant", new RegistryFieldRewriter<>(Registries.WOLF_SOUND_VARIANT, "getSoundVariant")) + .register("CatType", new RegistryFieldRewriter<>(Registries.CAT_VARIANT, "getType")) + .register("FrogVariant", new RegistryFieldRewriter<>(Registries.FROG_VARIANT, "getVariant")) + .register("PatternType", new RegistryFieldRewriter<>(Registries.BANNER_PATTERN, "getType")) + .register("Biome", new RegistryFieldRewriter<>(Registries.BIOME, "getBiome")) + .register("Fluid", new RegistryFieldRewriter<>(Registries.FLUID, "getFluid")) + .register("Attribute", new AttributeRewriter()) + .register("Sound", new RegistryFieldRewriter<>(Registries.SOUND_EVENT, "getSound")) + .register("Art", new RegistryFieldRewriter<>(Registries.PAINTING_VARIANT, "getArt")) + .register("ChickenVariant", new RegistryFieldRewriter<>(Registries.CHICKEN_VARIANT, "getVariant")) + .register("CowVariant", new RegistryFieldRewriter<>(Registries.COW_VARIANT, "getVariant")) + .register("PigVariant", new RegistryFieldRewriter<>(Registries.PIG_VARIANT, "getVariant")) + .register("Dialog", new RegistryFieldRewriter<>(Registries.DIALOG, "getDialog")) + .register("BlockProperties", Types.BLOCK_PROPERTIES, new BlockPropertiesRewriter()) + .register("MemoryKey", new MemoryKeyRewriter()) + .register("ItemType", new ItemTypeRewriter()) + .register("BlockType", new BlockTypeRewriter()) + .register("FeatureFlag", Types.FEATURE_FLAG, new FeatureFlagRewriter()) + .register("Tag", Types.TAG, new TagRewriter()) + .register("MapPalette#colors", Types.MAP_PALETTE, new MapPaletteRewriter()); RegistryBootstrapper.bootstrapApi(sourceSet); } - private static void bootstrapServer(PatternSourceSetRewriter sourceSet) { + private static void bootstrapImpl(PatternSourceSetRewriter sourceSet) { sourceSet .register("CraftBlockData#MAP", Types.CRAFT_BLOCK_DATA, new CraftBlockDataMapping()) .register("CraftBlockEntityStates", Types.CRAFT_BLOCK_STATES, new CraftBlockEntityStateMapping()) + .register("CraftItemMetas#getItemMetaData", Types.CRAFT_ITEM_METAS, new CraftItemMetasRewriter()) .register(Types.CRAFT_STATISTIC, composite( - holder("CraftStatisticCustom", new StatisticRewriter.CraftCustom()), - holder("CraftStatisticType", new StatisticRewriter.CraftType()) + sameHolder("CraftStatisticCustom", new StatisticRewriter.CraftCustom()), + sameHolder("CraftStatisticType", new StatisticRewriter.CraftType()) )) .register(Types.CRAFT_POTION_UTIL, composite( - holder("CraftPotionUtil#upgradeable", new CraftPotionUtilRewriter("strong")), - holder("CraftPotionUtil#extendable", new CraftPotionUtilRewriter("long")) + sameHolder("CraftPotionUtil#upgradeable", new CraftPotionUtilRewriter("strong")), + sameHolder("CraftPotionUtil#extendable", new CraftPotionUtilRewriter("long")) )) .register("PaperFeatureFlagProviderImpl#FLAGS", Types.PAPER_FEATURE_FLAG_PROVIDER_IMPL, new PaperFeatureFlagMapping()) .register("MobGoalHelper#BUKKIT_BRIDGE", Types.MOB_GOAL_HELPER, new SearchReplaceRewriter() { @Override protected void insert(SearchMetadata metadata, StringBuilder builder) { - for (Map.Entry, Class> entry : MobGoalNames.BUKKIT_BRIDGE.entrySet()) { + for (Map.Entry, EntityClassData> entry : DataFileLoader.get(DataFiles.ENTITY_CLASS_NAMES).entrySet()) { builder.append(metadata.indent()).append("map.put(%s.class, %s.class);".formatted( - entry.getKey().getCanonicalName(), this.importCollector.getShortName(entry.getValue()) + entry.getKey().getCanonicalName(), this.importCollector.getShortName(Types.typed(entry.getValue().name())) )); builder.append('\n'); } @@ -221,4 +208,10 @@ public final class Rewriters { }); RegistryBootstrapper.bootstrapServer(sourceSet); } + + private static void bootstrapImplTest(PatternSourceSetRewriter sourceSet) { + sourceSet + .register("RegistriesArgumentProvider#DATA", Types.REGISTRIES_ARGUMENT_PROVIDER, new RegistriesArgumentProviderRewriter()) + .register("RegistryConversionTest#IGNORE_FOR_DIRECT_HOLDER", Types.REGISTRY_CONVERSION_TEST, new RegistryConversionTestRewriter()); + } } diff --git a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryBootstrapper.java b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryBootstrapper.java index c84fcee518..52eadfc10a 100644 --- a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryBootstrapper.java +++ b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryBootstrapper.java @@ -7,7 +7,7 @@ import io.papermc.generator.rewriter.types.registry.RegistryEventsRewriter; import io.papermc.generator.types.SourceGenerator; import io.papermc.generator.types.registry.GeneratedKeyType; import io.papermc.generator.types.registry.GeneratedTagKeyType; -import io.papermc.paper.registry.event.RegistryEvents; +import io.papermc.generator.utils.BasePackage; import java.util.List; import net.minecraft.core.registries.Registries; import org.jspecify.annotations.NullMarked; @@ -15,19 +15,19 @@ import org.jspecify.annotations.NullMarked; @NullMarked public class RegistryBootstrapper { - private static final String PAPER_REGISTRY_PACKAGE = "io.papermc.paper.registry"; + private static final String PAPER_REGISTRY_PACKAGE = BasePackage.PAPER.name() + ".registry"; public static void bootstrap(List generators) { // typed/tag keys RegistryEntries.forEach(entry -> { generators.add(new GeneratedKeyType<>(PAPER_REGISTRY_PACKAGE + ".keys", entry)); if (entry.registry().listTags().findAny().isPresent()) { - generators.add(new GeneratedTagKeyType(entry, PAPER_REGISTRY_PACKAGE + ".keys.tags")); + generators.add(new GeneratedTagKeyType<>(entry, PAPER_REGISTRY_PACKAGE + ".keys.tags")); } }); // todo remove once entity type is a registry - generators.add(new GeneratedTagKeyType(RegistryEntries.byRegistryKey(Registries.ENTITY_TYPE), PAPER_REGISTRY_PACKAGE + ".keys.tags")); + generators.add(new GeneratedTagKeyType<>(RegistryEntries.byRegistryKey(Registries.ENTITY_TYPE), PAPER_REGISTRY_PACKAGE + ".keys.tags")); } public static void bootstrap(PatternSourceSetRewriter apiSourceSet, PatternSourceSetRewriter serverSourceSet) { @@ -36,7 +36,7 @@ public class RegistryBootstrapper { } public static void bootstrapApi(PatternSourceSetRewriter sourceSet) { - sourceSet.register("RegistryEvents", RegistryEvents.class, new RegistryEventsRewriter()); + sourceSet.register("RegistryEvents", Types.REGISTRY_EVENTS, new RegistryEventsRewriter()); } public static void bootstrapServer(PatternSourceSetRewriter sourceSet) { diff --git a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java index a4e46283c7..1342f0c5be 100644 --- a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java +++ b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java @@ -1,36 +1,24 @@ package io.papermc.generator.registry; +import com.google.common.collect.Multimap; +import com.google.common.collect.MultimapBuilder; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.data.RegistryData; import io.papermc.generator.utils.ClassHelper; -import io.papermc.paper.datacomponent.DataComponentType; -import io.papermc.paper.datacomponent.DataComponentTypes; -import io.papermc.paper.dialog.Dialog; -import io.papermc.paper.registry.data.BannerPatternRegistryEntry; -import io.papermc.paper.registry.data.CatTypeRegistryEntry; -import io.papermc.paper.registry.data.ChickenVariantRegistryEntry; -import io.papermc.paper.registry.data.CowVariantRegistryEntry; -import io.papermc.paper.registry.data.DamageTypeRegistryEntry; -import io.papermc.paper.registry.data.EnchantmentRegistryEntry; -import io.papermc.paper.registry.data.FrogVariantRegistryEntry; -import io.papermc.paper.registry.data.GameEventRegistryEntry; -import io.papermc.paper.registry.data.InstrumentRegistryEntry; -import io.papermc.paper.registry.data.JukeboxSongRegistryEntry; -import io.papermc.paper.registry.data.PaintingVariantRegistryEntry; -import io.papermc.paper.registry.data.PigVariantRegistryEntry; -import io.papermc.paper.registry.data.SoundEventRegistryEntry; -import io.papermc.paper.registry.data.WolfVariantRegistryEntry; -import io.papermc.paper.registry.data.dialog.DialogRegistryEntry; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.Type; -import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; +import java.util.stream.Stream; +import net.minecraft.Util; import net.minecraft.core.Registry; import net.minecraft.core.component.DataComponents; import net.minecraft.core.particles.ParticleTypes; @@ -40,6 +28,7 @@ import net.minecraft.server.dialog.Dialogs; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.memory.MemoryModuleType; import net.minecraft.world.entity.animal.CatVariants; @@ -52,6 +41,7 @@ import net.minecraft.world.entity.animal.wolf.WolfVariants; import net.minecraft.world.entity.decoration.PaintingVariants; import net.minecraft.world.entity.npc.VillagerProfession; import net.minecraft.world.entity.npc.VillagerType; +import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.Instruments; import net.minecraft.world.item.Items; import net.minecraft.world.item.JukeboxSongs; @@ -62,69 +52,21 @@ import net.minecraft.world.item.equipment.trim.TrimPatterns; import net.minecraft.world.level.biome.Biomes; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BannerPatterns; +import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.levelgen.structure.BuiltinStructures; +import net.minecraft.world.level.levelgen.structure.StructureType; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.saveddata.maps.MapDecorationTypes; -import org.bukkit.Art; -import org.bukkit.Fluid; -import org.bukkit.GameEvent; -import org.bukkit.JukeboxSong; -import org.bukkit.Keyed; -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.Chicken; -import org.bukkit.entity.Cow; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Frog; -import org.bukkit.entity.Pig; -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.jspecify.annotations.NullMarked; @NullMarked public final class RegistryEntries { - // CraftBukkit entry where implementation start by "Craft" - private static RegistryEntry entry(ResourceKey> registryKey, Class holderElementsClass, Class apiClass) { - return entry(registryKey, holderElementsClass, apiClass, "Craft"); + private static RegistryIntern entry(ResourceKey> registryKey, Class holderElementsClass) { + return new RegistryIntern<>(registryKey, holderElementsClass); } - private static RegistryEntry entry(ResourceKey> registryKey, Class holderElementsClass, Class apiClass, String implPrefix) { - String name = io.papermc.typewriter.util.ClassHelper.retrieveFullNestedName(apiClass); - RegistryKeyField registryKeyField = (RegistryKeyField) REGISTRY_KEY_FIELDS.get(registryKey); - String[] classes = name.split("\\."); - if (classes.length == 0) { - return new RegistryEntry<>(registryKey, registryKeyField, holderElementsClass, apiClass, implPrefix.concat(apiClass.getSimpleName())); - } - - String implName = Arrays.stream(classes).map(implPrefix::concat).collect(Collectors.joining(".")); - return new RegistryEntry<>(registryKey, registryKeyField, holderElementsClass, apiClass, implName); - } - - @Deprecated - private static RegistryEntry inconsistentEntry(ResourceKey> registryKey, Class holderElementsClass, Class apiClass, String implClass) { - return new RegistryEntry<>(registryKey, (RegistryKeyField) REGISTRY_KEY_FIELDS.get(registryKey), holderElementsClass, apiClass, implClass); - } - - private static final Map>, RegistryKeyField> REGISTRY_KEY_FIELDS; + public static final Map>, RegistryKeyField> REGISTRY_KEY_FIELDS; static { Map>, RegistryKeyField> registryKeyFields = new IdentityHashMap<>(); try { @@ -146,77 +88,104 @@ public final class RegistryEntries { REGISTRY_KEY_FIELDS = Collections.unmodifiableMap(registryKeyFields); } - public static final Set> REGISTRY_CLASS_NAME_BASED_ON_API = Set.of( - BlockType.class, - ItemType.class + private static final Map>, RegistryIntern> EXPOSED_REGISTRIES = Stream.of( + entry(Registries.GAME_EVENT, GameEvent.class), + entry(Registries.STRUCTURE_TYPE, StructureType.class), + entry(Registries.MOB_EFFECT, MobEffects.class), + entry(Registries.BLOCK, Blocks.class), + entry(Registries.ITEM, Items.class), + entry(Registries.VILLAGER_PROFESSION, VillagerProfession.class), + entry(Registries.VILLAGER_TYPE, VillagerType.class), + entry(Registries.MAP_DECORATION_TYPE, MapDecorationTypes.class), + entry(Registries.MENU, MenuType.class), + entry(Registries.ATTRIBUTE, Attributes.class), + entry(Registries.FLUID, Fluids.class), + entry(Registries.SOUND_EVENT, SoundEvents.class), + entry(Registries.DATA_COMPONENT_TYPE, DataComponents.class), + entry(Registries.BIOME, Biomes.class), + entry(Registries.STRUCTURE, BuiltinStructures.class), + entry(Registries.TRIM_MATERIAL, TrimMaterials.class), + entry(Registries.TRIM_PATTERN, TrimPatterns.class), + entry(Registries.DAMAGE_TYPE, DamageTypes.class), + entry(Registries.WOLF_VARIANT, WolfVariants.class), + entry(Registries.WOLF_SOUND_VARIANT, WolfSoundVariants.class), + entry(Registries.ENCHANTMENT, Enchantments.class), + entry(Registries.JUKEBOX_SONG, JukeboxSongs.class), + entry(Registries.BANNER_PATTERN, BannerPatterns.class), + entry(Registries.PAINTING_VARIANT, PaintingVariants.class), + entry(Registries.INSTRUMENT, Instruments.class), + entry(Registries.CAT_VARIANT, CatVariants.class), + entry(Registries.FROG_VARIANT, FrogVariants.class), + entry(Registries.CHICKEN_VARIANT, ChickenVariants.class), + entry(Registries.COW_VARIANT, CowVariants.class), + entry(Registries.PIG_VARIANT, PigVariants.class), + entry(Registries.DIALOG, Dialogs.class), + entry(Registries.ENTITY_TYPE, EntityType.class), + entry(Registries.PARTICLE_TYPE, ParticleTypes.class), + entry(Registries.POTION, Potions.class), + entry(Registries.MEMORY_MODULE_TYPE, MemoryModuleType.class) + ).collect(Collectors.toMap(RegistryIntern::getRegistryKey, entry -> entry)); + + @Deprecated + public static final List> API_ONLY = new ArrayList<>(); + + @Deprecated + public static final List>> API_ONLY_KEYS = List.of( + Registries.ENTITY_TYPE, Registries.PARTICLE_TYPE, Registries.POTION, Registries.MEMORY_MODULE_TYPE ); - public static final List> BUILT_IN = List.of( - entry(Registries.GAME_EVENT, net.minecraft.world.level.gameevent.GameEvent.class, GameEvent.class).writableApiRegistryBuilder(GameEventRegistryEntry.Builder.class, "PaperGameEventRegistryEntry.PaperBuilder"), - entry(Registries.STRUCTURE_TYPE, net.minecraft.world.level.levelgen.structure.StructureType.class, StructureType.class), - entry(Registries.MOB_EFFECT, MobEffects.class, PotionEffectType.class), - entry(Registries.BLOCK, Blocks.class, BlockType.class), - entry(Registries.ITEM, Items.class, ItemType.class), - entry(Registries.VILLAGER_PROFESSION, VillagerProfession.class, Villager.Profession.class), - entry(Registries.VILLAGER_TYPE, VillagerType.class, Villager.Type.class), - entry(Registries.MAP_DECORATION_TYPE, MapDecorationTypes.class, MapCursor.Type.class), - entry(Registries.MENU, net.minecraft.world.inventory.MenuType.class, MenuType.class), - entry(Registries.ATTRIBUTE, Attributes.class, Attribute.class).serializationUpdater("ATTRIBUTE_RENAME"), - entry(Registries.FLUID, Fluids.class, Fluid.class), - entry(Registries.SOUND_EVENT, SoundEvents.class, Sound.class).allowDirect().apiRegistryField("SOUNDS").apiRegistryBuilder(SoundEventRegistryEntry.Builder.class, "PaperSoundEventRegistryEntry.PaperBuilder", RegistryEntry.RegistryModificationApiSupport.NONE), - entry(Registries.DATA_COMPONENT_TYPE, DataComponents.class, DataComponentType.class, "Paper").preload(DataComponentTypes.class).apiAccessName("of") - ); + public static final Multimap> REGISTRIES = Util.make(MultimapBuilder.enumKeys(RegistryEntry.Type.class).arrayListValues().build(), map -> { + List>> remainingRegistries = new ArrayList<>(EXPOSED_REGISTRIES.keySet()); + DataFileLoader.REGISTRIES.forEach((type, file) -> { + Map>, RegistryData> registries = file.get(); + for (Map.Entry>, RegistryData> registry : registries.entrySet()) { + ResourceKey> registryKey = registry.getKey(); + RegistryIntern intern = Objects.requireNonNull(EXPOSED_REGISTRIES.get(registryKey), + () -> "Registry '%s' found in registry/%s.json is not exposed to the api".formatted(registryKey.location(), type.getSerializedName()) + ); + RegistryEntry entry = intern.bind(registry.getValue()); + entry.validate(type); + if (remainingRegistries.remove(registryKey)) { + if (API_ONLY_KEYS.contains(registryKey)) { + API_ONLY.add(entry); + } else { + map.put(type, entry); + } + } + } + }); - public static final List> DATA_DRIVEN = List.of( - entry(Registries.BIOME, Biomes.class, Biome.class).delayed(), - entry(Registries.STRUCTURE, BuiltinStructures.class, Structure.class).delayed(), - entry(Registries.TRIM_MATERIAL, TrimMaterials.class, TrimMaterial.class).allowDirect().delayed(), - entry(Registries.TRIM_PATTERN, TrimPatterns.class, TrimPattern.class).allowDirect().delayed(), - entry(Registries.DAMAGE_TYPE, DamageTypes.class, DamageType.class).writableApiRegistryBuilder(DamageTypeRegistryEntry.Builder.class, "PaperDamageTypeRegistryEntry.PaperBuilder").delayed(), - entry(Registries.WOLF_VARIANT, WolfVariants.class, Wolf.Variant.class).writableApiRegistryBuilder(WolfVariantRegistryEntry.Builder.class, "PaperWolfVariantRegistryEntry.PaperBuilder").delayed(), - entry(Registries.WOLF_SOUND_VARIANT, WolfSoundVariants.class, Wolf.SoundVariant.class), - entry(Registries.ENCHANTMENT, Enchantments.class, Enchantment.class).writableApiRegistryBuilder(EnchantmentRegistryEntry.Builder.class, "PaperEnchantmentRegistryEntry.PaperBuilder").serializationUpdater("ENCHANTMENT_RENAME").delayed(), - entry(Registries.JUKEBOX_SONG, JukeboxSongs.class, JukeboxSong.class).writableApiRegistryBuilder(JukeboxSongRegistryEntry.Builder.class, "PaperJukeboxSongRegistryEntry.PaperBuilder").delayed(), - entry(Registries.BANNER_PATTERN, BannerPatterns.class, PatternType.class).allowDirect().writableApiRegistryBuilder(BannerPatternRegistryEntry.Builder.class, "PaperBannerPatternRegistryEntry.PaperBuilder").delayed(), - entry(Registries.PAINTING_VARIANT, PaintingVariants.class, Art.class).writableApiRegistryBuilder(PaintingVariantRegistryEntry.Builder.class, "PaperPaintingVariantRegistryEntry.PaperBuilder").apiRegistryField("ART").delayed(), - entry(Registries.INSTRUMENT, Instruments.class, MusicInstrument.class).allowDirect().writableApiRegistryBuilder(InstrumentRegistryEntry.Builder.class, "PaperInstrumentRegistryEntry.PaperBuilder").delayed(), - entry(Registries.CAT_VARIANT, CatVariants.class, Cat.Type.class).writableApiRegistryBuilder(CatTypeRegistryEntry.Builder.class, "PaperCatTypeRegistryEntry.PaperBuilder").delayed(), - entry(Registries.FROG_VARIANT, FrogVariants.class, Frog.Variant.class).writableApiRegistryBuilder(FrogVariantRegistryEntry.Builder.class, "PaperFrogVariantRegistryEntry.PaperBuilder").delayed(), - entry(Registries.CHICKEN_VARIANT, ChickenVariants.class, Chicken.Variant.class).writableApiRegistryBuilder(ChickenVariantRegistryEntry.Builder.class, "PaperChickenVariantRegistryEntry.PaperBuilder"), - 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.DIALOG, Dialogs.class, Dialog.class, "Paper").allowDirect().writableApiRegistryBuilder(DialogRegistryEntry.Builder.class, "PaperDialogRegistryEntry.PaperBuilder") - ); + if (!remainingRegistries.isEmpty()) { + throw new IllegalStateException("Registry not found in data files: " + remainingRegistries); + } + }); - public static final List> API_ONLY = List.of( - entry(Registries.ENTITY_TYPE, net.minecraft.world.entity.EntityType.class, EntityType.class), - entry(Registries.PARTICLE_TYPE, ParticleTypes.class, Particle.class), - entry(Registries.POTION, Potions.class, PotionType.class), - entry(Registries.MEMORY_MODULE_TYPE, MemoryModuleType.class, MemoryKey.class) - ); + public static Collection> byType(RegistryEntry.Type type) { + return REGISTRIES.get(type); + } public static final Map>, RegistryEntry> BY_REGISTRY_KEY; static { - Map>, RegistryEntry> byRegistryKey = new IdentityHashMap<>(BUILT_IN.size() + DATA_DRIVEN.size() + API_ONLY.size()); + Map>, RegistryEntry> byRegistryKey = new IdentityHashMap<>(REGISTRIES.size() + API_ONLY.size()); forEach(entry -> { - byRegistryKey.put(entry.registryKey(), entry); - }, RegistryEntries.BUILT_IN, RegistryEntries.DATA_DRIVEN, RegistryEntries.API_ONLY); + byRegistryKey.put(entry.getRegistryKey(), entry); + }, REGISTRIES.values(), API_ONLY); BY_REGISTRY_KEY = Collections.unmodifiableMap(byRegistryKey); } @SuppressWarnings("unchecked") public static RegistryEntry byRegistryKey(ResourceKey> registryKey) { - return (RegistryEntry) Objects.requireNonNull(BY_REGISTRY_KEY.get(registryKey)); + return (RegistryEntry) Objects.requireNonNull(BY_REGISTRY_KEY.get(registryKey), "registry not found: " + registryKey); } // real registries public static void forEach(Consumer> callback) { - forEach(callback, RegistryEntries.BUILT_IN, RegistryEntries.DATA_DRIVEN); + forEach(callback, REGISTRIES.values()); } @SafeVarargs - public static void forEach(Consumer> callback, List>... datas) { - for (List> data : datas) { + public static void forEach(Consumer> callback, Collection>... datas) { + for (Collection> data : datas) { for (RegistryEntry entry : data) { callback.accept(entry); } diff --git a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntry.java b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntry.java index 86e8c53f56..a6dedda2da 100644 --- a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntry.java +++ b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntry.java @@ -2,59 +2,42 @@ package io.papermc.generator.registry; import com.google.common.base.Preconditions; import io.papermc.generator.Main; +import io.papermc.generator.resources.data.RegistryData; import io.papermc.generator.utils.ClassHelper; -import java.lang.constant.ConstantDescs; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.util.Collections; import java.util.IdentityHashMap; import java.util.Map; -import java.util.Optional; import java.util.function.Function; -import javax.lang.model.SourceVersion; import net.minecraft.core.Holder; import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceKey; -import org.bukkit.Keyed; +import net.minecraft.util.StringRepresentable; import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; @NullMarked -public final class RegistryEntry { +public class RegistryEntry implements RegistryIdentifiable { private final ResourceKey> registryKey; private final RegistryKeyField registryKeyField; - private final Class elementClass; private final Class holderElementsClass; - private boolean allowDirect; - - private final Class apiClass; // TODO remove Keyed - private Class preloadClass; - private final String implClass; - - private @Nullable RegistryModificationApiSupport modificationApiSupport; - private @Nullable Class apiRegistryBuilder; - private @Nullable String apiRegistryBuilderImpl; - - private @Nullable String fieldRename; - private boolean delayed; - private String apiAccessName = ConstantDescs.INIT_NAME; - private Optional apiRegistryField = Optional.empty(); + private final RegistryData data; private @Nullable Map, String> fieldNames; - public RegistryEntry(ResourceKey> registryKey, RegistryKeyField registryKeyField, Class holderElementsClass, Class apiClass, String implClass) { + protected RegistryEntry(ResourceKey> registryKey, RegistryKeyField registryKeyField, Class holderElementsClass, RegistryData data) { this.registryKey = registryKey; this.registryKeyField = registryKeyField; - this.elementClass = registryKeyField.elementClass(); this.holderElementsClass = holderElementsClass; - this.apiClass = apiClass; - this.preloadClass = apiClass; - this.implClass = implClass; + this.data = data; } - public ResourceKey> registryKey() { + @Override + public ResourceKey> getRegistryKey() { return this.registryKey; } @@ -62,123 +45,55 @@ public final class RegistryEntry { return Main.REGISTRY_ACCESS.lookupOrThrow(this.registryKey); } + public Class elementClass() { + return this.registryKeyField.elementClass(); + } + public String registryKeyField() { return this.registryKeyField.name(); } - public Class apiClass() { - return this.apiClass; + public RegistryData data() { + return this.data; } - public String implClass() { - return this.implClass; - } - - public RegistryEntry allowDirect() { - this.allowDirect = true; - return this; - } - - public RegistryEntry delayed() { - this.delayed = true; - return this; - } - - public RegistryEntry preload(Class klass) { - this.preloadClass = klass; - return this; - } - - public RegistryEntry apiAccessName(String name) { - Preconditions.checkArgument(SourceVersion.isIdentifier(name) && !SourceVersion.isKeyword(name), "Invalid accessor name"); - this.apiAccessName = name; - return this; - } - - public RegistryEntry serializationUpdater(String fieldName) { - this.fieldRename = fieldName; - return this; - } - - public boolean canAllowDirect() { - return this.allowDirect; - } - - public boolean isDelayed() { - return this.delayed; - } - - public String apiAccessName() { - return this.apiAccessName; - } - - public Class preloadClass() { - return this.preloadClass; - } - - public @Nullable String fieldRename() { - return this.fieldRename; - } - - public @Nullable Class apiRegistryBuilder() { - return this.apiRegistryBuilder; - } - - public @Nullable String apiRegistryBuilderImpl() { - return this.apiRegistryBuilderImpl; - } - - public @Nullable RegistryModificationApiSupport modificationApiSupport() { - return this.modificationApiSupport; - } - - public RegistryEntry writableApiRegistryBuilder(Class builderClass, String builderImplClass) { - return this.apiRegistryBuilder(builderClass, builderImplClass, RegistryModificationApiSupport.WRITABLE); - } - - public RegistryEntry apiRegistryBuilder(Class builderClass, String builderImplClass, RegistryModificationApiSupport modificationApiSupport) { - this.apiRegistryBuilder = builderClass; - this.apiRegistryBuilderImpl = builderImplClass; - this.modificationApiSupport = modificationApiSupport; - return this; - } - - public Optional apiRegistryField() { - return this.apiRegistryField; - } - - public RegistryEntry apiRegistryField(String registryField) { - this.apiRegistryField = Optional.of(registryField); - return this; + protected void validate(Type type) { + boolean isBuiltIn = type == Type.BUILT_IN; + Type realType = type == Type.BUILT_IN ? Type.DATA_DRIVEN : Type.BUILT_IN; + Preconditions.checkState(isBuiltIn == BuiltInRegistries.REGISTRY.containsKey(this.registryKey.location()), // type is checked at runtime and not guessed in case api/impl change is needed + "Mismatch type, registry '%s' is %s but was in registry/%s.json", this.registryKey.location(), realType.getSerializedName(), type.getSerializedName() + ); + Preconditions.checkState(type != Type.BUILT_IN || !this.data.impl().delayed(), "Built-in registry '%s' cannot be delayed!", this.registryKey.location()); } public String keyClassName() { - if (RegistryEntries.REGISTRY_CLASS_NAME_BASED_ON_API.contains(this.apiClass)) { - return this.apiClass.getSimpleName(); + if (this.data.api().keyClassNameRelate()) { + return this.data.api().klass().name().simpleName(); } - return this.elementClass.getSimpleName(); + return this.elementClass().getSimpleName(); } public boolean allowCustomKeys() { - return (this.apiRegistryBuilder != null && this.modificationApiSupport.canAdd()) || RegistryEntries.DATA_DRIVEN.contains(this); + return (this.data.builder().isPresent() && this.data.builder().get().capability().canAdd()) || RegistryEntries.byType(Type.DATA_DRIVEN).contains(this); } private Map, TO> getFields(Map, TO> map, Function transform) { Registry registry = this.registry(); + Class elementClass = this.elementClass(); try { for (Field field : this.holderElementsClass.getDeclaredFields()) { - if (!ResourceKey.class.isAssignableFrom(field.getType()) && !Holder.Reference.class.isAssignableFrom(field.getType()) && !this.elementClass.isAssignableFrom(field.getType())) { + if (!ResourceKey.class.isAssignableFrom(field.getType()) && !Holder.Reference.class.isAssignableFrom(field.getType()) && !elementClass.isAssignableFrom(field.getType())) { continue; } if (ClassHelper.isStaticConstant(field, Modifier.PUBLIC)) { ResourceKey key = null; - if (this.elementClass.isAssignableFrom(field.getType())) { - key = registry.getResourceKey(this.elementClass.cast(field.get(null))).orElseThrow(); + if (elementClass.isAssignableFrom(field.getType())) { + key = registry.getResourceKey(elementClass.cast(field.get(null))).orElseThrow(); } else { if (field.getGenericType() instanceof ParameterizedType complexType && complexType.getActualTypeArguments().length == 1 && - complexType.getActualTypeArguments()[0] == this.elementClass) { + complexType.getActualTypeArguments()[0] == elementClass) { if (Holder.Reference.class.isAssignableFrom(field.getType())) { key = ((Holder.Reference) field.get(null)).key(); @@ -217,19 +132,23 @@ public final class RegistryEntry { return "RegistryEntry[" + "registryKey=" + this.registryKey + ", " + "registryKeyField=" + this.registryKeyField + ", " + - "apiClass=" + this.apiClass + ", " + - "implClass=" + this.implClass + ", " + + "data=" + this.data + ']'; } - public enum RegistryModificationApiSupport { - NONE, - ADDABLE, - MODIFIABLE, - WRITABLE; + public enum Type implements StringRepresentable { - public boolean canAdd() { - return this != MODIFIABLE && this != NONE; + BUILT_IN("built_in"), + DATA_DRIVEN("data_driven"); + + private final String name; + Type(String name) { + this.name = name; + } + + @Override + public String getSerializedName() { + return this.name; } } } diff --git a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryIdentifiable.java b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryIdentifiable.java new file mode 100644 index 0000000000..03fee18532 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryIdentifiable.java @@ -0,0 +1,11 @@ +package io.papermc.generator.registry; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public interface RegistryIdentifiable { + + ResourceKey> getRegistryKey(); +} diff --git a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryIntern.java b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryIntern.java new file mode 100644 index 0000000000..0a1fcae8bd --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryIntern.java @@ -0,0 +1,22 @@ +package io.papermc.generator.registry; + +import io.papermc.generator.resources.data.RegistryData; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public record RegistryIntern(ResourceKey> registryKey, RegistryKeyField registryKeyField, Class holderElementsClass) implements RegistryIdentifiable { + public RegistryIntern(ResourceKey> registryKey, Class holderElementsClass) { + this(registryKey, (RegistryKeyField) RegistryEntries.REGISTRY_KEY_FIELDS.get(registryKey), holderElementsClass); + } + + @Override + public ResourceKey> getRegistryKey() { + return this.registryKey; + } + + public RegistryEntry bind(RegistryData data) { + return new RegistryEntry<>(this.registryKey, this.registryKeyField, this.holderElementsClass, data); + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/DataFile.java b/paper-generator/src/main/java/io/papermc/generator/resources/DataFile.java new file mode 100644 index 0000000000..8cc6bb61e7 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/DataFile.java @@ -0,0 +1,182 @@ +package io.papermc.generator.resources; + +import com.google.gson.FormattingStyle; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.JsonOps; +import io.papermc.generator.Main; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.stream.Collectors; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.jetbrains.annotations.VisibleForTesting; + +public abstract class DataFile { + + private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().setFormattingStyle(FormattingStyle.PRETTY).create(); + + private final String path; + protected final Codec codec; + protected final DynamicOps requiredOps; + private final Transmuter transmuter; + private final boolean requireRegistry; + private @MonotonicNonNull V value; + + protected DataFile(String path, Codec codec, Transmuter transmuter, boolean requireRegistry) { + this.path = path; + this.codec = codec; + this.transmuter = transmuter; + this.requireRegistry = requireRegistry; + this.requiredOps = this.getRequiredOps(JsonOps.INSTANCE); + } + + protected DataFile(String path, Codec codec, Transmuter transmuter) { + this(path, codec, transmuter, false); + } + + public V get() { + if (this.value == null) { + this.value = this.readUnchecked(); + } + return this.value; + } + + public V readUnchecked() { + try { + return this.read(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public V read() throws IOException { + try (Reader input = new BufferedReader(new InputStreamReader(DataFile.class.getClassLoader().getResourceAsStream(this.path)))) { + JsonElement predicates = GSON.fromJson(input, JsonElement.class); + return this.codec.parse(this.requiredOps, predicates).getOrThrow(JsonParseException::new); + } + } + + public SliceResult slice(){ + return this.transmuter.examine(this.get()); + } + + public SliceResult upgrade(Path destination) throws IOException { + if (!(this.transmuter instanceof Transmuter.Mutable mutableTransmuter)) { + return SliceResult.empty(); + } + + SliceResult result = this.slice(); + this.value = mutableTransmuter.apply(this.value, result); + + Files.writeString(destination, this.toJsonString(this.value) + "\n", StandardCharsets.UTF_8); + return result; + } + + public String toJsonString(V value) { + JsonElement element = this.codec.encodeStart(this.requiredOps, value).getOrThrow(); + return GSON.toJson(element); + } + + public abstract FlattenSliceResult print(SliceResult result); + + public String path() { + return this.path; + } + + @VisibleForTesting + public Codec codec() { + return this.codec; + } + + @VisibleForTesting + public DynamicOps getRequiredOps(DynamicOps ops) { + if (this.requireRegistry) { + return Main.REGISTRY_ACCESS.createSerializationContext(ops); + } + return ops; + } + + @Override + public String toString() { + return "DataFile[path=" + this.path + ']'; + } + + public static class Map extends DataFile, java.util.Map.Entry, K> { + public Map(String path, Codec> codec, Transmuter, java.util.Map.Entry, K> transmuter, boolean requireRegistry) { + super(path, codec, transmuter, requireRegistry); + } + + public Map(String path, Codec> codec, Transmuter, java.util.Map.Entry, K> transmuter) { + super(path, codec, transmuter); + } + + @Override + public FlattenSliceResult print(SliceResult, K> result) { + String newEntries = null; + String dropEntries = null; + if (!result.added().isEmpty()) { + java.util.Map added = result.added().stream().collect(Collectors.toMap(java.util.Map.Entry::getKey, java.util.Map.Entry::getValue)); + newEntries = this.toJsonString(added); + } + + if (!result.removed().isEmpty()) { + java.util.Map removed = new HashMap<>(result.removed().size()); + result.removed().forEach(key -> removed.put(key, null)); + + JsonElement dropElement = this.codec.encodeStart(this.requiredOps, removed).getOrThrow(); + if (dropElement instanceof JsonObject object) { + JsonArray array = new JsonArray(object.size()); + for (String key : object.keySet()) { + array.add(key); + } + dropEntries = GSON.toJson(array); + } + } + + return new FlattenSliceResult<>( + newEntries, + dropEntries + ); + } + } + + public static class List extends DataFile, E, E> { + public List(String path, Codec> codec, Transmuter, E, E> transmuter, boolean requireRegistry) { + super(path, codec, transmuter, requireRegistry); + } + + public List(String path, Codec> codec, Transmuter, E, E> transmuter) { + super(path, codec, transmuter); + } + + @Override + public FlattenSliceResult print(SliceResult result) { + String newEntries = null; + String dropEntries = null; + if (!result.added().isEmpty()) { + newEntries = this.toJsonString(java.util.List.copyOf(result.added())); + } + + if (!result.removed().isEmpty()) { + dropEntries = this.toJsonString(java.util.List.copyOf(result.removed())); + } + + return new FlattenSliceResult<>( + newEntries, + dropEntries + ); + } + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/DataFileLoader.java b/paper-generator/src/main/java/io/papermc/generator/resources/DataFileLoader.java new file mode 100644 index 0000000000..bb08af218b --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/DataFileLoader.java @@ -0,0 +1,218 @@ +package io.papermc.generator.resources; + +import com.google.common.base.Suppliers; +import com.google.common.collect.Sets; +import com.google.common.reflect.TypeToken; +import com.mojang.serialization.Codec; +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ScanResult; +import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.registry.RegistryEntry; +import io.papermc.generator.resources.data.EntityClassData; +import io.papermc.generator.resources.data.EntityTypeData; +import io.papermc.generator.resources.data.ItemMetaData; +import io.papermc.generator.resources.data.RegistryData; +import io.papermc.generator.resources.predicate.BlockPredicate; +import io.papermc.generator.resources.predicate.ItemPredicate; +import io.papermc.generator.utils.BasePackage; +import io.papermc.generator.utils.ClassHelper; +import io.papermc.generator.utils.Formatting; +import io.papermc.generator.utils.SourceCodecs; +import io.papermc.typewriter.ClassNamed; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import net.minecraft.Util; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.vehicle.AbstractBoat; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + +public class DataFileLoader { + + private static Transmuter, Map.Entry, K> sortedMap(Comparator comparator) { + return transmuteMap(SliceResult::empty, comparator); + } + + private static Transmuter, Map.Entry, K> transmuteMap(Supplier> typesProvider, Function onMissing, Comparator comparator) { + return transmuteMap(map -> { + Set types = typesProvider.get(); + Set registeredTypes = map.keySet(); + + Set> added = new HashSet<>(); + Sets.difference(types, registeredTypes).forEach(missingType -> added.add(Map.entry(missingType, onMissing.apply(missingType)))); + Set removed = new HashSet<>(Sets.difference(registeredTypes, types)); + return new SliceResult<>(added, removed); + }, comparator); + } + + private static Transmuter, Map.Entry, K> transmuteMap(Function, SliceResult, K>> slicer, Comparator comparator) { + return new Transmuter.Mutable<>() { + + @Override + public SliceResult, K> examine(Map original) { + return slicer.apply(original); + } + + @Override + public Map apply(Map original, SliceResult, K> result) { + Map map = new TreeMap<>(comparator); + map.putAll(original); + result.added().forEach(entry -> map.put(entry.getKey(), entry.getValue())); + result.removed().forEach(map::remove); + return map; + } + }; + } + + private static final @MonotonicNonNull Map>, DataFile> DATA_FILES = new HashMap<>(); + public static final @MonotonicNonNull Map>, DataFile> DATA_FILES_VIEW = Collections.unmodifiableMap(DATA_FILES); + + private static final Supplier>, Class>> ENTITY_TYPE_GENERICS = Suppliers.memoize(() -> RegistryEntries.byRegistryKey(Registries.ENTITY_TYPE).getFields(field -> { + if (field.getGenericType() instanceof ParameterizedType complexType && complexType.getActualTypeArguments().length == 1) { + return (Class) complexType.getActualTypeArguments()[0]; + } + return null; + })); + + public static final Map>, RegistryData>> REGISTRIES = Collections.unmodifiableMap(Util.make(new EnumMap<>(RegistryEntry.Type.class), map -> { + Codec>, RegistryData>> codec = Codec.lazyInitialized(() -> Codec.unboundedMap(SourceCodecs.REGISTRY_KEY, RegistryData.CODEC)); + for (RegistryEntry.Type type : RegistryEntry.Type.values()) { + ResourceKey>, RegistryData>> key = DataFiles.registry(type); + map.put(type, register(key, path -> { + return new DataFile.Map<>(path, codec, SliceResult::empty); + })); + } + })); + + static { + // todo remove Orientation once the duplicate enum is gone and then possibly check enum property types conflict instead + register(DataFiles.BLOCK_STATE_AMBIGUOUS_NAMES, () -> Codec.unboundedMap( + SourceCodecs.IDENTIFIER, ExtraCodecs.nonEmptyList(SourceCodecs.IDENTIFIER.listOf()) + ), + (path, codec) -> new DataFile.Map<>( + path, codec, SliceResult::empty + )); + + register(DataFiles.BLOCK_STATE_ENUM_PROPERTY_TYPES, () -> Codec.unboundedMap( + SourceCodecs.classCodec(new TypeToken>() {}), SourceCodecs.CLASS_NAME + ), + (path, codec) -> new DataFile.Map<>( + path, codec, + transmuteMap(() -> { + try { + Set>> enumPropertyTypes = Collections.newSetFromMap(new IdentityHashMap<>()); + for (Field field : BlockStateProperties.class.getDeclaredFields()) { + if (ClassHelper.isStaticConstant(field, Modifier.PUBLIC)) { + if (!EnumProperty.class.isAssignableFrom(field.getType())) { + continue; + } + + enumPropertyTypes.add(((EnumProperty) field.get(null)).getValueClass()); + } + } + return Collections.unmodifiableSet(enumPropertyTypes); + } catch (ReflectiveOperationException ex) { + throw new RuntimeException(ex); + } + }, + missingType -> BasePackage.BUKKIT.relativeClass("block.data.type", missingType.getSimpleName()), + Comparator.comparing(Class::getCanonicalName)) + )); + + // order matters: instance_of / is_class -> has_property -> contains_property + register(DataFiles.BLOCK_STATE_PREDICATES, () -> Codec.unboundedMap( + SourceCodecs.CLASS_NAMED, ExtraCodecs.compactListCodec(BlockPredicate.CODEC, ExtraCodecs.nonEmptyList(BlockPredicate.CODEC.listOf())) + ), + (path, codec) -> new DataFile.Map<>( + path, codec, SliceResult::empty + )); + + register(DataFiles.ITEM_META_BRIDGE, () -> Codec.unboundedMap(SourceCodecs.CLASS_NAMED, ItemMetaData.CODEC), + (path, codec) -> new DataFile.Map<>( + path, codec, sortedMap(Comparator.comparing(ClassNamed::canonicalName)) + )); + + // order matters + register(DataFiles.ITEM_META_PREDICATES, () -> Codec.unboundedMap( + SourceCodecs.CLASS_NAMED, ExtraCodecs.nonEmptyList(ItemPredicate.CODEC.listOf()) + ), + (path, codec) -> new DataFile.Map<>( + path, codec, SliceResult::empty, true + )); + + register(DataFiles.ENTITY_TYPES, () -> Codec.unboundedMap(ResourceKey.codec(Registries.ENTITY_TYPE), EntityTypeData.CODEC), + (path, codec) -> new DataFile.Map<>( + path, codec, + transmuteMap(() -> BuiltInRegistries.ENTITY_TYPE.listElementIds().collect(Collectors.toSet()), + missingType -> { + Class genericType = ENTITY_TYPE_GENERICS.get().get(missingType); + + String packageName = BasePackage.BUKKIT.name().concat(".entity"); + if (AbstractBoat.class.isAssignableFrom(genericType)) { + packageName += ".boat"; + } else if (AbstractMinecart.class.isAssignableFrom(genericType)) { + packageName += ".minecart"; + } + + return new EntityTypeData(ClassNamed.of(packageName, genericType.getSimpleName())); + }, + Formatting.alphabeticKeyOrder(key -> key.location().getPath())) + )); + + register(DataFiles.ENTITY_CLASS_NAMES, () -> Codec.unboundedMap(SourceCodecs.classCodec(Mob.class), EntityClassData.CODEC), + (path, codec) -> new DataFile.Map<>( + path, codec, + transmuteMap(() -> { + try (ScanResult scanResult = new ClassGraph().enableClassInfo().acceptPackages(Entity.class.getPackageName()).scan()) { + Set> classes = new HashSet<>(scanResult.getSubclasses(Mob.class.getName()).loadClasses(Mob.class)); + if (classes.isEmpty()) { + throw new IllegalStateException("There are supposed to be more than 0 mob classes!"); + } + + classes.add(Mob.class); + return Collections.unmodifiableSet(classes); + } + }, + missingType -> new EntityClassData(BasePackage.BUKKIT.relativeClass("entity", missingType.getSimpleName())), + Comparator.comparing(Class::getCanonicalName)) + )); + } + + public static V get(ResourceKey> key) { + return ((DataFile) DATA_FILES.get(key)).get(); + } + + private static void register(ResourceKey> key, Supplier> codec, BiFunction, DataFile> maker) { + register(key, path -> maker.apply(path, Codec.lazyInitialized(codec))); + } + + private static > F register(ResourceKey key, Function maker) { + F file = maker.apply("data/%s.json".formatted(key.location().getPath())); + DATA_FILES.put(key, file); + return file; + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/DataFiles.java b/paper-generator/src/main/java/io/papermc/generator/resources/DataFiles.java new file mode 100644 index 0000000000..083ac95627 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/DataFiles.java @@ -0,0 +1,44 @@ +package io.papermc.generator.resources; + +import com.squareup.javapoet.ClassName; +import io.papermc.generator.registry.RegistryEntry; +import io.papermc.generator.resources.data.EntityClassData; +import io.papermc.generator.resources.data.EntityTypeData; +import io.papermc.generator.resources.data.ItemMetaData; +import io.papermc.generator.resources.data.RegistryData; +import io.papermc.generator.resources.predicate.BlockPredicate; +import io.papermc.generator.resources.predicate.ItemPredicate; +import io.papermc.typewriter.ClassNamed; +import java.util.List; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; + +public final class DataFiles { + + private static final ResourceKey>> REGISTRY_KEY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath("paper", "data_file")); + + public static final ResourceKey>> BLOCK_STATE_AMBIGUOUS_NAMES = store("block_state/ambiguous_names"); + public static final ResourceKey>, ClassName>> BLOCK_STATE_ENUM_PROPERTY_TYPES = store("block_state/enum_property_types"); + public static final ResourceKey>> BLOCK_STATE_PREDICATES = store("block_state/predicates"); + + public static final ResourceKey> ITEM_META_BRIDGE = store("item_meta/bridge"); + public static final ResourceKey>> ITEM_META_PREDICATES = store("item_meta/predicates"); + + public static ResourceKey>, RegistryData>> registry(RegistryEntry.Type type) { + return store("registry/%s".formatted(type.getSerializedName())); + } + + public static final ResourceKey>, EntityTypeData>> ENTITY_TYPES = store("entity_types"); + public static final ResourceKey, EntityClassData>> ENTITY_CLASS_NAMES = store("entity_class_names"); + + private static > ResourceKey store(String name) { + return (ResourceKey) ResourceKey.create(REGISTRY_KEY, ResourceLocation.fromNamespaceAndPath("paper", name)); + } + + private DataFiles() { + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/FlattenSliceResult.java b/paper-generator/src/main/java/io/papermc/generator/resources/FlattenSliceResult.java new file mode 100644 index 0000000000..4e4418a156 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/FlattenSliceResult.java @@ -0,0 +1,6 @@ +package io.papermc.generator.resources; + +import org.jspecify.annotations.Nullable; + +public record FlattenSliceResult(@Nullable A added, @Nullable R removed) { +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/ParameterizedClass.java b/paper-generator/src/main/java/io/papermc/generator/resources/ParameterizedClass.java new file mode 100644 index 0000000000..b61b848a90 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/ParameterizedClass.java @@ -0,0 +1,99 @@ +package io.papermc.generator.resources; + +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.WildcardTypeName; +import io.papermc.generator.types.Types; +import io.papermc.generator.utils.SourceCodecs; +import io.papermc.typewriter.ClassNamed; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.function.Function; +import net.minecraft.util.ExtraCodecs; + +public record ParameterizedClass(ClassNamed klass, List arguments) { + public ParameterizedClass(ClassNamed value) { + this(value, List.of()); + } + + private static Codec directCodec(Codec codec) { + return RecordCodecBuilder.create(instance -> instance.group( + SourceCodecs.CLASS_NAMED.fieldOf("class").forGetter(ParameterizedClass::klass), + ExtraCodecs.compactListCodec(codec).optionalFieldOf("arguments", List.of()).forGetter(ParameterizedClass::arguments) + ).apply(instance, ParameterizedClass::new)); + } + + public static final Codec CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAMED.xmap(ParameterizedClass::new, ParameterizedClass::klass); + + public static final Codec CODEC = Codec.recursive("ParameterizedClass", codec -> { + return Codec.either(CLASS_ONLY_CODEC, directCodec(codec)).xmap(Either::unwrap, parameterizedClass -> { + if (parameterizedClass.arguments().isEmpty()) { + return Either.left(parameterizedClass); + } + return Either.right(parameterizedClass); + }); + }); + + public TypeName getType() { + ClassName rawType = Types.typed(this.klass); + if (!this.arguments.isEmpty()) { + List convertedArgs = new ArrayList<>(this.arguments.size()); + for (ParameterizedClass argument : this.arguments) { + convertedArgs.add(argument.getType()); + } + + return ParameterizedTypeName.get(rawType, convertedArgs.toArray(TypeName[]::new)); + } + + return rawType; + } + + public void appendType(StringBuilder builder, Function imported) { + builder.append(imported.apply(this.klass)); + if (!this.arguments.isEmpty()) { + builder.append('<'); + for (ParameterizedClass argument : this.arguments) { + argument.appendType(builder, imported); + } + builder.append('>'); + } + } + + public static TypeName getAsWildcardType(ClassName rawType, List wildcardClasses) { + if (!wildcardClasses.isEmpty()) { + TypeName[] wildcards = new TypeName[wildcardClasses.size()]; + for (int i = 0; i < wildcardClasses.size(); i ++) { + wildcards[i] = WildcardTypeName.subtypeOf(wildcardClasses.get(i).getType()); + } + return ParameterizedTypeName.get(rawType, wildcards); + } + return rawType; + } + + public static void appendAsWildcardType(StringBuilder builder, ClassNamed rawType, List wildcardClasses, Function imported) { + builder.append(imported.apply(rawType)); + int size = wildcardClasses.size(); + if (size != 0) { + builder.append('<'); + Iterator iterator = wildcardClasses.iterator(); + while (iterator.hasNext()) { + ParameterizedClass wildcard = iterator.next(); + if (wildcard.arguments().isEmpty() && wildcard.klass().canonicalName().equals(Object.class.getCanonicalName())) { + builder.append('?'); + } else { + builder.append("? extends "); + wildcard.appendType(builder, imported); + } + if (iterator.hasNext()) { + builder.append(", "); + } + } + builder.append('>'); + } + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/SliceResult.java b/paper-generator/src/main/java/io/papermc/generator/resources/SliceResult.java new file mode 100644 index 0000000000..f069f64a19 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/SliceResult.java @@ -0,0 +1,19 @@ +package io.papermc.generator.resources; + +import java.util.Collections; +import java.util.Set; + +public record SliceResult(Set added, Set removed) { + + static SliceResult empty() { + return new SliceResult<>(Collections.emptySet(), Collections.emptySet()); + } + + static SliceResult empty(V value) { + return empty(); + } + + public boolean isEmpty() { + return this.added.isEmpty() && this.removed.isEmpty(); + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/Transmuter.java b/paper-generator/src/main/java/io/papermc/generator/resources/Transmuter.java new file mode 100644 index 0000000000..c5e8f768ec --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/Transmuter.java @@ -0,0 +1,11 @@ +package io.papermc.generator.resources; + +public interface Transmuter { + + SliceResult examine(V original); + + interface Mutable extends Transmuter { + + V apply(V original, SliceResult result); + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/data/EntityClassData.java b/paper-generator/src/main/java/io/papermc/generator/resources/data/EntityClassData.java new file mode 100644 index 0000000000..a7b614c05c --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/data/EntityClassData.java @@ -0,0 +1,28 @@ +package io.papermc.generator.resources.data; + +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.squareup.javapoet.ClassName; +import io.papermc.generator.utils.SourceCodecs; + +public record EntityClassData(ClassName name, boolean hasSpecifier) { + + public EntityClassData(ClassName name) { + this(name, true); + } + + public static final Codec DIRECT_CODEC = RecordCodecBuilder.create(instance -> instance.group( + SourceCodecs.CLASS_NAME.fieldOf("name").forGetter(EntityClassData::name), + Codec.BOOL.optionalFieldOf("has_specifier", true).forGetter(EntityClassData::hasSpecifier) + ).apply(instance, EntityClassData::new)); + + private static final Codec CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAME.xmap(EntityClassData::new, EntityClassData::name); + + public static final Codec CODEC = Codec.either(CLASS_ONLY_CODEC, DIRECT_CODEC).xmap(Either::unwrap, data -> { + if (!data.hasSpecifier()) { + return Either.right(data); + } + return Either.left(data); + }); +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/data/EntityTypeData.java b/paper-generator/src/main/java/io/papermc/generator/resources/data/EntityTypeData.java new file mode 100644 index 0000000000..96befaa9ad --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/data/EntityTypeData.java @@ -0,0 +1,31 @@ +package io.papermc.generator.resources.data; + +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import io.papermc.generator.utils.SourceCodecs; +import io.papermc.typewriter.ClassNamed; +import net.minecraft.util.ExtraCodecs; + +public record EntityTypeData(ClassNamed api, int legacyId) { + + private static final int NO_LEGACY_ID = -1; + + public EntityTypeData(ClassNamed api) { + this(api, NO_LEGACY_ID); + } + + public static final Codec DIRECT_CODEC = RecordCodecBuilder.create(instance -> instance.group( + SourceCodecs.CLASS_NAMED.fieldOf("api").forGetter(EntityTypeData::api), + ExtraCodecs.intRange(-1, Integer.MAX_VALUE).optionalFieldOf("legacy_id", NO_LEGACY_ID).deprecated(13).forGetter(EntityTypeData::legacyId) + ).apply(instance, EntityTypeData::new)); + + private static final Codec CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAMED.xmap(EntityTypeData::new, EntityTypeData::api); + + public static final Codec CODEC = Codec.either(CLASS_ONLY_CODEC, DIRECT_CODEC).xmap(Either::unwrap, data -> { + if (data.legacyId() != NO_LEGACY_ID) { + return Either.right(data); + } + return Either.left(data); + }); +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/data/ItemMetaData.java b/paper-generator/src/main/java/io/papermc/generator/resources/data/ItemMetaData.java new file mode 100644 index 0000000000..8f0c8f9e5d --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/data/ItemMetaData.java @@ -0,0 +1,15 @@ +package io.papermc.generator.resources.data; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import io.papermc.generator.utils.SourceCodecs; +import io.papermc.typewriter.ClassNamed; + +@Deprecated +public record ItemMetaData(ClassNamed api, String field) { + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + SourceCodecs.CLASS_NAMED.fieldOf("api").forGetter(ItemMetaData::api), + SourceCodecs.IDENTIFIER.fieldOf("field").forGetter(ItemMetaData::field) + ).apply(instance, ItemMetaData::new)); +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/data/RegistryData.java b/paper-generator/src/main/java/io/papermc/generator/resources/data/RegistryData.java new file mode 100644 index 0000000000..45157ffdeb --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/data/RegistryData.java @@ -0,0 +1,160 @@ +package io.papermc.generator.resources.data; + +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.squareup.javapoet.TypeName; +import io.papermc.generator.resources.ParameterizedClass; +import io.papermc.generator.types.Types; +import io.papermc.generator.utils.SourceCodecs; +import io.papermc.typewriter.ClassNamed; +import java.lang.constant.ConstantDescs; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.StringRepresentable; + +public record RegistryData( + Api api, + Impl impl, + Optional builder, + Optional serializationUpdaterField, + boolean allowInline +) { + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Api.CODEC.fieldOf("api").forGetter(RegistryData::api), + Impl.CODEC.fieldOf("impl").forGetter(RegistryData::impl), + Builder.CODEC.optionalFieldOf("builder").forGetter(RegistryData::builder), + SourceCodecs.IDENTIFIER.optionalFieldOf("serialization_updater_field").forGetter(RegistryData::serializationUpdaterField), + Codec.BOOL.optionalFieldOf("allow_inline", false).forGetter(RegistryData::allowInline) + ).apply(instance, RegistryData::new)); + + public record Api(Class klass, Optional holderClass, boolean keyClassNameRelate, Optional registryField) { + public Api(ClassNamed klass) { + this(new Class(klass), Optional.of(new HolderClass(klass)), false, Optional.empty()); + } + + public static final Codec DIRECT_CODEC = RecordCodecBuilder.create(instance -> instance.group( + Class.CODEC.fieldOf("class").forGetter(Api::klass), + HolderClass.CODEC.optionalFieldOf("holder_class").forGetter(Api::holderClass), + Codec.BOOL.optionalFieldOf("key_class_name_relate", false).forGetter(Api::keyClassNameRelate), + SourceCodecs.IDENTIFIER.optionalFieldOf("registry_field").forGetter(Api::registryField) + ).apply(instance, Api::new)); + + public static final Codec CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAMED.xmap(Api::new, api -> api.klass().name()); + + public static final Codec CODEC = Codec.either(CLASS_ONLY_CODEC, DIRECT_CODEC).xmap(Either::unwrap, api -> { + if ((api.holderClass().isEmpty() || + (api.holderClass().get().name().isEmpty() || api.klass().name().equals(api.holderClass().get().name().get()) && api.holderClass().get().isInterface())) && + !api.klass().legacyEnum() && api.klass().wildcards().isEmpty() && + !api.keyClassNameRelate() && api.registryField().isEmpty()) { + return Either.left(api); + } + return Either.right(api); + }); + + public record Class(ClassNamed name, List wildcards, boolean legacyEnum) { + public Class(ClassNamed name) { + this(name, List.of(), false); + } + + public static final Codec DIRECT_CODEC = RecordCodecBuilder.create(instance -> instance.group( + SourceCodecs.CLASS_NAMED.fieldOf("name").forGetter(Class::name), + ExtraCodecs.compactListCodec(ParameterizedClass.CODEC).optionalFieldOf("wildcards", List.of()).forGetter(Class::wildcards), + Codec.BOOL.optionalFieldOf("legacy_enum", false).deprecated(8).forGetter(Class::legacyEnum) + ).apply(instance, Class::new)); + + public static final Codec CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAMED.xmap(Class::new, Class::name); + + public static final Codec CODEC = Codec.either(CLASS_ONLY_CODEC, DIRECT_CODEC).xmap(Either::unwrap, api -> { + if (!api.legacyEnum() && api.wildcards().isEmpty()) { + return Either.left(api); + } + return Either.right(api); + }); + + public TypeName getType() { + return ParameterizedClass.getAsWildcardType(Types.typed(this.name), this.wildcards); + } + + public void appendType(StringBuilder builder, Function imported) { + ParameterizedClass.appendAsWildcardType(builder, this.name, this.wildcards, imported); + } + } + + public record HolderClass(Optional name, boolean isInterface) { + public HolderClass(ClassNamed name) { + this(Optional.of(name), true); + } + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + SourceCodecs.CLASS_NAMED.optionalFieldOf("name").forGetter(HolderClass::name), + Codec.BOOL.optionalFieldOf("is_interface", true).forGetter(HolderClass::isInterface) + ).apply(instance, HolderClass::new)); + } + } + + public record Impl(ClassNamed klass, String instanceMethod, boolean delayed) { + public Impl(ClassNamed klass) { + this(klass, ConstantDescs.INIT_NAME, false); + } + + public static final Codec DIRECT_CODEC = RecordCodecBuilder.create(instance -> instance.group( + SourceCodecs.CLASS_NAMED.fieldOf("class").forGetter(Impl::klass), + SourceCodecs.IDENTIFIER.optionalFieldOf("instance_method", ConstantDescs.INIT_NAME).forGetter(Impl::instanceMethod), + Codec.BOOL.optionalFieldOf("delayed", false).deprecated(21).forGetter(Impl::delayed) + ).apply(instance, Impl::new)); + + public static final Codec CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAMED.xmap(Impl::new, Impl::klass); + + public static final Codec CODEC = Codec.either(CLASS_ONLY_CODEC, DIRECT_CODEC).xmap(Either::unwrap, impl -> { + if (impl.instanceMethod().equals(ConstantDescs.INIT_NAME) && !impl.delayed()) { + return Either.left(impl); + } + return Either.right(impl); + }); + } + + public record Builder(ClassNamed api, ClassNamed impl, List wildcards, RegisterCapability capability) { + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + SourceCodecs.CLASS_NAMED.fieldOf("api").forGetter(Builder::api), + SourceCodecs.CLASS_NAMED.fieldOf("impl").forGetter(Builder::impl), + ExtraCodecs.compactListCodec(ParameterizedClass.CODEC).optionalFieldOf("wildcards", List.of()).forGetter(Builder::wildcards), + RegisterCapability.CODEC.optionalFieldOf("capability", RegisterCapability.WRITABLE).forGetter(Builder::capability) + ).apply(instance, Builder::new)); + + public TypeName getApiType() { + return ParameterizedClass.getAsWildcardType(Types.typed(this.api), this.wildcards); + } + + public void appendApiType(StringBuilder builder, Function imported) { + ParameterizedClass.appendAsWildcardType(builder, this.api, this.wildcards, imported); + } + + public enum RegisterCapability implements StringRepresentable { + NONE("none"), + ADDABLE("addable"), + MODIFIABLE("modifiable"), + WRITABLE("writable"); + + private final String name; + static final Codec CODEC = StringRepresentable.fromEnum(RegisterCapability::values); + + RegisterCapability(String name) { + this.name = name; + } + + public boolean canAdd() { + return this != MODIFIABLE && this != NONE; + } + + @Override + public String getSerializedName() { + return this.name; + } + } + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/package-info.java b/paper-generator/src/main/java/io/papermc/generator/resources/package-info.java new file mode 100644 index 0000000000..50fa28b468 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package io.papermc.generator.resources; + +import org.jspecify.annotations.NullMarked; diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/predicate/BlockPredicate.java b/paper-generator/src/main/java/io/papermc/generator/resources/predicate/BlockPredicate.java new file mode 100644 index 0000000000..b38427943a --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/predicate/BlockPredicate.java @@ -0,0 +1,146 @@ +package io.papermc.generator.resources.predicate; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import io.papermc.generator.utils.SourceCodecs; +import java.util.List; +import java.util.Set; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.properties.Property; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public sealed interface BlockPredicate permits BlockPredicate.ContainsPropertyPredicate, BlockPredicate.InstanceOfPredicate, BlockPredicate.IsClassPredicate { + + Codec CODEC = Type.CODEC.dispatch("type", BlockPredicate::type, type -> type.codec); + + Type type(); + + enum Type implements StringRepresentable { + INSTANCE_OF("instance_of", InstanceOfPredicate.CODEC), + IS_CLASS("is_class", IsClassPredicate.CODEC), + HAS_PROPERTY("has_property", ContainsPropertyPredicate.SINGLE_CODEC), + CONTAINS_PROPERTY("contains_property", ContainsPropertyPredicate.CODEC); + + public static final Codec CODEC = StringRepresentable.fromValues(Type::values); + private final String name; + final MapCodec codec; + + Type(final String name, final MapCodec codec) { + this.name = name; + this.codec = codec; + } + + @Override + public String getSerializedName() { + return this.name; + } + } + + boolean matches(Class block, Set> properties); + + record IsClassPredicate(Class value) implements BlockPredicate { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + SourceCodecs.classCodec(Block.class).fieldOf("value").forGetter(IsClassPredicate::value) + ).apply(instance, IsClassPredicate::new)); + + @Override + public Type type() { + return Type.IS_CLASS; + } + + @Override + public boolean matches(Class block, Set> properties) { + return this.value.equals(block); + } + } + + record InstanceOfPredicate(Class value, List propertyPredicates) implements BlockPredicate { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + SourceCodecs.classCodec(Block.class).fieldOf("value").forGetter(InstanceOfPredicate::value), + ExtraCodecs.compactListCodec(BlockPropertyPredicate.CODEC).optionalFieldOf("has_property", List.of()).forGetter(InstanceOfPredicate::propertyPredicates) + ).apply(instance, InstanceOfPredicate::new)); + + @Override + public Type type() { + return Type.INSTANCE_OF; + } + + @Override + public boolean matches(Class block, Set> properties) { + if (!this.value.isAssignableFrom(block)) { + return false; + } + + if (this.propertyPredicates.isEmpty()) { + return true; + } + + for (BlockPropertyPredicate predicate : this.propertyPredicates) { + for (Property property : properties) { + if (predicate.matches(property)) { + return true; + } + } + } + return false; + } + } + + record ContainsPropertyPredicate(List value, int count, Strategy strategy) implements BlockPredicate { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ExtraCodecs.nonEmptyList(BlockPropertyPredicate.CODEC.listOf()).fieldOf("value").forGetter(ContainsPropertyPredicate::value), + ExtraCodecs.POSITIVE_INT.fieldOf("count").forGetter(ContainsPropertyPredicate::count), + Strategy.CODEC.fieldOf("strategy").forGetter(ContainsPropertyPredicate::strategy) + ).apply(instance, ContainsPropertyPredicate::new)); + + public static final MapCodec SINGLE_CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ExtraCodecs.compactListCodec(BlockPropertyPredicate.CODEC, ExtraCodecs.nonEmptyList(BlockPropertyPredicate.CODEC.listOf())).fieldOf("value").forGetter(ContainsPropertyPredicate::value) + ).apply(instance, value -> new ContainsPropertyPredicate(value, 1, Strategy.AT_LEAST))); + + @Override + public Type type() { + return Type.CONTAINS_PROPERTY; + } + + @Override + public boolean matches(Class block, Set> properties) { + int found = 0; + for (BlockPropertyPredicate predicate : this.value) { + for (Property property : properties) { + if (predicate.matches(property)) { + found++; + if (this.strategy == Strategy.AT_LEAST && found == this.count) { + return true; + } + } + } + } + + return this.strategy == Strategy.EXACT && found == this.count; + } + + public enum Strategy implements StringRepresentable { + EXACT("exact"), + AT_LEAST("at_least"); + + private final String name; + static final Codec CODEC = StringRepresentable.fromEnum(Strategy::values); + + Strategy(String name) { + this.name = name; + } + + @Override + public String getSerializedName() { + return this.name; + } + } + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/predicate/BlockPropertyPredicate.java b/paper-generator/src/main/java/io/papermc/generator/resources/predicate/BlockPropertyPredicate.java new file mode 100644 index 0000000000..1af634fbf0 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/predicate/BlockPropertyPredicate.java @@ -0,0 +1,112 @@ +package io.papermc.generator.resources.predicate; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import io.papermc.generator.utils.BlockStateMapping; +import io.papermc.generator.utils.SourceCodecs; +import java.util.function.Predicate; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.Property; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public sealed interface BlockPropertyPredicate permits BlockPropertyPredicate.IsFieldPredicate, BlockPropertyPredicate.IsNamePredicate { + + Codec DIRECT_CODEC = Type.CODEC.dispatch("type", BlockPropertyPredicate::type, type -> type.codec); + Codec COMPACT_CODEC = Codec.withAlternative(IsFieldPredicate.COMPACT_CODEC, IsNamePredicate.COMPACT_CODEC); + Codec CODEC = Codec.withAlternative(DIRECT_CODEC, COMPACT_CODEC); + + String value(); + + Type type(); + + enum Type implements StringRepresentable { + IS_FIELD("is_field", IsFieldPredicate.CODEC), + IS_NAME("is_name", IsNamePredicate.CODEC); + + public static final Codec CODEC = StringRepresentable.fromValues(Type::values); + private final String name; + final MapCodec codec; + + Type(final String name, final MapCodec codec) { + this.name = name; + this.codec = codec; + } + + @Override + public String getSerializedName() { + return this.name; + } + } + + boolean matches(Property property); + + static boolean testProperty(Predicate predicate, String id, boolean supportInversion) { + // expand if needed with proper support + AND/OR-ed + if (supportInversion && id.charAt(0) == '!') { + return !predicate.test(id.substring(1)); + } + + return predicate.test(id); + } + + record IsNamePredicate(String value) implements BlockPropertyPredicate { + + private static final Codec PROPERTY_NAME = ExtraCodecs.RESOURCE_PATH_CODEC + .comapFlatMap(name -> { + if (!BlockStateMapping.PROPERTY_NAMES.contains(name)) { + return DataResult.error(() -> "Invalid property name: '%s'".formatted(name)); + } + return DataResult.success(name); + }, name -> name); + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + PROPERTY_NAME.fieldOf("value").forGetter(IsNamePredicate::value) + ).apply(instance, IsNamePredicate::new)); + + public static final Codec COMPACT_CODEC = PROPERTY_NAME.xmap(IsNamePredicate::new, BlockPropertyPredicate::value); + + @Override + public Type type() { + return Type.IS_NAME; + } + + @Override + public boolean matches(Property property) { + return BlockPropertyPredicate.testProperty( + name -> name.equals(property.getName()), + this.value, + false + ); + } + } + + record IsFieldPredicate(String value) implements BlockPropertyPredicate { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + SourceCodecs.fieldNameCodec(BlockStateProperties.class, BlockStateMapping.GENERIC_FIELD_NAMES::containsValue).fieldOf("value").forGetter(IsFieldPredicate::value) + ).apply(instance, IsFieldPredicate::new)); + + public static final Codec COMPACT_CODEC = SourceCodecs.fieldCodec( + BlockStateProperties.class, BlockStateMapping.GENERIC_FIELD_NAMES::containsValue + ).xmap(IsFieldPredicate::new, BlockPropertyPredicate::value); + + @Override + public Type type() { + return Type.IS_FIELD; + } + + @Override + public boolean matches(Property property) { + return BlockPropertyPredicate.testProperty( + field -> field.equals(BlockStateMapping.GENERIC_FIELD_NAMES.get(property)), + this.value, + false + ); + } + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/resources/predicate/ItemPredicate.java b/paper-generator/src/main/java/io/papermc/generator/resources/predicate/ItemPredicate.java new file mode 100644 index 0000000000..2f971f5f6b --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/resources/predicate/ItemPredicate.java @@ -0,0 +1,112 @@ +package io.papermc.generator.resources.predicate; + +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import io.papermc.generator.utils.SourceCodecs; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.Registries; +import net.minecraft.tags.TagKey; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public sealed interface ItemPredicate permits ItemPredicate.IsClassPredicate, ItemPredicate.InstanceOfPredicate, ItemPredicate.IsElementPredicate { + + Codec DIRECT_CODEC = Type.CODEC.dispatch("type", ItemPredicate::type, type -> type.codec); + Codec CODEC = Codec.either(IsElementPredicate.COMPACT_CODEC, DIRECT_CODEC).xmap(Either::unwrap, Either::right); + + Type type(); + + enum Type implements StringRepresentable { + INSTANCE_OF("instance_of", InstanceOfPredicate.CODEC), + IS_CLASS("is_class", IsClassPredicate.CODEC), + IS_ELEMENT("is_element", IsElementPredicate.CODEC); + + public static final Codec CODEC = StringRepresentable.fromValues(Type::values); + private final String name; + final MapCodec codec; + + Type(final String name, final MapCodec codec) { + this.name = name; + this.codec = codec; + } + + @Override + public String getSerializedName() { + return this.name; + } + } + + boolean matches(Holder.Reference item); + + record IsClassPredicate(Class value, boolean againstBlock) implements ItemPredicate { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + SourceCodecs.CLASS.fieldOf("value").forGetter(IsClassPredicate::value), + Codec.BOOL.optionalFieldOf("against_block", false).forGetter(IsClassPredicate::againstBlock) + ).apply(instance, IsClassPredicate::new)); + + @Override + public Type type() { + return Type.IS_CLASS; + } + + @Override + public boolean matches(Holder.Reference item) { + if (!this.againstBlock) { + return this.value.equals(item.value().getClass()); + } else if (item.value() instanceof BlockItem blockItem) { + return this.value.equals(blockItem.getBlock().getClass()); + } + + return false; + } + } + + record InstanceOfPredicate(Class value, boolean againstBlock) implements ItemPredicate { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + SourceCodecs.CLASS.fieldOf("value").forGetter(InstanceOfPredicate::value), + Codec.BOOL.optionalFieldOf("against_block", false).forGetter(InstanceOfPredicate::againstBlock) + ).apply(instance, InstanceOfPredicate::new)); + + @Override + public Type type() { + return Type.INSTANCE_OF; + } + + @Override + public boolean matches(Holder.Reference item) { + if (!this.againstBlock) { + return this.value.isAssignableFrom(item.value().getClass()); + } else if (item.value() instanceof BlockItem blockItem) { + return this.value.isAssignableFrom(blockItem.getBlock().getClass()); + } + + return false; + } + } + + record IsElementPredicate(Either, Holder> value) implements ItemPredicate { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + SourceCodecs.elementOrTagCodec(Registries.ITEM).fieldOf("value").forGetter(IsElementPredicate::value) + ).apply(instance, IsElementPredicate::new)); + + public static final Codec COMPACT_CODEC = SourceCodecs.elementOrTagCodec(Registries.ITEM).xmap(IsElementPredicate::new, IsElementPredicate::value); + + @Override + public Type type() { + return Type.IS_ELEMENT; + } + + @Override + public boolean matches(Holder.Reference item) { + return this.value.map(item::is, item::is); + } + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/registration/PaperPatternSourceSetRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/registration/PaperPatternSourceSetRewriter.java index 566dec1905..e8defb18b6 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/registration/PaperPatternSourceSetRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/registration/PaperPatternSourceSetRewriter.java @@ -1,8 +1,8 @@ package io.papermc.generator.rewriter.registration; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.rewriter.utils.Annotations; import io.papermc.generator.types.SimpleGenerator; -import io.papermc.paper.generated.GeneratedFrom; import io.papermc.typewriter.ClassNamed; import io.papermc.typewriter.SourceFile; import io.papermc.typewriter.context.IndentUnit; @@ -46,7 +46,7 @@ public class PaperPatternSourceSetRewriter extends SourceSetRewriterImpl { - default PatternSourceSetRewriter register(String pattern, Class targetClass, SearchReplaceRewriter rewriter) { - return register(pattern, new ClassNamed(targetClass), rewriter); + default > PatternSourceSetRewriter register(String pattern, T rewriter) { + return this.register(pattern, RegistryEntries.byRegistryKey(rewriter.getRegistryKey()).data().api().klass().name(), rewriter); } PatternSourceSetRewriter register(String pattern, ClassNamed targetClass, SearchReplaceRewriter rewriter); - default PatternSourceSetRewriter register(Class mainClass, CompositeRewriter rewriter) { - return this.register(new ClassNamed(mainClass), rewriter); - } - PatternSourceSetRewriter register(ClassNamed mainClass, CompositeRewriter rewriter); } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/registration/RewriterHolder.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/registration/RewriterHolder.java index 0d4809a214..1945fde4fd 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/registration/RewriterHolder.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/registration/RewriterHolder.java @@ -1,5 +1,7 @@ package io.papermc.generator.rewriter.registration; +import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.registry.RegistryIdentifiable; import io.papermc.typewriter.ClassNamed; import io.papermc.typewriter.replace.ReplaceOptionsLike; import io.papermc.typewriter.replace.SearchReplaceRewriter; @@ -17,7 +19,12 @@ public record RewriterHolder(String pattern, @Nullable ClassNamed targetClass, S } @Contract(value = "_, _ -> new", pure = true) - public static RewriterHolder holder(String pattern, SearchReplaceRewriter rewriter) { + public static > RewriterHolder holder(String pattern, T rewriter) { + return new RewriterHolder(pattern, RegistryEntries.byRegistryKey(rewriter.getRegistryKey()).data().api().klass().name(), rewriter); + } + + @Contract(value = "_, _ -> new", pure = true) + public static RewriterHolder sameHolder(String pattern, SearchReplaceRewriter rewriter) { return holder(pattern, null, rewriter); } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/Types.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/Types.java index c84868cee1..d13815195e 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/Types.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/Types.java @@ -1,30 +1,149 @@ package io.papermc.generator.rewriter.types; +import com.squareup.javapoet.ClassName; import io.papermc.typewriter.ClassNamed; +import java.util.ArrayList; +import java.util.List; import org.jspecify.annotations.NullMarked; +import static io.papermc.generator.utils.BasePackage.BUKKIT; +import static io.papermc.generator.utils.BasePackage.CRAFT_BUKKIT; +import static io.papermc.generator.utils.BasePackage.PAPER; +import static io.papermc.generator.utils.BasePackage.PAPER_LEGACY; + @NullMarked public final class Types { - public static final String BASE_PACKAGE = "org.bukkit.craftbukkit"; + public static final ClassNamed BUKKIT_CLASS = BUKKIT.rootClassNamed("Bukkit"); - public static final ClassNamed CRAFT_BLOCK_DATA = ClassNamed.of(BASE_PACKAGE + ".block.data", "CraftBlockData"); + public static final ClassNamed FEATURE_FLAG = BUKKIT.rootClassNamed("FeatureFlag"); - public static final ClassNamed CRAFT_BLOCK_STATES = ClassNamed.of(BASE_PACKAGE + ".block", "CraftBlockStates"); + public static final ClassNamed REGISTRY = BUKKIT.rootClassNamed("Registry"); - public static final ClassNamed CRAFT_STATISTIC = ClassNamed.of(BASE_PACKAGE, "CraftStatistic"); + public static final ClassNamed TAG = BUKKIT.rootClassNamed("Tag"); - public static final ClassNamed CRAFT_POTION_UTIL = ClassNamed.of(BASE_PACKAGE + ".potion", "CraftPotionUtil"); + public static final ClassNamed NAMESPACED_KEY = typed(io.papermc.generator.types.Types.NAMESPACED_KEY); - public static final ClassNamed FIELD_RENAME = ClassNamed.of(BASE_PACKAGE + ".legacy", "FieldRename"); + public static final ClassNamed MINECRAFT_EXPERIMENTAL = typed(io.papermc.generator.types.Types.MINECRAFT_EXPERIMENTAL); + public static final ClassNamed MINECRAFT_EXPERIMENTAL_REQUIRES = typed(io.papermc.generator.types.Types.MINECRAFT_EXPERIMENTAL_REQUIRES); - public static final ClassNamed PAPER_REGISTRIES = ClassNamed.of("io.papermc.paper.registry", "PaperRegistries"); + @Deprecated + public static final ClassNamed STATISTIC = BUKKIT.rootClassNamed("Statistic"); - public static final ClassNamed REGISTRY_MODIFICATION_API_SUPPORT = ClassNamed.of("io.papermc.paper.registry.entry", "RegistryEntryMeta", "RegistryModificationApiSupport"); + public static final ClassNamed STATISTIC_TYPE = BUKKIT.rootClassNamed("Statistic", "Type"); - public static final ClassNamed PAPER_FEATURE_FLAG_PROVIDER_IMPL = ClassNamed.of("io.papermc.paper.world.flag", "PaperFeatureFlagProviderImpl"); + public static final ClassNamed BLOCK_TYPE_TYPED = BUKKIT.relativeClassNamed("block", "BlockType", "Typed"); - public static final ClassNamed PAPER_SIMPLE_REGISTRY = ClassNamed.of("io.papermc.paper.registry", "PaperSimpleRegistry"); + public static final ClassNamed ITEM_TYPE_TYPED = BUKKIT.relativeClassNamed("inventory", "ItemType", "Typed"); - public static final ClassNamed MOB_GOAL_HELPER = ClassNamed.of("com.destroystokyo.paper.entity.ai", "MobGoalHelper"); + public static final ClassNamed ITEM_META = BUKKIT.relativeClassNamed("inventory.meta", "ItemMeta"); + + public static final ClassNamed LOCATION = BUKKIT.rootClassNamed("Location"); + + public static final ClassNamed MATERIAL = BUKKIT.rootClassNamed("Material"); + + public static final ClassNamed POSE = BUKKIT.relativeClassNamed("entity", "Pose"); + + @Deprecated + public static final ClassNamed VILLAGER = BUKKIT.relativeClassNamed("entity", "Villager"); + + public static final ClassNamed SNIFFER_STATE = BUKKIT.relativeClassNamed("entity", "Sniffer", "State"); + + public static final ClassNamed TROPICAL_FISH_PATTERN = BUKKIT.relativeClassNamed("entity", "TropicalFish", "Pattern"); + + public static final ClassNamed FOX_TYPE = BUKKIT.relativeClassNamed("entity", "Fox", "Type"); + + public static final ClassNamed SALMON_VARIANT = BUKKIT.relativeClassNamed("entity", "Salmon", "Variant"); + + public static final ClassNamed ARMADILLO_STATE = BUKKIT.relativeClassNamed("entity", "Armadillo", "State"); + + public static final ClassNamed PANDA_GENE = BUKKIT.relativeClassNamed("entity", "Panda", "Gene"); + + public static final ClassNamed BOAT_STATUS = BUKKIT.relativeClassNamed("entity", "Boat", "Status"); + + public static final ClassNamed ITEM_RARITY = BUKKIT.relativeClassNamed("inventory", "ItemRarity"); + + public static final ClassNamed COOKING_BOOK_CATEGORY = BUKKIT.relativeClassNamed("inventory.recipe", "CookingBookCategory"); + + public static final ClassNamed CRAFTING_BOOK_CATEGORY = BUKKIT.relativeClassNamed("inventory.recipe", "CraftingBookCategory"); + + public static final ClassNamed MAP_PALETTE = BUKKIT.relativeClassNamed("map", "MapPalette"); + + public static final ClassNamed DISPLAY_SLOT = BUKKIT.relativeClassNamed("scoreboard", "DisplaySlot"); + + public static final ClassNamed SOUND_CATEGORY = BUKKIT.rootClassNamed("SoundCategory"); + + public static final ClassNamed DAMAGE_TYPE_TAGS = BUKKIT.relativeClassNamed("tag", "DamageTypeTags"); + + public static final ClassNamed BLOCK_DATA = BUKKIT.relativeClassNamed("block.data", "BlockData"); + + public static final ClassNamed BLOCK_DATA_REDSTONE_WIRE = BUKKIT.relativeClassNamed("block.data.type", "RedstoneWire"); + + public static final ClassNamed BLOCK_DATA_MULTIPLE_FACING = BUKKIT.relativeClassNamed("block.data", "MultipleFacing"); + + public static final ClassNamed BLOCK_DATA_RAIL_SHAPE = typed(io.papermc.generator.types.Types.BLOCK_DATA_RAIL_SHAPE); + + public static final ClassNamed AXIS = typed(io.papermc.generator.types.Types.AXIS); + + public static final ClassNamed BLOCK_FACE = typed(io.papermc.generator.types.Types.BLOCK_FACE); + + public static final ClassNamed NOTE = typed(io.papermc.generator.types.Types.NOTE); + + public static final ClassNamed NAMED_TEXT_COLOR = ClassNamed.of("net.kyori.adventure.text.format", "NamedTextColor"); + + public static final ClassNamed REGISTRY_KEY = typed(io.papermc.generator.types.Types.REGISTRY_KEY); + + public static final ClassNamed REGISTRY_EVENTS = PAPER.relativeClassNamed("registry.event", "RegistryEvents"); + + public static final ClassNamed REGISTRY_EVENT_PROVIDER = PAPER.relativeClassNamed("registry.event", "RegistryEventProvider"); + + public static final ClassNamed ITEM_USE_ANIMATION = PAPER.relativeClassNamed("datacomponent.item.consumable", "ItemUseAnimation"); + + public static final ClassNamed GENERATED_FROM = typed(io.papermc.generator.types.Types.GENERATED_FROM); + + public static final ClassNamed BLOCK_PROPERTIES = PAPER.relativeClassNamed("block.property", "BlockProperties"); + + public static final ClassNamed BLOCK_PROPERTY = PAPER.relativeClassNamed("block.property", "BlockProperty"); + + public static final ClassNamed BOOLEAN_BLOCK_PROPERTY = PAPER.relativeClassNamed("block.property", "BooleanBlockProperty"); + + public static final ClassNamed ENUM_BLOCK_PROPERTY = PAPER.relativeClassNamed("block.property", "EnumBlockProperty"); + + public static final ClassNamed INTEGER_BLOCK_PROPERTY = PAPER.relativeClassNamed("block.property", "IntegerBlockProperty"); + + public static final ClassNamed ROTATION_BLOCK_PROPERTY = PAPER.relativeClassNamed("block.property", "RotationBlockProperty"); + + public static final ClassNamed NOTE_BLOCK_PROPERTY = PAPER.relativeClassNamed("block.property", "NoteBlockProperty"); + + public static final ClassNamed CRAFT_BLOCK_DATA = typed(io.papermc.generator.types.Types.CRAFT_BLOCK_DATA); + + public static final ClassNamed CRAFT_BLOCK_STATES = CRAFT_BUKKIT.relativeClassNamed("block", "CraftBlockStates"); + + public static final ClassNamed CRAFT_ITEM_METAS = CRAFT_BUKKIT.relativeClassNamed("inventory", "CraftItemMetas"); + + public static final ClassNamed CRAFT_STATISTIC = CRAFT_BUKKIT.relativeClassNamed(null, "CraftStatistic"); + + public static final ClassNamed CRAFT_POTION_UTIL = CRAFT_BUKKIT.relativeClassNamed("potion", "CraftPotionUtil"); + + public static final ClassNamed FIELD_RENAME = CRAFT_BUKKIT.relativeClassNamed("legacy", "FieldRename"); + + public static final ClassNamed REGISTRIES_ARGUMENT_PROVIDER = BUKKIT.relativeClassNamed("support.provider" , "RegistriesArgumentProvider"); + + public static final ClassNamed REGISTRY_CONVERSION_TEST = BUKKIT.relativeClassNamed("registry", "RegistryConversionTest"); + + public static final ClassNamed PAPER_REGISTRIES = PAPER.relativeClassNamed("registry", "PaperRegistries"); + + public static final ClassNamed PAPER_FEATURE_FLAG_PROVIDER_IMPL = PAPER.relativeClassNamed("world.flag", "PaperFeatureFlagProviderImpl"); + + public static final ClassNamed PAPER_SIMPLE_REGISTRY = PAPER.relativeClassNamed("registry", "PaperSimpleRegistry"); + + public static final ClassNamed REGISTRY_MODIFICATION_API_SUPPORT = PAPER.relativeClassNamed("registry.entry", "RegistryEntryMeta", "RegistryModificationApiSupport"); + + public static final ClassNamed MOB_GOAL_HELPER = PAPER_LEGACY.relativeClassNamed("entity.ai", "MobGoalHelper"); + + public static ClassNamed typed(ClassName name) { + List names = new ArrayList<>(name.simpleNames()); + String topName = names.removeFirst(); + return ClassNamed.of(name.packageName(), topName, names.toArray(new String[0])); + } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/EnumRegistryRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/EnumRegistryRewriter.java index b2ab2aac1d..d71e0e81d1 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/EnumRegistryRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/EnumRegistryRewriter.java @@ -2,12 +2,13 @@ package io.papermc.generator.rewriter.types.registry; import com.google.common.base.Suppliers; import io.papermc.generator.Main; +import io.papermc.generator.registry.RegistryIdentifiable; import io.papermc.generator.rewriter.utils.Annotations; import io.papermc.generator.utils.Formatting; import io.papermc.generator.utils.experimental.ExperimentalCollector; import io.papermc.generator.utils.experimental.SingleFlagHolder; import io.papermc.typewriter.preset.EnumRewriter; -import io.papermc.typewriter.preset.model.EnumValue; +import io.papermc.typewriter.preset.model.EnumConstant; import java.util.Map; import java.util.function.Supplier; import net.minecraft.core.Holder; @@ -16,29 +17,28 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.world.flag.FeatureElement; import net.minecraft.world.flag.FeatureFlags; import org.jetbrains.annotations.ApiStatus; -import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; import static io.papermc.generator.utils.Formatting.quoted; -@NullMarked @ApiStatus.Obsolete -public class EnumRegistryRewriter extends EnumRewriter> { +public class EnumRegistryRewriter extends EnumRewriter> implements RegistryIdentifiable { + private final ResourceKey> registryKey; private final Supplier> registry; private final Supplier, SingleFlagHolder>> experimentalKeys; private final boolean isFilteredRegistry; - private final boolean hasKeyArgument; public EnumRegistryRewriter(ResourceKey> registryKey) { - this(registryKey, true); - } - - protected EnumRegistryRewriter(ResourceKey> registryKey, boolean hasKeyArgument) { + this.registryKey = registryKey; this.registry = Suppliers.memoize(() -> Main.REGISTRY_ACCESS.lookupOrThrow(registryKey)); this.experimentalKeys = Suppliers.memoize(() -> ExperimentalCollector.collectDataDrivenElementIds(this.registry.get())); this.isFilteredRegistry = FeatureElement.FILTERED_REGISTRIES.contains(registryKey); - this.hasKeyArgument = hasKeyArgument; + } + + @Override + public ResourceKey> getRegistryKey() { + return this.registryKey; } @Override @@ -47,23 +47,24 @@ public class EnumRegistryRewriter extends EnumRewriter> { } @Override - protected EnumValue.Builder rewriteEnumValue(Holder.Reference reference) { - EnumValue.Builder value = EnumValue.builder(Formatting.formatKeyAsField(reference.key().location().getPath())); - if (this.hasKeyArgument) { - value.argument(quoted(reference.key().location().getPath())); - } - return value; + protected EnumConstant.Builder constantPrototype(Holder.Reference reference) { + return EnumConstant.builder(Formatting.formatKeyAsField(reference.key().location().getPath())); } @Override - protected void appendEnumValue(Holder.Reference reference, StringBuilder builder, String indent, boolean reachEnd) { + protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference reference) { + builder.argument(quoted(reference.key().location().getPath())); + } + + @Override + protected void appendConstant(Holder.Reference reference, StringBuilder builder, String indent, boolean reachEnd) { // experimental annotation SingleFlagHolder requiredFeature = this.getRequiredFeature(reference); if (requiredFeature != null) { Annotations.experimentalAnnotations(builder, indent, this.importCollector, requiredFeature); } - super.appendEnumValue(reference, builder, indent, reachEnd); + super.appendConstant(reference, builder, indent, reachEnd); } protected @Nullable SingleFlagHolder getRequiredFeature(Holder.Reference reference) { diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/FeatureFlagRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/FeatureFlagRewriter.java index ede08c4a00..73e02d83f2 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/FeatureFlagRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/FeatureFlagRewriter.java @@ -1,8 +1,7 @@ package io.papermc.generator.rewriter.types.registry; -import com.mojang.logging.LogUtils; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.utils.Formatting; -import io.papermc.typewriter.SourceFile; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; import java.util.Iterator; @@ -12,29 +11,12 @@ import net.minecraft.world.flag.FeatureFlag; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.flag.FeatureFlags; import org.jetbrains.annotations.ApiStatus; -import org.jspecify.annotations.NullMarked; -import org.slf4j.Logger; import static io.papermc.generator.rewriter.utils.Annotations.annotation; import static io.papermc.generator.utils.Formatting.quoted; -@NullMarked public class FeatureFlagRewriter extends SearchReplaceRewriter { - private static final Logger LOGGER = LogUtils.getLogger(); - - @Override - public boolean registerFor(SourceFile file) { - try { - org.bukkit.FeatureFlag.class.getDeclaredMethod("create", String.class); - } catch (NoSuchMethodException e) { - LOGGER.error("Fetch method not found, skipping the rewriter for feature flag", e); - return false; - } - - return super.registerFor(file); - } - @Override protected void insert(SearchMetadata metadata, StringBuilder builder) { Iterator> flagIterator = FeatureFlags.REGISTRY.names.entrySet().stream().sorted(Formatting.alphabeticKeyOrder(entry -> entry.getKey().getPath())).iterator(); @@ -47,7 +29,7 @@ public class FeatureFlagRewriter extends SearchReplaceRewriter { builder.append(metadata.indent()); - builder.append(org.bukkit.FeatureFlag.class.getSimpleName()).append(' ').append(Formatting.formatKeyAsField(name.getPath())); + builder.append(Types.FEATURE_FLAG.simpleName()).append(' ').append(Formatting.formatKeyAsField(name.getPath())); builder.append(" = "); builder.append("create(%s)".formatted(quoted(name.getPath()))); builder.append(';'); diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/PaperFeatureFlagMapping.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/PaperFeatureFlagMapping.java index 06287f65a0..be07db0c00 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/PaperFeatureFlagMapping.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/PaperFeatureFlagMapping.java @@ -1,15 +1,13 @@ package io.papermc.generator.rewriter.types.registry; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.utils.Formatting; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; import java.util.Iterator; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.flag.FeatureFlags; -import org.bukkit.FeatureFlag; -import org.jspecify.annotations.NullMarked; -@NullMarked public class PaperFeatureFlagMapping extends SearchReplaceRewriter { @Override @@ -20,7 +18,7 @@ public class PaperFeatureFlagMapping extends SearchReplaceRewriter { ResourceLocation name = flagIterator.next(); String keyedName = Formatting.formatKeyAsField(name.getPath()); builder.append(metadata.indent()); - builder.append("%s.%s, %s.%s".formatted(FeatureFlag.class.getSimpleName(), keyedName, FeatureFlags.class.getSimpleName(), keyedName)); + builder.append("%s.%s, %s.%s".formatted(Types.FEATURE_FLAG.simpleName(), keyedName, FeatureFlags.class.getSimpleName(), keyedName)); if (flagIterator.hasNext()) { builder.append(','); } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/PaperRegistriesRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/PaperRegistriesRewriter.java index 599356eba7..4bd3793261 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/PaperRegistriesRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/PaperRegistriesRewriter.java @@ -3,74 +3,66 @@ package io.papermc.generator.rewriter.types.registry; import com.google.common.base.CaseFormat; import io.papermc.generator.registry.RegistryEntries; import io.papermc.generator.registry.RegistryEntry; +import io.papermc.generator.resources.data.RegistryData; import io.papermc.generator.rewriter.types.Types; -import io.papermc.paper.registry.RegistryKey; -import io.papermc.typewriter.ClassNamed; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; import java.lang.constant.ConstantDescs; -import java.util.stream.Stream; import net.minecraft.core.registries.Registries; -import org.bukkit.Keyed; -import org.bukkit.Registry; -import org.jspecify.annotations.NullMarked; -@NullMarked public class PaperRegistriesRewriter extends SearchReplaceRewriter { - - private void appendEntry(String indent, StringBuilder builder, RegistryEntry entry, boolean canBeDelayed, boolean apiOnly) { + private void appendEntry(String indent, StringBuilder builder, RegistryEntry entry, boolean apiOnly) { builder.append(indent); builder.append("start"); builder.append('('); builder.append(Registries.class.getSimpleName()).append('.').append(entry.registryKeyField()); builder.append(", "); - builder.append(RegistryKey.class.getSimpleName()).append('.').append(entry.registryKeyField()); + builder.append(Types.REGISTRY_KEY.simpleName()).append('.').append(entry.registryKeyField()); builder.append(")."); + + RegistryData data = entry.data(); if (apiOnly) { builder.append("apiOnly("); - if (entry.apiClass().isEnum()) { - builder.append(this.importCollector.getShortName(Types.PAPER_SIMPLE_REGISTRY)).append("::").append(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, entry.registryKey().location().getPath())); + if (data.api().klass().legacyEnum()) { + builder.append(this.importCollector.getShortName(Types.PAPER_SIMPLE_REGISTRY)).append("::").append(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, entry.getRegistryKey().location().getPath())); } else { builder.append("() -> "); - builder.append(Registry.class.getCanonicalName()).append('.').append(entry.apiRegistryField().orElse(entry.registryKeyField())); + builder.append(Types.REGISTRY.canonicalName()).append('.').append(data.api().registryField().orElse(entry.registryKeyField())); } builder.append(')'); } else { builder.append("craft("); - builder.append(this.importCollector.getShortName(entry.preloadClass())).append(".class"); + builder.append(this.importCollector.getShortName(data.api().holderClass().flatMap(RegistryData.Api.HolderClass::name).orElse(data.api().klass().name()))).append(".class"); builder.append(", "); - builder.append(this.importCollector.getShortName(this.getImplClassName(entry))).append("::").append(entry.apiAccessName().equals(ConstantDescs.INIT_NAME) ? "new" : entry.apiAccessName()); + builder.append(this.importCollector.getShortName(data.impl().klass())).append("::").append(data.impl().instanceMethod().equals(ConstantDescs.INIT_NAME) ? "new" : data.impl().instanceMethod()); - if (entry.canAllowDirect()) { + if (data.allowInline()) { builder.append(", "); builder.append(Boolean.TRUE.toString()); } builder.append(')'); - if (entry.fieldRename() != null) { - builder.append(".serializationUpdater(").append(Types.FIELD_RENAME.simpleName()).append('.').append(entry.fieldRename()).append(")"); - } + data.serializationUpdaterField().ifPresent(field -> { + builder.append(".serializationUpdater(").append(Types.FIELD_RENAME.simpleName()).append('.').append(field).append(")"); + }); - if (entry.apiRegistryBuilderImpl() != null && entry.modificationApiSupport() != null) { - switch (entry.modificationApiSupport()) { - case WRITABLE -> builder.append(".writable("); - case ADDABLE -> builder.append(".addable("); - case MODIFIABLE -> builder.append(".modifiable("); - case NONE -> builder.append(".create("); + data.builder().ifPresentOrElse(b -> { + if (b.capability() != RegistryData.Builder.RegisterCapability.NONE) { + builder.append(".%s(".formatted(b.capability().getSerializedName())); + builder.append(this.importCollector.getShortName(b.impl())).append("::new"); + builder.append(')'); + } else { + builder.append(".create(%s::new, %s.%s)".formatted( + this.importCollector.getShortName(b.impl()), + Types.REGISTRY_MODIFICATION_API_SUPPORT.dottedNestedName(), + b.capability().name() + )); } - builder.append(this.importCollector.getShortName(this.classNamedView.findFirst(entry.apiRegistryBuilderImpl()).resolve(this.classResolver))).append("::new"); - if (entry.modificationApiSupport() == RegistryEntry.RegistryModificationApiSupport.NONE) { - builder.append(", "); - builder.append(Types.REGISTRY_MODIFICATION_API_SUPPORT.dottedNestedName()).append(".NONE"); - } - builder.append(')'); - } else { - builder.append(".build()"); - } + }, () -> builder.append(".build()")); } - if (canBeDelayed && entry.isDelayed()) { + if (data.impl().delayed()) { builder.append(".delayed()"); } builder.append(','); @@ -79,37 +71,24 @@ public class PaperRegistriesRewriter extends SearchReplaceRewriter { @Override public void insert(SearchMetadata metadata, StringBuilder builder) { - builder.append(metadata.indent()).append("// built-in"); - builder.append('\n'); + for (RegistryEntry.Type type : RegistryEntry.Type.values()) { + builder.append(metadata.indent()).append("// ").append(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, type.getSerializedName())); + builder.append('\n'); - for (RegistryEntry entry : RegistryEntries.BUILT_IN) { - appendEntry(metadata.indent(), builder, entry, false, false); + for (RegistryEntry entry : RegistryEntries.byType(type)) { + appendEntry(metadata.indent(), builder, entry, false); + } + + builder.append('\n'); } - builder.append('\n'); - builder.append(metadata.indent()).append("// data-driven"); - builder.append('\n'); - - for (RegistryEntry entry : RegistryEntries.DATA_DRIVEN) { - appendEntry(metadata.indent(), builder, entry, true, false); - } - - builder.append('\n'); builder.append(metadata.indent()).append("// api-only"); builder.append('\n'); for (RegistryEntry entry : RegistryEntries.API_ONLY) { - appendEntry(metadata.indent(), builder, entry, false, true); + appendEntry(metadata.indent(), builder, entry, true); } builder.deleteCharAt(builder.length() - 2); // delete extra comma... } - - private ClassNamed getImplClassName(RegistryEntry entry) { - try (Stream stream = this.classNamedView.find(entry.implClass())) { - return stream.map(klass -> klass.resolve(this.classResolver)) - .filter(klass -> Keyed.class.isAssignableFrom(klass.knownClass())) // todo check handleable/holderable once keyed is gone - .findFirst().orElseThrow(); - } - } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistriesArgumentProviderRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistriesArgumentProviderRewriter.java new file mode 100644 index 0000000000..bd2b6ce798 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistriesArgumentProviderRewriter.java @@ -0,0 +1,37 @@ +package io.papermc.generator.rewriter.types.registry; + +import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.rewriter.types.Types; +import io.papermc.typewriter.replace.SearchMetadata; +import io.papermc.typewriter.replace.SearchReplaceRewriter; +import java.util.Set; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; + +public class RegistriesArgumentProviderRewriter extends SearchReplaceRewriter { + + private static final Set>> NEW_BRIDGE_METHODS = Set.of( + Registries.ITEM, + Registries.BLOCK + ); + + @Override + public void insert(SearchMetadata metadata, StringBuilder builder) { + RegistryEntries.forEach(entry -> { + builder.append(metadata.indent()); + builder.append("register(").append( + "%s.%s, %s.class, %s.%s, %s.class, %s.class, %s".formatted( + Types.REGISTRY_KEY.simpleName(), + entry.registryKeyField(), + this.importCollector.getShortName(entry.data().api().klass().name()), + Registries.class.getSimpleName(), + entry.registryKeyField(), + this.importCollector.getShortName(entry.data().impl().klass()), + this.importCollector.getShortName(entry.elementClass()), + Boolean.toString(NEW_BRIDGE_METHODS.contains(entry.getRegistryKey())) + )).append(");"); + builder.append("\n"); + }); + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryConversionTestRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryConversionTestRewriter.java new file mode 100644 index 0000000000..ef624ca922 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryConversionTestRewriter.java @@ -0,0 +1,22 @@ +package io.papermc.generator.rewriter.types.registry; + +import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.rewriter.types.Types; +import io.papermc.typewriter.replace.SearchMetadata; +import io.papermc.typewriter.replace.SearchReplaceRewriter; + +public class RegistryConversionTestRewriter extends SearchReplaceRewriter { + + @Override + public void insert(SearchMetadata metadata, StringBuilder builder) { + RegistryEntries.forEach(entry -> { + if (entry.data().allowInline()) { + builder.append(metadata.indent()); + builder.append("%s.%s,".formatted(Types.REGISTRY_KEY.simpleName(), entry.registryKeyField())); + builder.append("\n"); + } + }); + + builder.deleteCharAt(builder.length() - 2); // delete extra comma... + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryEventsRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryEventsRewriter.java index ef9735652c..1bf43fbeef 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryEventsRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryEventsRewriter.java @@ -1,34 +1,40 @@ package io.papermc.generator.rewriter.types.registry; import io.papermc.generator.registry.RegistryEntries; -import io.papermc.generator.registry.RegistryEntry; -import io.papermc.paper.registry.RegistryKey; -import io.papermc.paper.registry.event.RegistryEventProvider; +import io.papermc.generator.resources.data.RegistryData; +import io.papermc.generator.rewriter.types.Types; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; -import org.jspecify.annotations.NullMarked; import static javax.lang.model.element.Modifier.FINAL; import static javax.lang.model.element.Modifier.PUBLIC; import static javax.lang.model.element.Modifier.STATIC; -@NullMarked public class RegistryEventsRewriter extends SearchReplaceRewriter { @Override public void insert(SearchMetadata metadata, StringBuilder builder) { RegistryEntries.forEach(entry -> { - if (entry.apiRegistryBuilder() != null && entry.modificationApiSupport() != RegistryEntry.RegistryModificationApiSupport.NONE) { + RegistryData data = entry.data(); + data.builder().ifPresent(b -> { + if (b.capability() == RegistryData.Builder.RegisterCapability.NONE) { + return; + } + builder.append(metadata.indent()); builder.append("%s %s %s ".formatted(PUBLIC, STATIC, FINAL)); - builder.append(RegistryEventProvider.class.getSimpleName()); - builder.append("<").append(this.importCollector.getShortName(entry.apiClass())).append(", ").append(this.importCollector.getShortName(entry.apiRegistryBuilder())).append('>'); + builder.append(Types.REGISTRY_EVENT_PROVIDER.simpleName()); + builder.append('<'); + data.api().klass().appendType(builder, name -> this.importCollector.getShortName(name)); + builder.append(", "); + b.appendApiType(builder, name -> this.importCollector.getShortName(name)); + builder.append('>'); builder.append(' '); builder.append(entry.registryKeyField()); builder.append(" = "); - builder.append("create(").append(RegistryKey.class.getSimpleName()).append('.').append(entry.registryKeyField()).append(");"); + builder.append("create(").append(Types.REGISTRY_KEY.simpleName()).append('.').append(entry.registryKeyField()).append(");"); builder.append('\n'); - } + }); }); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryFieldRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryFieldRewriter.java index 5f9526d595..45cc6a251b 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryFieldRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryFieldRewriter.java @@ -1,20 +1,18 @@ package io.papermc.generator.rewriter.types.registry; -import com.google.common.base.Preconditions; import com.google.common.base.Suppliers; -import com.mojang.logging.LogUtils; -import io.papermc.generator.Main; +import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.registry.RegistryEntry; +import io.papermc.generator.registry.RegistryIdentifiable; import io.papermc.generator.rewriter.utils.Annotations; import io.papermc.generator.utils.Formatting; import io.papermc.generator.utils.experimental.ExperimentalCollector; import io.papermc.generator.utils.experimental.SingleFlagHolder; -import io.papermc.typewriter.ClassNamed; import io.papermc.typewriter.SourceFile; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; import java.util.Iterator; import java.util.Map; -import java.util.Objects; import java.util.function.Supplier; import net.minecraft.core.Holder; import net.minecraft.core.Registry; @@ -22,25 +20,20 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.world.flag.FeatureElement; import net.minecraft.world.flag.FeatureFlags; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; import static io.papermc.generator.utils.Formatting.quoted; import static javax.lang.model.element.Modifier.FINAL; import static javax.lang.model.element.Modifier.PUBLIC; import static javax.lang.model.element.Modifier.STATIC; -@NullMarked -public class RegistryFieldRewriter extends SearchReplaceRewriter { - - private static final Logger LOGGER = LogUtils.getLogger(); +public class RegistryFieldRewriter extends SearchReplaceRewriter implements RegistryIdentifiable { private final ResourceKey> registryKey; private final boolean isFilteredRegistry; private final @Nullable String fetchMethod; - protected @MonotonicNonNull ClassNamed fieldClass; + protected @MonotonicNonNull RegistryEntry entry; private @MonotonicNonNull Supplier, SingleFlagHolder>> experimentalKeys; public RegistryFieldRewriter(ResourceKey> registryKey, @Nullable String fetchMethod) { @@ -49,27 +42,21 @@ public class RegistryFieldRewriter extends SearchReplaceRewriter { this.fetchMethod = fetchMethod; } + @Override + public ResourceKey> getRegistryKey() { + return this.registryKey; + } + @Override public boolean registerFor(SourceFile file) { - this.fieldClass = this.options.targetClass().orElse(file.mainClass()); - Preconditions.checkState(this.fieldClass.knownClass() != null, "This rewriter can't run without knowing the field class at runtime!"); - - if (this.fetchMethod != null) { - try { - this.fieldClass.knownClass().getDeclaredMethod(this.fetchMethod, String.class); - } catch (NoSuchMethodException e) { - LOGGER.error("Fetch method not found, skipping the rewriter for registry fields of {}", this.registryKey, e); - return false; - } - } - + this.entry = RegistryEntries.byRegistryKey(this.registryKey); return super.registerFor(file); } @Override protected void insert(SearchMetadata metadata, StringBuilder builder) { - boolean isInterface = Objects.requireNonNull(this.fieldClass.knownClass()).isInterface(); - Registry registry = Main.REGISTRY_ACCESS.lookupOrThrow(this.registryKey); + boolean isInterface = this.entry.data().api().holderClass().isEmpty() || this.entry.data().api().holderClass().get().isInterface(); + Registry registry = this.entry.registry(); this.experimentalKeys = Suppliers.memoize(() -> ExperimentalCollector.collectDataDrivenElementIds(registry)); Iterator> referenceIterator = registry.listElements().filter(this::canPrintField).sorted(Formatting.HOLDER_ORDER).iterator(); @@ -108,7 +95,7 @@ public class RegistryFieldRewriter extends SearchReplaceRewriter { } protected String rewriteFieldType(Holder.Reference reference) { - return this.fieldClass.simpleName(); + return this.entry.data().api().klass().name().simpleName(); } protected String rewriteFieldName(Holder.Reference reference) { diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryTagRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryTagRewriter.java index 99c99efe80..eb196cee25 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryTagRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/RegistryTagRewriter.java @@ -1,63 +1,44 @@ package io.papermc.generator.rewriter.types.registry; -import com.google.common.base.Preconditions; -import com.mojang.logging.LogUtils; import io.papermc.generator.Main; +import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.registry.RegistryEntry; +import io.papermc.generator.registry.RegistryIdentifiable; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.rewriter.utils.Annotations; import io.papermc.generator.utils.Formatting; import io.papermc.generator.utils.experimental.SingleFlagHolder; -import io.papermc.typewriter.ClassNamed; -import io.papermc.typewriter.SourceFile; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; import java.util.Iterator; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.tags.TagKey; -import org.bukkit.Keyed; -import org.bukkit.Tag; import org.jetbrains.annotations.ApiStatus; -import org.jspecify.annotations.NullMarked; -import org.slf4j.Logger; import static io.papermc.generator.utils.Formatting.quoted; import static javax.lang.model.element.Modifier.FINAL; import static javax.lang.model.element.Modifier.PUBLIC; import static javax.lang.model.element.Modifier.STATIC; -@NullMarked @ApiStatus.Obsolete -public class RegistryTagRewriter extends SearchReplaceRewriter { - - private static final Logger LOGGER = LogUtils.getLogger(); +public class RegistryTagRewriter extends SearchReplaceRewriter implements RegistryIdentifiable { private final ResourceKey> registryKey; - private final Class apiClass; - private final String fetchMethod = "getTag"; - public RegistryTagRewriter(ResourceKey> registryKey, Class apiClass) { + public RegistryTagRewriter(ResourceKey> registryKey) { this.registryKey = registryKey; - this.apiClass = apiClass; } @Override - public boolean registerFor(SourceFile file) { - ClassNamed holderClass = this.options.targetClass().orElse(file.mainClass()); - Preconditions.checkState(holderClass.knownClass() != null, "This rewriter can't run without knowing the field class at runtime!"); - try { - holderClass.knownClass().getDeclaredMethod(this.fetchMethod, String.class); - } catch (NoSuchMethodException e) { - LOGGER.error("Fetch method not found, skipping the rewriter for registry tag fields of {}", this.registryKey, e); - return false; - } - - return super.registerFor(file); + public ResourceKey> getRegistryKey() { + return this.registryKey; } @Override protected void insert(SearchMetadata metadata, StringBuilder builder) { - Registry registry = Main.REGISTRY_ACCESS.lookupOrThrow(this.registryKey); - Iterator> keyIterator = registry.listTagIds().sorted(Formatting.TAG_ORDER).iterator(); + RegistryEntry entry = RegistryEntries.byRegistryKey(this.registryKey); + Iterator> keyIterator = entry.registry().listTagIds().sorted(Formatting.TAG_ORDER).iterator(); while (keyIterator.hasNext()) { TagKey tagKey = keyIterator.next(); @@ -70,7 +51,7 @@ public class RegistryTagRewriter extends SearchReplaceRewriter { builder.append(metadata.indent()); builder.append("%s %s %s ".formatted(PUBLIC, STATIC, FINAL)); - builder.append("%s<%s>".formatted(Tag.class.getSimpleName(), this.apiClass.getSimpleName())).append(' ').append(this.rewriteFieldName(tagKey)); + builder.append("%s<%s>".formatted(Types.TAG.simpleName(), entry.data().api().klass().name().simpleName())).append(' ').append(this.rewriteFieldName(tagKey)); builder.append(" = "); builder.append(this.rewriteFieldValue(tagKey)); builder.append(';'); @@ -87,6 +68,6 @@ public class RegistryTagRewriter extends SearchReplaceRewriter { } protected String rewriteFieldValue(TagKey tagKey) { - return "%s(%s)".formatted(this.fetchMethod, quoted(tagKey.location().getPath())); + return "%s(%s)".formatted(TagRewriter.FETCH_METHOD, quoted(tagKey.location().getPath())); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/TagRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/TagRewriter.java index 6bfc438ac8..1bedfcf151 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/TagRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/TagRewriter.java @@ -1,47 +1,89 @@ package io.papermc.generator.rewriter.types.registry; +import com.mojang.logging.LogUtils; import io.papermc.generator.Main; +import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.rewriter.utils.Annotations; import io.papermc.generator.utils.Formatting; import io.papermc.generator.utils.experimental.SingleFlagHolder; +import io.papermc.typewriter.ClassNamed; +import io.papermc.typewriter.parser.Lexer; +import io.papermc.typewriter.parser.sequence.SequenceTokens; +import io.papermc.typewriter.parser.sequence.TokenTaskBuilder; +import io.papermc.typewriter.parser.token.CharSequenceToken; +import io.papermc.typewriter.parser.token.TokenType; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; +import java.util.ArrayList; +import java.util.EnumSet; import java.util.Iterator; +import java.util.List; import java.util.Locale; +import java.util.Set; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.tags.TagKey; -import org.bukkit.Bukkit; -import org.bukkit.Fluid; -import org.bukkit.GameEvent; -import org.bukkit.Keyed; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.entity.EntityType; import org.jetbrains.annotations.ApiStatus; -import org.jspecify.annotations.NullMarked; +import org.slf4j.Logger; import static io.papermc.generator.utils.Formatting.quoted; -@NullMarked @ApiStatus.Obsolete public class TagRewriter extends SearchReplaceRewriter { - public record TagRegistry(String legacyFolderName, Class apiType, ResourceKey> registryKey) { // TODO remove Keyed + private static final Logger LOGGER = LogUtils.getLogger(); + static final String FETCH_METHOD = "getTag"; + + private record TagRegistry(String legacyFolderName, ClassNamed apiType, ResourceKey> registryKey) { + public TagRegistry(String legacyFolderName, ResourceKey> registryKey) { + this(legacyFolderName, RegistryEntries.BY_REGISTRY_KEY.get(registryKey).data().api().klass().name(), registryKey); + } } private static final TagRegistry[] SUPPORTED_REGISTRIES = { // 1.21 folder name are normalized to registry key but api will stay as is - new TagRegistry("blocks", Material.class, Registries.BLOCK), - new TagRegistry("items", Material.class, Registries.ITEM), - new TagRegistry("fluids", Fluid.class, Registries.FLUID), - new TagRegistry("entity_types", EntityType.class, Registries.ENTITY_TYPE), - new TagRegistry("game_events", GameEvent.class, Registries.GAME_EVENT) - // new TagRegistry("damage_types", DamageType.class, Registries.DAMAGE_TYPE) - separate in DamageTypeTags + new TagRegistry("blocks", Types.MATERIAL, Registries.BLOCK), + new TagRegistry("items", Types.MATERIAL, Registries.ITEM), + new TagRegistry("fluids", Registries.FLUID), + new TagRegistry("entity_types", Registries.ENTITY_TYPE), + new TagRegistry("game_events", Registries.GAME_EVENT) + // new TagRegistry("damage_types", Registries.DAMAGE_TYPE) - separate in DamageTypeTags }; + private static final Set FORMAT_TOKENS = EnumSet.of( + TokenType.COMMENT, + TokenType.SINGLE_COMMENT, + TokenType.JAVADOC, + TokenType.MARKDOWN_JAVADOC + ); + + private List parseExistingFields(String content) { + List fields = new ArrayList<>(); + + Lexer lex = new Lexer(content.toCharArray()); + lex.checkMarkdownDocComments = !this.sourcesMetadata.canSkipMarkdownDocComments(); + // todo skipUntilNextLine + cleanup lexer flags + SequenceTokens.wrap(lex, FORMAT_TOKENS) + .group(action -> { + action + .skip(TokenType.IDENTIFIER) // Tag + .skipClosure(TokenType.LT, TokenType.GT, true) // <*> + .map(TokenType.IDENTIFIER, token -> { + fields.add(((CharSequenceToken) token).value()); + }) + .skipQualifiedName() // Bukkit.getTag + .skipClosure(TokenType.LPAREN, TokenType.RPAREN, true) // (*) + .skip(TokenType.SECO); // ; + }, TokenTaskBuilder::asRepeatable) + .executeOrThrow(); + return fields; + } + @Override protected void insert(SearchMetadata metadata, StringBuilder builder) { + List replacedFields = !Main.IS_UPDATING ? new ArrayList<>() : this.parseExistingFields(metadata.replacedContent()); + for (int i = 0, len = SUPPORTED_REGISTRIES.length; i < len; i++) { final TagRegistry tagRegistry = SUPPORTED_REGISTRIES[i]; @@ -56,11 +98,11 @@ public class TagRewriter extends SearchReplaceRewriter { } // registry name field - builder.append(metadata.indent()); - builder.append("%s %s = %s;".formatted(String.class.getSimpleName(), registryFieldName, quoted(tagRegistry.legacyFolderName()))); + //builder.append(metadata.indent()); + //builder.append("%s %s = %s;".formatted(String.class.getSimpleName(), registryFieldName, quoted(tagRegistry.legacyFolderName()))); - builder.append('\n'); - builder.append('\n'); + //builder.append('\n'); + //builder.append('\n'); Iterator> keyIterator = registry.listTagIds().sorted(Formatting.TAG_ORDER).iterator(); @@ -68,6 +110,7 @@ public class TagRewriter extends SearchReplaceRewriter { TagKey tagKey = keyIterator.next(); final String keyPath = tagKey.location().getPath(); final String fieldName = fieldPrefix + Formatting.formatKeyAsField(keyPath); + replacedFields.remove(fieldName); // tag field String featureFlagName = Main.EXPERIMENTAL_TAGS.get(tagKey); @@ -78,7 +121,7 @@ public class TagRewriter extends SearchReplaceRewriter { builder.append(metadata.indent()); builder.append("%s<%s>".formatted(this.source.mainClass().simpleName(), this.importCollector.getShortName(tagRegistry.apiType()))).append(' ').append(fieldName); builder.append(" = "); - builder.append("%s.getTag(%s, %s.minecraft(%s), %s.class)".formatted(Bukkit.class.getSimpleName(), registryFieldName, NamespacedKey.class.getSimpleName(), quoted(keyPath), tagRegistry.apiType().getSimpleName())); // assume type is imported properly + builder.append("%s.%s(%s, %s.minecraft(%s), %s.class)".formatted(Types.BUKKIT_CLASS.simpleName(), FETCH_METHOD, registryFieldName, Types.NAMESPACED_KEY.simpleName(), quoted(keyPath), tagRegistry.apiType().simpleName())); // assume type is imported properly builder.append(';'); builder.append('\n'); @@ -87,5 +130,10 @@ public class TagRewriter extends SearchReplaceRewriter { } } } + + if (!replacedFields.isEmpty()) { + LOGGER.warn("Removed {} tag field(s) from {} because they are no longer present in the game:", replacedFields.size(), Types.TAG.canonicalName()); + replacedFields.forEach(fieldName -> LOGGER.warn("- {}", fieldName)); + } } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/package-info.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/package-info.java new file mode 100644 index 0000000000..cf653ff37a --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/registry/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package io.papermc.generator.rewriter.types.registry; + +import org.jspecify.annotations.NullMarked; diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/BlockPropertiesRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/BlockPropertiesRewriter.java new file mode 100644 index 0000000000..d97262c03a --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/BlockPropertiesRewriter.java @@ -0,0 +1,141 @@ +package io.papermc.generator.rewriter.types.simple; + +import com.squareup.javapoet.ClassName; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; +import io.papermc.generator.rewriter.types.Types; +import io.papermc.generator.utils.BlockStateMapping; +import io.papermc.typewriter.ClassNamed; +import io.papermc.typewriter.replace.SearchMetadata; +import io.papermc.typewriter.replace.SearchReplaceRewriter; +import java.lang.reflect.Field; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Predicate; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.block.state.properties.Property; +import org.jspecify.annotations.Nullable; + +import static io.papermc.generator.utils.Formatting.quoted; +import static javax.lang.model.element.Modifier.FINAL; +import static javax.lang.model.element.Modifier.PUBLIC; +import static javax.lang.model.element.Modifier.STATIC; + +public class BlockPropertiesRewriter extends SearchReplaceRewriter { + + private record BlockPropertyData(ClassNamed propertyClass, String accessorName) { + } + + private static final Map, BlockPropertyData> DATA = Map.of( + BooleanProperty.class, new BlockPropertyData(Types.BOOLEAN_BLOCK_PROPERTY, "bool"), + IntegerProperty.class, new BlockPropertyData(Types.INTEGER_BLOCK_PROPERTY, "integer"), + EnumProperty.class, new BlockPropertyData(Types.ENUM_BLOCK_PROPERTY, "enumeration") + ); + + private record PropertyType(ClassNamed typeClass, ClassNamed propertyClass, @Nullable ClassNamed valueClass) { + } + + private static final Map, PropertyType> MODIFIED_TYPES = Map.of( + BlockStateProperties.NOTE, new PropertyType(Types.BLOCK_PROPERTY, Types.NOTE_BLOCK_PROPERTY, Types.NOTE), + BlockStateProperties.ROTATION_16, new PropertyType(Types.ENUM_BLOCK_PROPERTY, Types.ROTATION_BLOCK_PROPERTY, Types.BLOCK_FACE) + ); + + private interface CodeContext { + void write(StringBuilder builder, Function imported); + } + + private static final Map, CodeContext> PREDICATES = Map.of( + BlockStateProperties.FACING, (builder, imported) -> { + builder.append("%s::isCartesian".formatted(imported.apply(Types.BLOCK_FACE))); + }, + BlockStateProperties.HORIZONTAL_FACING, (builder, imported) -> { + builder.append("%s::isCardinal".formatted(imported.apply(Types.BLOCK_FACE))); + }, + BlockStateProperties.FACING_HOPPER, (builder, imported) -> { + builder.append("((%1$s<%2$s>) %2$s::isCartesian).and(face -> face != %2$s.UP)".formatted( + Predicate.class.getSimpleName(), + imported.apply(Types.BLOCK_FACE) + )); + }, + BlockStateProperties.VERTICAL_DIRECTION, (builder, $) -> { + builder.append("%1$s -> %1$s.getModY() != 0".formatted("face")); + }, + BlockStateProperties.HORIZONTAL_AXIS, (builder, imported) -> { + builder.append("%s::isHorizontal".formatted( + imported.apply(Types.AXIS) + )); + }, + BlockStateProperties.RAIL_SHAPE_STRAIGHT, (builder, imported) -> { + builder.append("%s::isStraight".formatted( + imported.apply(Types.BLOCK_DATA_RAIL_SHAPE) + )); + } + ); + + private static final Comparator, Field>> FIELD_ORDER = + Comparator., Field>, String>comparing(entry -> entry.getKey().getClass().getSimpleName()) + .thenComparing(entry -> entry.getValue().getName()); + + @Override + protected void insert(SearchMetadata metadata, StringBuilder builder) { + Map>, ClassName> enumTypes = DataFileLoader.get(DataFiles.BLOCK_STATE_ENUM_PROPERTY_TYPES); + for (Map.Entry, Field> entry : BlockStateMapping.GENERIC_FIELDS.entrySet().stream().sorted(FIELD_ORDER).toList()) { + Property property = entry.getKey(); + builder.append(metadata.indent()); + builder.append("%s %s %s ".formatted(PUBLIC, STATIC, FINAL)); + BlockPropertyData data = DATA.get(property.getClass()); + + if (MODIFIED_TYPES.containsKey(property)) { + PropertyType type = MODIFIED_TYPES.get(property); + builder.append("%s<%s> %s = register(new %s(%s));".formatted( + type.typeClass().simpleName(), + this.importCollector.getShortName(type.valueClass()), + entry.getValue().getName(), + type.propertyClass().simpleName(), + quoted(entry.getKey().getName()) + )); + } else { + builder.append(data.propertyClass().simpleName()); + ClassNamed enumType = null; + if (property.getClass().equals(EnumProperty.class)) { + builder.append('<'); + if (!enumTypes.containsKey(property.getValueClass())) { + throw new IllegalStateException("Unknown enum type for " + property); + } + enumType = Types.typed(enumTypes.get(property.getValueClass())); + builder.append(this.importCollector.getShortName(enumType)); + builder.append('>'); + } + + builder.append(' '); + builder.append(entry.getValue().getName()); + builder.append(" = "); + builder.append(data.accessorName()); + builder.append('('); + builder.append(quoted(entry.getKey().getName())); + if (property instanceof IntegerProperty intProperty) { + builder.append(", "); + List values = intProperty.getPossibleValues(); + builder.append("%d, %d".formatted(values.getFirst(), values.getLast())); + } else if (enumType != null) { + builder.append(", "); + builder.append("%s.class".formatted(enumType.dottedNestedName())); // already imported + CodeContext predicate = PREDICATES.get(property); + if (predicate != null) { + builder.append(", "); + predicate.write(builder, name -> this.importCollector.getShortName(name)); + } + } + builder.append(");"); + } + + builder.append('\n'); + } + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/BlockTypeRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/BlockTypeRewriter.java index 9a496c75e1..688d78602b 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/BlockTypeRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/BlockTypeRewriter.java @@ -1,13 +1,12 @@ package io.papermc.generator.rewriter.types.simple; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.rewriter.types.registry.RegistryFieldRewriter; import io.papermc.generator.utils.BlockStateMapping; -import io.papermc.typewriter.util.ClassHelper; +import io.papermc.typewriter.ClassNamed; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.world.level.block.Block; -import org.bukkit.block.BlockType; -import org.bukkit.block.data.BlockData; public class BlockTypeRewriter extends RegistryFieldRewriter { @@ -17,11 +16,11 @@ public class BlockTypeRewriter extends RegistryFieldRewriter { @Override protected String rewriteFieldType(Holder.Reference reference) { - Class blockData = BlockStateMapping.getBestSuitedApiClass(reference.value().getClass()); + ClassNamed blockData = BlockStateMapping.getBestSuitedApiClass(reference.value().getClass()); if (blockData == null) { - blockData = BlockData.class; + blockData = Types.BLOCK_DATA; } - return "%s<%s>".formatted(ClassHelper.retrieveFullNestedName(BlockType.Typed.class), this.importCollector.getShortName(blockData)); + return "%s<%s>".formatted(Types.BLOCK_TYPE_TYPED.dottedNestedName(), this.importCollector.getShortName(blockData)); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftBlockDataMapping.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftBlockDataMapping.java index 2a090056e0..7de7f09d2e 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftBlockDataMapping.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftBlockDataMapping.java @@ -1,6 +1,6 @@ package io.papermc.generator.rewriter.types.simple; -import io.papermc.generator.rewriter.types.Types; +import io.papermc.generator.utils.BasePackage; import io.papermc.generator.utils.BlockStateMapping; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; @@ -10,9 +10,9 @@ public class CraftBlockDataMapping extends SearchReplaceRewriter { @Override protected void insert(SearchMetadata metadata, StringBuilder builder) { - BlockStateMapping.MAPPING.entrySet().stream().sorted(Comparator.comparing(entry -> entry.getKey().getCanonicalName())).forEach(entry -> { + BlockStateMapping.getOrCreate().entrySet().stream().sorted(Comparator.comparing(entry -> entry.getKey().getCanonicalName())).forEach(entry -> { builder.append(metadata.indent()); - builder.append("register(%s.class, %s.block.impl.%s::new);".formatted(entry.getKey().getCanonicalName(), Types.BASE_PACKAGE, entry.getValue().implName())); + builder.append("register(%s.class, %s::new);".formatted(entry.getKey().getCanonicalName(), BasePackage.CRAFT_BUKKIT.name().concat(".block.impl.").concat(entry.getValue().implName()))); builder.append('\n'); }); } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftItemMetasRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftItemMetasRewriter.java new file mode 100644 index 0000000000..825cf5c482 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftItemMetasRewriter.java @@ -0,0 +1,92 @@ +package io.papermc.generator.rewriter.types.simple; + +import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; +import io.papermc.generator.resources.predicate.ItemPredicate; +import io.papermc.generator.rewriter.types.Types; +import io.papermc.generator.utils.Formatting; +import io.papermc.typewriter.ClassNamed; +import io.papermc.typewriter.context.IndentUnit; +import io.papermc.typewriter.replace.SearchMetadata; +import io.papermc.typewriter.replace.SearchReplaceRewriter; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; + +@Deprecated +public class CraftItemMetasRewriter extends SearchReplaceRewriter { + + @Override + protected void insert(SearchMetadata metadata, StringBuilder builder) { + IndentUnit indentUnit = this.indentUnit(); + ClassNamed itemType = RegistryEntries.byRegistryKey(Registries.ITEM).data().api().klass().name(); + for (Map.Entry> entry : DataFileLoader.get(DataFiles.ITEM_META_PREDICATES).entrySet()) { + String field = DataFileLoader.get(DataFiles.ITEM_META_BRIDGE).get(entry.getKey()).field(); + Iterator predicateIterator = entry.getValue().iterator(); + + builder.append(metadata.indent()); + builder.append("if ("); + boolean beginning = true; + while (predicateIterator.hasNext()) { + ItemPredicate predicate = predicateIterator.next(); + if (!beginning) { + builder.append(metadata.indent()).append(indentUnit); + } + switch (predicate) { + case ItemPredicate.IsElementPredicate isElementPredicate: + isElementPredicate.value() + .ifLeft(tagKey -> { + // flatten tag since they can change at runtime with plugins/data-packs + Iterator> tagValues = BuiltInRegistries.ITEM.getTagOrEmpty(tagKey).iterator(); + while (tagValues.hasNext()) { + appendElementEquality(builder, itemType, tagValues.next().unwrapKey().orElseThrow().location()); + if (tagValues.hasNext()) { + builder.append(" ||").append("\n"); + builder.append(metadata.indent()).append(indentUnit); + } + } + }) + .ifRight(element -> appendElementEquality(builder, itemType, element.unwrapKey().orElseThrow().location())); + break; + case ItemPredicate.IsClassPredicate isClassPredicate: { + String itemLikeName = isClassPredicate.againstBlock() ? "blockHandle" : "itemHandle"; + if (itemLikeName.equals("itemHandle")) { // itemHandle is never null + builder.append("%s.getClass().equals(%s.class)".formatted(itemLikeName, this.importCollector.getShortName(isClassPredicate.value()))); + } else { + builder.append("(%1$s != null && %1$s.getClass().equals(%2$s.class))".formatted(itemLikeName, this.importCollector.getShortName(isClassPredicate.value()))); + } + break; + } + case ItemPredicate.InstanceOfPredicate instanceOfPredicate: { + String itemLikeName = instanceOfPredicate.againstBlock() ? "blockHandle" : "itemHandle"; + builder.append("%s instanceof %s".formatted(itemLikeName, this.importCollector.getShortName(instanceOfPredicate.value()))); + break; + } + } + if (predicateIterator.hasNext()) { + builder.append(" ||").append("\n"); + } + beginning = false; + } + + builder.append(") {").append("\n"); + { + builder.append(metadata.indent()).append(indentUnit); + builder.append("return %s.asType(%s);".formatted(Types.CRAFT_ITEM_METAS.simpleName(), field)); + builder.append("\n"); + } + builder.append(metadata.indent()); + builder.append("}").append("\n"); + } + } + + private static void appendElementEquality(StringBuilder builder, ClassNamed itemType, ResourceLocation id) { + builder.append("itemType == %s.%s".formatted(itemType.simpleName(), Formatting.formatKeyAsField(id.getPath()))); + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftPotionUtilRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftPotionUtilRewriter.java index df57fadbc8..7eb1ae8f3b 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftPotionUtilRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/CraftPotionUtilRewriter.java @@ -1,12 +1,14 @@ package io.papermc.generator.rewriter.types.simple; +import io.papermc.generator.registry.RegistryEntries; import io.papermc.generator.utils.Formatting; +import io.papermc.typewriter.ClassNamed; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; import java.util.Locale; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; -import org.bukkit.potion.PotionType; @Deprecated(forRemoval = true) public class CraftPotionUtilRewriter extends SearchReplaceRewriter { @@ -20,12 +22,13 @@ public class CraftPotionUtilRewriter extends SearchReplaceRewriter { @Override protected void insert(SearchMetadata metadata, StringBuilder builder) { String upperStatePrefix = this.statePrefix.toUpperCase(Locale.ENGLISH); + ClassNamed potionType = RegistryEntries.byRegistryKey(Registries.POTION).data().api().klass().name(); BuiltInRegistries.POTION.keySet().stream() .filter(key -> BuiltInRegistries.POTION.containsKey(key.withPath(path -> this.statePrefix + "_" + path))) .sorted(Formatting.alphabeticKeyOrder(ResourceLocation::getPath)).forEach(key -> { String keyedName = Formatting.formatKeyAsField(key.getPath()); builder.append(metadata.indent()); - builder.append(".put(%s.%s, %s.%s_%s)".formatted(PotionType.class.getSimpleName(), keyedName, PotionType.class.getSimpleName(), upperStatePrefix, keyedName)); + builder.append(".put(%1$s.%2$s, %1$s.%3$s_%4$s)".formatted(potionType.simpleName(), keyedName, upperStatePrefix, keyedName)); builder.append('\n'); }); } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/EntityTypeRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/EntityTypeRewriter.java index d3e548ab0a..4eaf8cceca 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/EntityTypeRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/EntityTypeRewriter.java @@ -1,176 +1,37 @@ package io.papermc.generator.rewriter.types.simple; -import com.google.common.base.CaseFormat; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; +import io.papermc.generator.resources.data.EntityTypeData; import io.papermc.generator.rewriter.types.registry.EnumRegistryRewriter; -import io.papermc.generator.types.goal.MobGoalNames; -import io.papermc.typewriter.ClassNamed; -import io.papermc.typewriter.preset.model.EnumValue; -import io.papermc.typewriter.util.ClassResolver; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import java.lang.reflect.ParameterizedType; +import io.papermc.typewriter.preset.model.EnumConstant; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import net.minecraft.Util; +import java.util.Objects; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.Mob; import static io.papermc.generator.utils.Formatting.quoted; public class EntityTypeRewriter extends EnumRegistryRewriter> { - private static final Map>, Class> ENTITY_GENERIC_TYPES = - RegistryEntries.byRegistryKey(Registries.ENTITY_TYPE).getFields(field -> { - if (field.getGenericType() instanceof ParameterizedType complexType && complexType.getActualTypeArguments().length == 1) { - return (Class) complexType.getActualTypeArguments()[0]; - } - return null; - }); - - private static final Map CLASS_RENAMES = ImmutableMap.builder() - .put("ExperienceBottle", "ThrownExpBottle") - .put("EyeOfEnder", "EnderSignal") - .put("EndCrystal", "EnderCrystal") - .put("FireworkRocket", "Firework") - .put("FishingBobber", "FishHook") - .put("LeashKnot", "LeashHitch") - .put("LightningBolt", "LightningStrike") - .put("Tnt", "TNTPrimed") - .put("Minecart", "RideableMinecart") - .put("ChestMinecart", "StorageMinecart") - .put("CommandBlockMinecart", "CommandMinecart") - .put("TntMinecart", "ExplosiveMinecart") - .put("FurnaceMinecart", "PoweredMinecart") - .buildOrThrow(); - - @Deprecated - private static final Object2IntMap> LEGACY_ID = Util.make(new Object2IntOpenHashMap<>(), map -> { - map.put(EntityType.ITEM, 1); - map.put(EntityType.EXPERIENCE_ORB, 2); - map.put(EntityType.AREA_EFFECT_CLOUD, 3); - map.put(EntityType.ELDER_GUARDIAN, 4); - map.put(EntityType.WITHER_SKELETON, 5); - map.put(EntityType.STRAY, 6); - map.put(EntityType.EGG, 7); - map.put(EntityType.LEASH_KNOT, 8); - map.put(EntityType.PAINTING, 9); - map.put(EntityType.ARROW, 10); - map.put(EntityType.SNOWBALL, 11); - map.put(EntityType.FIREBALL, 12); - map.put(EntityType.SMALL_FIREBALL, 13); - map.put(EntityType.ENDER_PEARL, 14); - map.put(EntityType.EYE_OF_ENDER, 15); - map.put(EntityType.SPLASH_POTION, 16); - map.put(EntityType.EXPERIENCE_BOTTLE, 17); - map.put(EntityType.ITEM_FRAME, 18); - map.put(EntityType.WITHER_SKULL, 19); - map.put(EntityType.TNT, 20); - map.put(EntityType.FALLING_BLOCK, 21); - map.put(EntityType.FIREWORK_ROCKET, 22); - map.put(EntityType.HUSK, 23); - map.put(EntityType.SPECTRAL_ARROW, 24); - map.put(EntityType.SHULKER_BULLET, 25); - map.put(EntityType.DRAGON_FIREBALL, 26); - map.put(EntityType.ZOMBIE_VILLAGER, 27); - map.put(EntityType.SKELETON_HORSE, 28); - map.put(EntityType.ZOMBIE_HORSE, 29); - map.put(EntityType.ARMOR_STAND, 30); - map.put(EntityType.DONKEY, 31); - map.put(EntityType.MULE, 32); - map.put(EntityType.EVOKER_FANGS, 33); - map.put(EntityType.EVOKER, 34); - map.put(EntityType.VEX, 35); - map.put(EntityType.VINDICATOR, 36); - map.put(EntityType.ILLUSIONER, 37); - - map.put(EntityType.COMMAND_BLOCK_MINECART, 40); - map.put(EntityType.MINECART, 42); - map.put(EntityType.CHEST_MINECART, 43); - map.put(EntityType.FURNACE_MINECART, 44); - map.put(EntityType.TNT_MINECART, 45); - map.put(EntityType.HOPPER_MINECART, 46); - map.put(EntityType.SPAWNER_MINECART, 47); - - map.put(EntityType.CREEPER, 50); - map.put(EntityType.SKELETON, 51); - map.put(EntityType.SPIDER, 52); - map.put(EntityType.GIANT, 53); - map.put(EntityType.ZOMBIE, 54); - map.put(EntityType.SLIME, 55); - map.put(EntityType.GHAST, 56); - map.put(EntityType.ZOMBIFIED_PIGLIN, 57); - map.put(EntityType.ENDERMAN, 58); - map.put(EntityType.CAVE_SPIDER, 59); - map.put(EntityType.SILVERFISH, 60); - map.put(EntityType.BLAZE, 61); - map.put(EntityType.MAGMA_CUBE, 62); - map.put(EntityType.ENDER_DRAGON, 63); - map.put(EntityType.WITHER, 64); - map.put(EntityType.BAT, 65); - map.put(EntityType.WITCH, 66); - map.put(EntityType.ENDERMITE, 67); - map.put(EntityType.GUARDIAN, 68); - map.put(EntityType.SHULKER, 69); - - map.put(EntityType.PIG, 90); - map.put(EntityType.SHEEP, 91); - map.put(EntityType.COW, 92); - map.put(EntityType.CHICKEN, 93); - map.put(EntityType.SQUID, 94); - map.put(EntityType.WOLF, 95); - map.put(EntityType.MOOSHROOM, 96); - map.put(EntityType.SNOW_GOLEM, 97); - map.put(EntityType.OCELOT, 98); - map.put(EntityType.IRON_GOLEM, 99); - map.put(EntityType.HORSE, 100); - map.put(EntityType.RABBIT, 101); - map.put(EntityType.POLAR_BEAR, 102); - map.put(EntityType.LLAMA, 103); - map.put(EntityType.LLAMA_SPIT, 104); - map.put(EntityType.PARROT, 105); - - map.put(EntityType.VILLAGER, 120); - - map.put(EntityType.END_CRYSTAL, 200); - }); - - private static final ClassResolver runtime = new ClassResolver(EntityTypeRewriter.class.getClassLoader()); - public EntityTypeRewriter() { - super(Registries.ENTITY_TYPE, false); + super(Registries.ENTITY_TYPE); } @Override - protected EnumValue.Builder rewriteEnumValue(Holder.Reference> reference) { + protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference> reference) { + EntityTypeData data = Objects.requireNonNull(DataFileLoader.get(DataFiles.ENTITY_TYPES).get(reference.key()), () -> "Missing entity type data for " + reference); String path = reference.key().location().getPath(); List arguments = new ArrayList<>(4); arguments.add(quoted(path)); - arguments.add(toBukkitClass(reference).concat(".class")); - arguments.add(Integer.toString(LEGACY_ID.getOrDefault(reference.value(), -1))); + arguments.add(this.importCollector.getShortName(data.api()).concat(".class")); + arguments.add(Integer.toString(data.legacyId())); if (!reference.value().canSummon()) { arguments.add(Boolean.FALSE.toString()); } - return super.rewriteEnumValue(reference).arguments(arguments); - } - - private String toBukkitClass(Holder.Reference> reference) { - Class internalClass = ENTITY_GENERIC_TYPES.get(reference.key()); - if (Mob.class.isAssignableFrom(internalClass)) { - return this.importCollector.getShortName(MobGoalNames.BUKKIT_BRIDGE.get((Class) internalClass)); - } - - String className = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, reference.key().location().getPath()); // use the key instead of the internal class name since name match a bit more - ClassNamed resolvedClass = this.classNamedView.findFirst(CLASS_RENAMES.getOrDefault(className, className)).resolve(runtime); - Preconditions.checkArgument(org.bukkit.entity.Entity.class.isAssignableFrom(resolvedClass.knownClass()), "Generic type must be an entity"); - return this.importCollector.getShortName(this.classNamedView.findFirst(CLASS_RENAMES.getOrDefault(className, className)).resolve(runtime)); + builder.arguments(arguments); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/ItemTypeRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/ItemTypeRewriter.java index 232cf52237..5b5fd3b1b1 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/ItemTypeRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/ItemTypeRewriter.java @@ -1,13 +1,17 @@ package io.papermc.generator.rewriter.types.simple; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; +import io.papermc.generator.resources.predicate.ItemPredicate; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.rewriter.types.registry.RegistryFieldRewriter; -import io.papermc.typewriter.util.ClassHelper; +import io.papermc.typewriter.ClassNamed; +import java.util.List; +import java.util.Map; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; -import org.bukkit.inventory.ItemType; -import org.bukkit.inventory.meta.ItemMeta; @Deprecated // bad generic public class ItemTypeRewriter extends RegistryFieldRewriter { @@ -22,6 +26,21 @@ public class ItemTypeRewriter extends RegistryFieldRewriter { return super.rewriteFieldType(reference); } - return "%s<%s>".formatted(ClassHelper.retrieveFullNestedName(ItemType.Typed.class), ItemMeta.class.getSimpleName()); + ClassNamed implMetaName = null; + mainLoop: + for (Map.Entry> entry : DataFileLoader.get(DataFiles.ITEM_META_PREDICATES).entrySet()) { + for (ItemPredicate predicate : entry.getValue()) { + if (predicate.matches(reference)) { + implMetaName = entry.getKey(); + break mainLoop; + } + } + } + + ClassNamed metaName = null; + if (implMetaName != null) { + metaName = DataFileLoader.get(DataFiles.ITEM_META_BRIDGE).get(implMetaName).api(); + } + return "%s<%s>".formatted(Types.ITEM_TYPE_TYPED.dottedNestedName(), metaName != null ? this.importCollector.getShortName(metaName) : Types.ITEM_META.simpleName()); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MapPaletteRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MapPaletteRewriter.java index 18f4902389..d3bade1485 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MapPaletteRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MapPaletteRewriter.java @@ -1,6 +1,7 @@ package io.papermc.generator.rewriter.types.simple; import com.mojang.logging.LogUtils; +import io.papermc.generator.Main; import io.papermc.typewriter.replace.SearchMetadata; import io.papermc.typewriter.replace.SearchReplaceRewriter; import java.awt.Color; @@ -11,7 +12,6 @@ import org.slf4j.Logger; public class MapPaletteRewriter extends SearchReplaceRewriter { private static final Logger LOGGER = LogUtils.getLogger(); - private static final boolean UPDATING = Boolean.getBoolean("paper.updatingMinecraft"); @Override protected void insert(SearchMetadata metadata, StringBuilder builder) { @@ -34,7 +34,7 @@ public class MapPaletteRewriter extends SearchReplaceRewriter { } } - if (UPDATING) { + if (Main.IS_UPDATING) { LOGGER.warn("There are {} map colors, check CraftMapView#render for possible change and update md5 hash in CraftMapColorCache", count); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MaterialRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MaterialRewriter.java index 764fa4a506..9c0896e73d 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MaterialRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MaterialRewriter.java @@ -1,9 +1,13 @@ package io.papermc.generator.rewriter.types.simple; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.rewriter.types.registry.EnumRegistryRewriter; import io.papermc.generator.utils.BlockStateMapping; import io.papermc.generator.utils.Formatting; -import io.papermc.typewriter.preset.model.EnumValue; +import io.papermc.typewriter.ClassNamed; +import io.papermc.typewriter.preset.model.EnumConstant; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; @@ -11,9 +15,6 @@ import net.minecraft.core.registries.Registries; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.WallSignBlock; -import org.bukkit.block.data.BlockData; - -import static io.papermc.generator.utils.Formatting.asCode; @Deprecated(forRemoval = true) public class MaterialRewriter { @@ -23,7 +24,7 @@ public class MaterialRewriter { public static class Blocks extends EnumRegistryRewriter { public Blocks() { - super(Registries.BLOCK, false); + super(Registries.BLOCK); } @Override @@ -33,10 +34,12 @@ public class MaterialRewriter { } @Override - protected EnumValue.Builder rewriteEnumValue(Holder.Reference reference) { - EnumValue.Builder value = super.rewriteEnumValue(reference); + protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference reference) { Block block = reference.value(); - if (BlockStateMapping.MAPPING.containsKey(block.getClass())) { + List args = new ArrayList<>(3); + args.add(Integer.toString(-1)); // legacy id (not needed for non legacy material) + + if (BlockStateMapping.getOrCreate().containsKey(block.getClass())) { // some block can also be represented as item in that enum // doing a double job Optional equivalentItem = BuiltInRegistries.ITEM.getOptional(reference.key().location()); @@ -47,16 +50,16 @@ public class MaterialRewriter { equivalentItem = Optional.of(block.asItem()); } - Class blockData = BlockStateMapping.getBestSuitedApiClass(block.getClass()); + ClassNamed blockData = BlockStateMapping.getBestSuitedApiClass(block.getClass()); if (blockData == null) { - blockData = BlockData.class; + blockData = Types.BLOCK_DATA; } if (equivalentItem.isPresent() && equivalentItem.get().getDefaultMaxStackSize() != Item.DEFAULT_MAX_STACK_SIZE) { - return value.arguments(Integer.toString(-1), Integer.toString(equivalentItem.get().getDefaultMaxStackSize()), this.importCollector.getShortName(blockData).concat(".class")); + args.add(Integer.toString(equivalentItem.get().getDefaultMaxStackSize())); // max stack size } - return value.arguments(Integer.toString(-1), this.importCollector.getShortName(blockData).concat(".class")); + args.add(this.importCollector.getShortName(blockData).concat(".class")); // block data class } - return value.argument(Integer.toString(-1)); // id not needed for non legacy material + builder.arguments(args); } } @@ -79,7 +82,7 @@ public class MaterialRewriter { public static class Items extends EnumRegistryRewriter { public Items() { - super(Registries.ITEM, false); + super(Registries.ITEM); } @Override @@ -89,15 +92,17 @@ public class MaterialRewriter { } @Override - protected EnumValue.Builder rewriteEnumValue(Holder.Reference reference) { - EnumValue.Builder value = super.rewriteEnumValue(reference); + protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference reference) { Item item = reference.value(); + List args = new ArrayList<>(2); + args.add(Integer.toString(-1)); // legacy id (not needed for non legacy material) + int maxStackSize = item.getDefaultMaxStackSize(); if (maxStackSize != Item.DEFAULT_MAX_STACK_SIZE) { - return value.arguments(asCode(-1, maxStackSize)); + args.add(Integer.toString(maxStackSize)); } - return value.argument(Integer.toString(-1)); // id not needed for non legacy material + builder.arguments(args); } } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MemoryKeyRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MemoryKeyRewriter.java index 08e321aabd..71f14b7ae5 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MemoryKeyRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/MemoryKeyRewriter.java @@ -2,8 +2,10 @@ package io.papermc.generator.rewriter.types.simple; import com.google.gson.internal.Primitives; import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.rewriter.types.registry.RegistryFieldRewriter; import io.papermc.generator.utils.ClassHelper; +import io.papermc.typewriter.ClassNamed; import java.lang.reflect.ParameterizedType; import java.util.Map; import java.util.Set; @@ -21,8 +23,6 @@ import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities; import net.minecraft.world.entity.ai.memory.WalkTarget; import net.minecraft.world.level.pathfinder.Path; import net.minecraft.world.phys.Vec3; -import org.bukkit.Location; -import org.bukkit.NamespacedKey; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import static io.papermc.generator.utils.Formatting.quoted; @@ -60,8 +60,8 @@ public class MemoryKeyRewriter extends RegistryFieldRewriter Entity.class ); - private static final Map, Class> API_BRIDGE = Map.of( - GlobalPos.class, Location.class + private static final Map, ClassNamed> API_BRIDGE = Map.of( + GlobalPos.class, Types.LOCATION ); private static final Map FIELD_RENAMES = Map.of( @@ -83,7 +83,7 @@ public class MemoryKeyRewriter extends RegistryFieldRewriter return true; } - private @MonotonicNonNull Class apiMemoryType; + private @MonotonicNonNull ClassNamed apiMemoryType; @Override protected String rewriteFieldType(Holder.Reference> reference) { @@ -92,10 +92,10 @@ public class MemoryKeyRewriter extends RegistryFieldRewriter if (!Primitives.isWrapperType(memoryType) && API_BRIDGE.containsKey(memoryType)) { this.apiMemoryType = API_BRIDGE.get(memoryType); } else { - this.apiMemoryType = memoryType; + this.apiMemoryType = new ClassNamed(memoryType); } - return "%s<%s>".formatted(this.fieldClass.simpleName(), this.importCollector.getShortName(this.apiMemoryType)); + return "%s<%s>".formatted(this.entry.data().api().klass().name().simpleName(), this.importCollector.getShortName(this.apiMemoryType)); } @Override @@ -107,10 +107,10 @@ public class MemoryKeyRewriter extends RegistryFieldRewriter @Override protected String rewriteFieldValue(Holder.Reference> reference) { return "new %s<>(%s.minecraft(%s), %s.class)".formatted( - this.fieldClass.simpleName(), - NamespacedKey.class.getSimpleName(), + this.entry.data().api().klass().name().simpleName(), + Types.NAMESPACED_KEY.simpleName(), quoted(reference.key().location().getPath()), - this.apiMemoryType.getSimpleName() // assume the type is already import (see above in rewriteFieldType) + this.apiMemoryType.simpleName() // assume the type is already imported (see above in rewriteFieldType) ); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/StatisticRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/StatisticRewriter.java index 8af0709727..27b11b4566 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/StatisticRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/StatisticRewriter.java @@ -1,15 +1,11 @@ package io.papermc.generator.rewriter.types.simple; import com.google.common.collect.ImmutableMap; +import io.papermc.generator.registry.RegistryEntries; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.rewriter.types.registry.EnumRegistryRewriter; -import io.papermc.generator.utils.ClassHelper; import io.papermc.generator.utils.Formatting; -import io.papermc.typewriter.preset.model.EnumValue; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.util.Collections; -import java.util.IdentityHashMap; +import io.papermc.typewriter.preset.model.EnumConstant; import java.util.Map; import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; @@ -20,7 +16,6 @@ import net.minecraft.stats.Stats; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; -import org.bukkit.Statistic; import static io.papermc.generator.utils.Formatting.quoted; @@ -65,12 +60,12 @@ public class StatisticRewriter { public static class Custom extends EnumRegistryRewriter { public Custom() { - super(Registries.CUSTOM_STAT, false); + super(Registries.CUSTOM_STAT); } @Override - protected EnumValue.Builder rewriteEnumValue(Holder.Reference reference) { - return super.rewriteEnumValue(reference).rename(name -> FIELD_RENAMES.getOrDefault(name, name)); + protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference reference) { + builder.rename(name -> FIELD_RENAMES.getOrDefault(name, name)); } } @@ -81,16 +76,14 @@ public class StatisticRewriter { ); public CraftCustom() { - super(Registries.CUSTOM_STAT, false); + super(Registries.CUSTOM_STAT); } @Override - protected EnumValue.Builder rewriteEnumValue(Holder.Reference reference) { - String keyedName = Formatting.formatKeyAsField(reference.key().location().getPath()); - - return super.rewriteEnumValue(reference) + protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference reference) { + builder .rename(name -> FIELD_RENAMES.getOrDefault(name, name)) - .argument("%s.%s".formatted(Stats.class.getSimpleName(), INTERNAL_FIELD_RENAMES.getOrDefault(keyedName, keyedName))); + .argument("%s.%s".formatted(Stats.class.getSimpleName(), INTERNAL_FIELD_RENAMES.getOrDefault(builder.initialName(), builder.initialName()))); } } @@ -102,30 +95,8 @@ public class StatisticRewriter { EntityType.class, "ENTITY" ); - private static final Map, Class> FIELD_GENERIC_TYPE; - - static { - final Map, Class> map = new IdentityHashMap<>(); - - try { - for (Field field : Stats.class.getDeclaredFields()) { - if (field.getType() != StatType.class) { - continue; - } - - if (ClassHelper.isStaticConstant(field, Modifier.PUBLIC)) { - java.lang.reflect.Type genericType = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]; - map.put((StatType) field.get(null), ClassHelper.eraseType(genericType)); - } - } - } catch (ReflectiveOperationException ex) { - throw new RuntimeException(ex); - } - FIELD_GENERIC_TYPE = Collections.unmodifiableMap(map); - } - public Type() { - super(Registries.STAT_TYPE, false); + super(Registries.STAT_TYPE); } @Override @@ -135,23 +106,22 @@ public class StatisticRewriter { } @Override - protected EnumValue.Builder rewriteEnumValue(Holder.Reference> reference) { - Class genericType = FIELD_GENERIC_TYPE.get(reference.value()); + protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference> reference) { + Class genericType = RegistryEntries.byRegistryKey(reference.value().getRegistry().key()).elementClass(); if (!TYPE_MAPPING.containsKey(genericType)) { throw new IllegalStateException("Unable to translate stat type generic " + genericType.getCanonicalName() + " into the api!"); } - return super.rewriteEnumValue(reference) + builder .rename(name -> FIELD_RENAMES.getOrDefault(name, name)) - .argument("%s.%s".formatted(Statistic.Type.class.getSimpleName(), TYPE_MAPPING.get(genericType))); // find a more direct way? - + .argument("%s.%s".formatted(Types.STATISTIC_TYPE.simpleName(), TYPE_MAPPING.get(genericType))); // find a more direct way? } } public static class CraftType extends EnumRegistryRewriter> { public CraftType() { - super(Registries.STAT_TYPE, false); + super(Registries.STAT_TYPE); } @Override @@ -161,8 +131,8 @@ public class StatisticRewriter { } @Override - protected EnumValue.Builder rewriteEnumValue(Holder.Reference> reference) { - return super.rewriteEnumValue(reference) + protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference> reference) { + builder .rename(name -> FIELD_RENAMES.getOrDefault(name, name)) .argument("%s.withDefaultNamespace(%s)".formatted(ResourceLocation.class.getSimpleName(), quoted(reference.key().location().getPath()))); } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/AttributeRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/AttributeRewriter.java new file mode 100644 index 0000000000..36d3742f05 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/AttributeRewriter.java @@ -0,0 +1,80 @@ +package io.papermc.generator.rewriter.types.simple.trial; + +import io.papermc.generator.rewriter.types.registry.RegistryFieldRewriter; +import io.papermc.typewriter.parser.Lexer; +import io.papermc.typewriter.parser.sequence.SequenceTokens; +import io.papermc.typewriter.parser.sequence.TokenTaskBuilder; +import io.papermc.typewriter.parser.token.CharSequenceBlockToken; +import io.papermc.typewriter.parser.token.CharSequenceToken; +import io.papermc.typewriter.parser.token.TokenType; +import io.papermc.typewriter.replace.SearchMetadata; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.entity.ai.attributes.Attribute; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + +public class AttributeRewriter extends RegistryFieldRewriter { + + public AttributeRewriter() { + super(Registries.ATTRIBUTE, "getAttribute"); + } + + private static final Set FORMAT_TOKENS = EnumSet.of( + TokenType.COMMENT, + TokenType.SINGLE_COMMENT + ); + + private @MonotonicNonNull Map javadocsPerConstant; + + private Map parseConstantJavadocs(String content) { + if (content.isBlank()) { + return Map.of(); + } + + Map map = new HashMap<>(); + + Lexer lex = new Lexer(content.toCharArray()); + lex.checkMarkdownDocComments = !this.sourcesMetadata.canSkipMarkdownDocComments(); + SequenceTokens.wrap(lex, FORMAT_TOKENS) + .group(action -> { + ProtoConstant constant = new ProtoConstant(); + action + .map(TokenType.JAVADOC, token -> { // /** */ + constant.javadocs(((CharSequenceBlockToken) token)); + }, TokenTaskBuilder::asOptional) + .skip(TokenType.IDENTIFIER) // Attribute + .map(TokenType.IDENTIFIER, token -> { // + constant.name(((CharSequenceToken) token).value()); + }) + .skip(TokenType.IDENTIFIER) // getAttribute + .skipClosure(TokenType.LPAREN, TokenType.RPAREN, true) // (*) + .map(TokenType.SECO, $ -> { // ; + if (constant.isComplete()) { + map.put(constant.name(), constant.javadocs()); + } + }); + }, TokenTaskBuilder::asRepeatable) + .executeOrThrow(); + + return map; + } + + @Override + protected void insert(SearchMetadata metadata, StringBuilder builder) { + this.javadocsPerConstant = parseConstantJavadocs(metadata.replacedContent()); + super.insert(metadata, builder); + } + + @Override + protected void rewriteJavadocs(Holder.Reference reference, String replacedContent, String indent, StringBuilder builder) { + String constantName = this.rewriteFieldName(reference); + if (this.javadocsPerConstant.containsKey(constantName)) { + CharSequenceBlockToken token = this.javadocsPerConstant.get(constantName); + builder.append(indent).append(replacedContent, token.pos(), token.endPos()).append('\n'); + } + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/PoseRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/PoseRewriter.java index 42dc3f8b0c..66c153d760 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/PoseRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/PoseRewriter.java @@ -7,7 +7,7 @@ import io.papermc.typewriter.parser.token.CharSequenceBlockToken; import io.papermc.typewriter.parser.token.CharSequenceToken; import io.papermc.typewriter.parser.token.TokenType; import io.papermc.typewriter.preset.EnumCloneRewriter; -import io.papermc.typewriter.preset.model.EnumValue; +import io.papermc.typewriter.preset.model.EnumConstant; import io.papermc.typewriter.replace.SearchMetadata; import java.util.EnumSet; import java.util.HashMap; @@ -35,6 +35,10 @@ public class PoseRewriter extends EnumCloneRewriter { private @MonotonicNonNull Map javadocsPerConstant; private Map parseConstantJavadocs(String content) { + if (content.isBlank()) { + return Map.of(); + } + Map map = new HashMap<>(); Lexer lex = new Lexer(content.toCharArray()); @@ -77,17 +81,17 @@ public class PoseRewriter extends EnumCloneRewriter { } @Override - protected EnumValue.Builder rewriteEnumValue(Pose item) { - return super.rewriteEnumValue(item).rename(name -> RENAMES.getOrDefault(name, name)); + protected void rewriteConstant(EnumConstant.Builder builder, Pose item) { + builder.rename(name -> RENAMES.getOrDefault(name, name)); } @Override - protected void appendEnumValue(Pose item, StringBuilder builder, String indent, boolean reachEnd) { + protected void appendConstant(Pose item, StringBuilder builder, String indent, boolean reachEnd) { String constantName = RENAMES.getOrDefault(item.name(), item.name()); if (this.javadocsPerConstant.containsKey(constantName)) { CharSequenceBlockToken token = this.javadocsPerConstant.get(constantName); builder.append(indent).append(this.metadata.replacedContent(), token.pos(), token.endPos()).append('\n'); } - super.appendEnumValue(item, builder, indent, reachEnd); + super.appendConstant(item, builder, indent, reachEnd); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/VillagerProfessionRewriter.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/VillagerProfessionRewriter.java index 52884792aa..44b3bcc675 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/VillagerProfessionRewriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/types/simple/trial/VillagerProfessionRewriter.java @@ -12,7 +12,6 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.Map; import java.util.Set; -import java.util.function.Predicate; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.npc.VillagerProfession; @@ -32,6 +31,10 @@ public class VillagerProfessionRewriter extends RegistryFieldRewriter javadocsPerConstant; private Map parseConstantJavadocs(String content) { + if (content.isBlank()) { + return Map.of(); + } + Map map = new HashMap<>(); Lexer lex = new Lexer(content.toCharArray()); @@ -40,46 +43,22 @@ public class VillagerProfessionRewriter extends RegistryFieldRewriter { ProtoConstant constant = new ProtoConstant(); action - .map(TokenType.JAVADOC, token -> { + .map(TokenType.JAVADOC, token -> { // /** */ constant.javadocs(((CharSequenceBlockToken) token)); }, TokenTaskBuilder::asOptional) - .skipQualifiedName(Predicate.isEqual(TokenType.JAVADOC)) - .map(TokenType.IDENTIFIER, token -> { + .skip(TokenType.IDENTIFIER) // Profession + .map(TokenType.IDENTIFIER, token -> { // constant.name(((CharSequenceToken) token).value()); }) - .skip(TokenType.IDENTIFIER) - .skipClosure(TokenType.LPAREN, TokenType.RPAREN, true) - .map(TokenType.SECO, $ -> { + .skip(TokenType.IDENTIFIER) // getProfession + .skipClosure(TokenType.LPAREN, TokenType.RPAREN, true) // (*) + .map(TokenType.SECO, $ -> { // ; if (constant.isComplete()) { map.put(constant.name(), constant.javadocs()); } }); }, TokenTaskBuilder::asRepeatable) .executeOrThrow(); - /* - for enums: - Set endMarkers = Set.of(TokenType.CO, TokenType.SECO); // move to static - SequenceTokens.wrap(lex, FORMAT_TOKENS) - .group(action -> { - ProtoConstant constant = new ProtoConstant(); - action - .map(TokenType.JAVADOC, token -> { - constant.javadocs(((CharSequenceBlockToken) token).value()); - }, TokenTaskBuilder::asOptional) - .map(TokenType.IDENTIFIER, token -> { - constant.name(((CharSequenceToken) token).value()); - }) - .skipClosure(TokenType.LPAREN, TokenType.RPAREN, true) - .skipClosure(TokenType.LSCOPE, TokenType.RSCOPE, true) - .map(endMarkers::contains, $ -> { - // this part will probably fail for the last entry for enum without end (,;) - if (constant.isComplete()) { - map.put(constant.name(), constant.javadocs()); - } - }); - }, TokenTaskBuilder::asRepeatable) - .executeOrThrow(); - */ return map; } diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/utils/Annotations.java b/paper-generator/src/main/java/io/papermc/generator/rewriter/utils/Annotations.java index a2e58656e0..a52d4d215a 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/utils/Annotations.java +++ b/paper-generator/src/main/java/io/papermc/generator/rewriter/utils/Annotations.java @@ -1,10 +1,11 @@ package io.papermc.generator.rewriter.utils; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.utils.experimental.SingleFlagHolder; +import io.papermc.typewriter.ClassNamed; import io.papermc.typewriter.context.ImportCollector; import io.papermc.typewriter.util.ClassHelper; import java.lang.annotation.Annotation; -import org.bukkit.MinecraftExperimental; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; @@ -20,6 +21,22 @@ public final class Annotations { } public static String annotation(Class clazz, ImportCollector collector, String param, String value) { + return annotation(new ClassNamed(clazz), collector, param, value); + } + + public static String annotation(Class clazz, ImportCollector collector, String value) { + return annotation(new ClassNamed(clazz), collector, value); + } + + public static String annotation(ClassNamed clazz, ImportCollector collector) { + return "@%s".formatted(collector.getShortName(clazz)); + } + + public static String annotationStyle(ClassNamed clazz) { + return "@%s".formatted(clazz.dottedNestedName()); + } + + public static String annotation(ClassNamed clazz, ImportCollector collector, String param, String value) { String annotation = annotation(clazz, collector); if (value.isEmpty()) { return annotation; @@ -27,7 +44,7 @@ public final class Annotations { return "%s(%s = %s)".formatted(annotation, param, value); } - public static String annotation(Class clazz, ImportCollector collector, String value) { + public static String annotation(ClassNamed clazz, ImportCollector collector, String value) { String annotation = annotation(clazz, collector); if (value.isEmpty()) { return annotation; @@ -36,8 +53,8 @@ public final class Annotations { } public static void experimentalAnnotations(StringBuilder builder, String indent, ImportCollector importCollector, SingleFlagHolder requiredFeature) { - builder.append(indent).append(annotation(MinecraftExperimental.class, importCollector, "%s.%s".formatted( - importCollector.getShortName(MinecraftExperimental.Requires.class, false), requiredFeature.asAnnotationMember().name() + builder.append(indent).append(annotation(Types.MINECRAFT_EXPERIMENTAL, importCollector, "%s.%s".formatted( + importCollector.getShortName(Types.MINECRAFT_EXPERIMENTAL_REQUIRES, false), requiredFeature.asAnnotationMember() ))).append('\n'); builder.append(indent).append(annotation(ApiStatus.Experimental.class, importCollector)).append('\n'); diff --git a/paper-generator/src/main/java/io/papermc/generator/tasks/PrepareInputFiles.java b/paper-generator/src/main/java/io/papermc/generator/tasks/PrepareInputFiles.java new file mode 100644 index 0000000000..0aa70e0dd8 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/tasks/PrepareInputFiles.java @@ -0,0 +1,46 @@ +package io.papermc.generator.tasks; + +import com.mojang.logging.LogUtils; +import io.papermc.generator.Main; +import io.papermc.generator.resources.DataFile; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.FlattenSliceResult; +import io.papermc.generator.resources.SliceResult; +import java.io.IOException; +import java.nio.file.Path; +import org.slf4j.Logger; + +public class PrepareInputFiles { + + static { + Main.bootStrap(true); + } + + private static final Logger LOGGER = LogUtils.getLogger(); + + public static void main(String[] args) throws IOException { + Path resourceDir = Path.of(args[0]); + for (DataFile file : DataFileLoader.DATA_FILES_VIEW.values()) { + upgrade(resourceDir, file); + } + } + + private static void upgrade(Path resourceDir, DataFile file) throws IOException { + Path filePath = Path.of(file.path()); + SliceResult result = file.upgrade(resourceDir.resolve(filePath)); + if (result.isEmpty()) { + return; + } + + FlattenSliceResult printedResult = file.print(result); + if (printedResult.added() != null) { + LOGGER.info("Added the following elements in {}:", filePath); + LOGGER.info(printedResult.added()); + } + + if (printedResult.removed() != null) { + LOGGER.warn("Removed the following keys in {}:", filePath); + LOGGER.warn(printedResult.removed()); + } + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/rewriter/utils/ScanOldGeneratedSourceCode.java b/paper-generator/src/main/java/io/papermc/generator/tasks/ScanOldGeneratedSourceCode.java similarity index 88% rename from paper-generator/src/main/java/io/papermc/generator/rewriter/utils/ScanOldGeneratedSourceCode.java rename to paper-generator/src/main/java/io/papermc/generator/tasks/ScanOldGeneratedSourceCode.java index 22cb899dad..79c2283c9d 100644 --- a/paper-generator/src/main/java/io/papermc/generator/rewriter/utils/ScanOldGeneratedSourceCode.java +++ b/paper-generator/src/main/java/io/papermc/generator/tasks/ScanOldGeneratedSourceCode.java @@ -1,9 +1,10 @@ -package io.papermc.generator.rewriter.utils; +package io.papermc.generator.tasks; import io.papermc.generator.Main; import io.papermc.generator.Rewriters; import io.papermc.generator.rewriter.registration.PaperPatternSourceSetRewriter; -import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.generator.rewriter.types.Types; +import io.papermc.generator.rewriter.utils.Annotations; import io.papermc.typewriter.SourceFile; import io.papermc.typewriter.SourceRewriter; import io.papermc.typewriter.context.FileMetadata; @@ -35,12 +36,14 @@ public class ScanOldGeneratedSourceCode { public static void main(String[] args) throws IOException { PaperPatternSourceSetRewriter apiSourceSet = new PaperPatternSourceSetRewriter(); - PaperPatternSourceSetRewriter serverSourceSet = new PaperPatternSourceSetRewriter(); + PaperPatternSourceSetRewriter implSourceSet = new PaperPatternSourceSetRewriter(); + PaperPatternSourceSetRewriter implTestSourceSet = new PaperPatternSourceSetRewriter(); - Rewriters.bootstrap(apiSourceSet, serverSourceSet); + Rewriters.bootstrap(apiSourceSet, implSourceSet, implTestSourceSet); checkOutdated(apiSourceSet, Path.of(args[0], "src/main/java")); - checkOutdated(serverSourceSet, Path.of(args[1], "src/main/java")); + checkOutdated(implSourceSet, Path.of(args[1], "src/main/java")); + checkOutdated(implTestSourceSet, Path.of(args[1], "src/test/java")); } private static void checkOutdated(PaperPatternSourceSetRewriter sourceSetRewriter, Path sourceSet) throws IOException { @@ -86,7 +89,7 @@ public class ScanOldGeneratedSourceCode { continue; } - String generatedComment = "// %s ".formatted(Annotations.annotationStyle(GeneratedFrom.class)); + String generatedComment = "// %s ".formatted(Annotations.annotationStyle(Types.GENERATED_FROM)); if (nextLineIterator.trySkipString(generatedComment) && nextLineIterator.canRead()) { String generatedVersion = nextLineIterator.getRemaining(); if (!CURRENT_VERSION.equals(generatedVersion)) { diff --git a/paper-generator/src/main/java/io/papermc/generator/types/OverriddenClassGenerator.java b/paper-generator/src/main/java/io/papermc/generator/types/OverriddenClassGenerator.java index 027cbf061e..569afa5056 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/OverriddenClassGenerator.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/OverriddenClassGenerator.java @@ -3,6 +3,7 @@ package io.papermc.generator.types; import com.mojang.logging.LogUtils; import com.squareup.javapoet.MethodSpec; import io.papermc.generator.utils.Annotations; +import io.papermc.typewriter.ClassNamed; import java.util.Arrays; import org.jspecify.annotations.NullMarked; import org.slf4j.Logger; @@ -10,38 +11,44 @@ import org.slf4j.Logger; import static javax.lang.model.element.Modifier.PUBLIC; @NullMarked -public abstract class OverriddenClassGenerator extends SimpleGenerator { +public abstract class OverriddenClassGenerator extends SimpleGenerator { private static final Logger LOGGER = LogUtils.getLogger(); - protected final Class baseClass; + protected final ClassNamed baseClass; protected boolean printWarningOnMissingOverride; - protected OverriddenClassGenerator(Class baseClass, String className, String packageName) { + protected OverriddenClassGenerator(ClassNamed baseClass, String className, String packageName) { super(className, packageName); this.baseClass = baseClass; } - public Class getBaseClass() { + public ClassNamed getBaseClass() { return this.baseClass; } public MethodSpec.Builder createMethod(String name, Class... parameterTypes) { MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(name) .addModifiers(PUBLIC); - if (methodExists(name, parameterTypes)) { + if (this.baseClass.knownClass() == null || methodExists(name, parameterTypes)) { methodBuilder.addAnnotation(Annotations.OVERRIDE); } else { if (this.printWarningOnMissingOverride) { - LOGGER.warn("Method {}#{}{} didn't override a known api method!", this.className, name, Arrays.toString(parameterTypes)); + LOGGER.warn("Method {}#{}{} didn't override a known api method!", this.className, name, LogUtils.defer(() -> Arrays.toString(parameterTypes))); } } return methodBuilder; } + public MethodSpec.Builder createUnsafeMethod(String name) { + return MethodSpec.methodBuilder(name) + .addModifiers(PUBLIC) + .addAnnotation(Annotations.OVERRIDE); + } + protected boolean methodExists(String name, Class... parameterTypes) { try { - this.baseClass.getMethod(name, parameterTypes); + this.baseClass.knownClass().getMethod(name, parameterTypes); return true; } catch (NoSuchMethodException e) { return false; diff --git a/paper-generator/src/main/java/io/papermc/generator/types/SimpleEnumGenerator.java b/paper-generator/src/main/java/io/papermc/generator/types/SimpleEnumGenerator.java index 282a30568a..20802bbd79 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/SimpleEnumGenerator.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/SimpleEnumGenerator.java @@ -6,11 +6,11 @@ import javax.lang.model.element.Modifier; import org.jspecify.annotations.NullMarked; @NullMarked -public class SimpleEnumGenerator> extends SimpleGenerator { +public class SimpleEnumGenerator> extends SimpleGenerator { - private final Class enumClass; + private final Class enumClass; - public SimpleEnumGenerator(Class enumClass, String packageName) { + public SimpleEnumGenerator(Class enumClass, String packageName) { super(enumClass.getSimpleName(), packageName); this.enumClass = enumClass; } @@ -21,7 +21,7 @@ public class SimpleEnumGenerator> extends SimpleGenerator { .addModifiers(Modifier.PUBLIC) .addAnnotations(Annotations.CLASS_HEADER); - for (T enumValue : this.enumClass.getEnumConstants()) { + for (E enumValue : this.enumClass.getEnumConstants()) { typeBuilder.addEnumConstant(enumValue.name()); } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/Types.java b/paper-generator/src/main/java/io/papermc/generator/types/Types.java index 84b52e7940..1e509af6eb 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/Types.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/Types.java @@ -1,14 +1,64 @@ package io.papermc.generator.types; import com.squareup.javapoet.ClassName; +import io.papermc.typewriter.ClassNamed; +import java.util.Arrays; import org.jspecify.annotations.NullMarked; +import static io.papermc.generator.utils.BasePackage.BUKKIT; +import static io.papermc.generator.utils.BasePackage.CRAFT_BUKKIT; +import static io.papermc.generator.utils.BasePackage.PAPER; +import static io.papermc.generator.utils.BasePackage.PAPER_LEGACY; + @NullMarked public final class Types { - public static final String BASE_PACKAGE = "org.bukkit.craftbukkit"; + public static final ClassName NAMESPACED_KEY = BUKKIT.rootClass("NamespacedKey"); - public static final ClassName CRAFT_BLOCK_DATA = ClassName.get(BASE_PACKAGE + ".block.data", "CraftBlockData"); + public static final ClassName MINECRAFT_EXPERIMENTAL = BUKKIT.rootClass("MinecraftExperimental"); - public static final ClassName CRAFT_BLOCK = ClassName.get(BASE_PACKAGE + ".block", "CraftBlock"); + public static final ClassName MINECRAFT_EXPERIMENTAL_REQUIRES = BUKKIT.rootClass("MinecraftExperimental", "Requires"); + + public static final ClassName VECTOR = BUKKIT.relativeClass("util", "Vector"); + + public static final ClassName AXIS = BUKKIT.rootClass("Axis"); + + public static final ClassName BLOCK_FACE = BUKKIT.relativeClass("block", "BlockFace"); + + public static final ClassName NOTE = BUKKIT.rootClass("Note"); + + public static final ClassName BLOCK_DATA_RAIL_SHAPE = BUKKIT.relativeClass("block.data", "Rail", "Shape"); + + public static final ClassName KEY = ClassName.get("net.kyori.adventure.key", "Key"); + + public static final ClassName REGISTRY_KEY = PAPER.relativeClass("registry", "RegistryKey"); + + public static final ClassName TYPED_KEY = PAPER.relativeClass("registry", "TypedKey"); + + public static final ClassName GOAL_KEY = PAPER_LEGACY.relativeClass("entity.ai", "GoalKey"); + + public static final ClassName GOAL = PAPER_LEGACY.relativeClass("entity.ai", "Goal"); + + public static final ClassName MOB = BUKKIT.relativeClass("entity", "Mob"); + + public static final ClassName RANGED_ENTITY = PAPER_LEGACY.relativeClass("entity", "RangedEntity"); + + + public static final ClassName CRAFT_BLOCK_DATA = CRAFT_BUKKIT.relativeClass("block.data", "CraftBlockData"); + + public static final ClassName CRAFT_BLOCK = CRAFT_BUKKIT.relativeClass("block", "CraftBlock"); + + public static final ClassName TAG_KEY = PAPER.relativeClass("registry.tag", "TagKey"); + + public static final ClassName GENERATED_FROM = PAPER.relativeClass("generated", "GeneratedFrom"); + + public static ClassName typed(ClassNamed name) { + if (name.knownClass() != null) { + return ClassName.get(name.knownClass()); + } + + String[] names = name.dottedNestedName().split("\\.", -1); + String topName = names[0]; + return ClassName.get(name.packageName(), topName, Arrays.copyOfRange(names, 1, names.length)); + } } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/CraftBlockDataBootstrapper.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/CraftBlockDataBootstrapper.java index fbdd1f3f21..e24441374b 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/CraftBlockDataBootstrapper.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/CraftBlockDataBootstrapper.java @@ -1,23 +1,18 @@ package io.papermc.generator.types.craftblockdata; -import com.google.common.base.Preconditions; import io.papermc.generator.types.SourceGenerator; import io.papermc.generator.utils.BlockStateMapping; import java.util.List; import java.util.Map; import net.minecraft.world.level.block.Block; -import org.bukkit.block.data.BlockData; import org.jspecify.annotations.NullMarked; @NullMarked public final class CraftBlockDataBootstrapper { public static void bootstrap(List generators) { - for (Map.Entry, BlockStateMapping.BlockData> entry : BlockStateMapping.MAPPING.entrySet()) { - Class api = BlockStateMapping.getBestSuitedApiClass(entry.getValue()); - Preconditions.checkState(api != null, "Unknown custom BlockData api class for " + entry.getKey().getCanonicalName()); - - generators.add(new CraftBlockDataGenerator<>(entry.getKey(), entry.getValue(), api)); + for (Map.Entry, BlockStateMapping.BlockData> entry : BlockStateMapping.getOrCreate().entrySet()) { + generators.add(new CraftBlockDataGenerator(entry.getKey(), entry.getValue())); } } } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/CraftBlockDataGenerator.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/CraftBlockDataGenerator.java index 9097b0c2d7..374fc671ae 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/CraftBlockDataGenerator.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/CraftBlockDataGenerator.java @@ -7,7 +7,10 @@ import com.mojang.datafixers.util.Either; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; import io.papermc.generator.types.OverriddenClassGenerator; import io.papermc.generator.types.Types; import io.papermc.generator.types.craftblockdata.property.PropertyMaker; @@ -19,12 +22,14 @@ import io.papermc.generator.types.craftblockdata.property.holder.VirtualField; import io.papermc.generator.types.craftblockdata.property.holder.converter.DataConverter; import io.papermc.generator.types.craftblockdata.property.holder.converter.DataConverters; import io.papermc.generator.utils.Annotations; +import io.papermc.generator.utils.BasePackage; import io.papermc.generator.utils.BlockStateMapping; import io.papermc.generator.utils.CommonVariable; import io.papermc.generator.utils.NamingManager; import it.unimi.dsi.fastutil.Pair; import java.lang.reflect.Field; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import net.minecraft.world.level.block.Block; @@ -32,10 +37,6 @@ import net.minecraft.world.level.block.ChiseledBookShelfBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.Property; -import org.bukkit.Axis; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Rail; import org.jspecify.annotations.NullMarked; import static io.papermc.generator.utils.NamingManager.keywordGet; @@ -46,18 +47,22 @@ import static javax.lang.model.element.Modifier.PUBLIC; import static javax.lang.model.element.Modifier.STATIC; @NullMarked -public class CraftBlockDataGenerator extends OverriddenClassGenerator { +public class CraftBlockDataGenerator extends OverriddenClassGenerator { private final Class blockClass; private final BlockStateMapping.BlockData blockData; - protected CraftBlockDataGenerator(Class blockClass, BlockStateMapping.BlockData blockData, Class baseClass) { - super(baseClass, blockData.implName(), Types.BASE_PACKAGE + ".block.impl"); + protected CraftBlockDataGenerator(Class blockClass, BlockStateMapping.BlockData blockData) { + super(blockData.api(), blockData.implName(), BasePackage.CRAFT_BUKKIT.name().concat(".block.impl")); this.blockClass = blockClass; this.blockData = blockData; this.printWarningOnMissingOverride = true; } + public Class getBlock() { + return this.blockClass; + } + // default keywords: get/set // for single boolean property: get = is // for indexed boolean property: get = has @@ -77,19 +82,19 @@ public class CraftBlockDataGenerator extends OverriddenClas method.addStatement("$1T.checkArgument($2N.isCartesian() && $2N.getModY() == 0, $3S)", Preconditions.class, param, "Invalid face, only cartesian horizontal face are allowed for this property!"); }, BlockStateProperties.FACING_HOPPER, (param, method) -> { - method.addStatement("$1T.checkArgument($2N.isCartesian() && $2N != $3T.UP, $4S)", Preconditions.class, param, BlockFace.class, "Invalid face, only cartesian face (excluding UP) are allowed for this property!"); + method.addStatement("$1T.checkArgument($2N.isCartesian() && $2N != $3T.UP, $4S)", Preconditions.class, param, Types.BLOCK_FACE, "Invalid face, only cartesian face (excluding UP) are allowed for this property!"); }, BlockStateProperties.VERTICAL_DIRECTION, (param, method) -> { method.addStatement("$T.checkArgument($N.getModY() != 0, $S)", Preconditions.class, param, "Invalid face, only vertical face are allowed for this property!"); }, BlockStateProperties.ROTATION_16, (param, method) -> { - method.addStatement("$1T.checkArgument($2N != $3T.SELF && $2N.getModY() == 0, $4S)", Preconditions.class, param, BlockFace.class, "Invalid face, only horizontal face are allowed for this property!"); + method.addStatement("$1T.checkArgument($2N != $3T.SELF && $2N.getModY() == 0, $4S)", Preconditions.class, param, Types.BLOCK_FACE, "Invalid face, only horizontal face are allowed for this property!"); }, BlockStateProperties.HORIZONTAL_AXIS, (param, method) -> { - method.addStatement("$1T.checkArgument($2N == $3T.X || $2N == $3T.Z, $4S)", Preconditions.class, param, Axis.class, "Invalid axis, only horizontal axis are allowed for this property!"); + method.addStatement("$1T.checkArgument($2N == $3T.X || $2N == $3T.Z, $4S)", Preconditions.class, param, Types.AXIS, "Invalid axis, only horizontal axis are allowed for this property!"); }, BlockStateProperties.RAIL_SHAPE_STRAIGHT, (param, method) -> { - method.addStatement("$1T.checkArgument($2N != $3T.NORTH_EAST && $2N != $3T.NORTH_WEST && $2N != $3T.SOUTH_EAST && $2N != $3T.SOUTH_WEST, $4S)", Preconditions.class, param, Rail.Shape.class, "Invalid rail shape, only straight rail are allowed for this property!"); + method.addStatement("$1T.checkArgument($2N != $3T.NORTH_EAST && $2N != $3T.NORTH_WEST && $2N != $3T.SOUTH_EAST && $2N != $3T.SOUTH_WEST, $4S)", Preconditions.class, param, Types.BLOCK_DATA_RAIL_SHAPE, "Invalid rail shape, only straight rail are allowed for this property!"); } ); @@ -98,7 +103,15 @@ public class CraftBlockDataGenerator extends OverriddenClas .addModifiers(PUBLIC) .addAnnotation(Annotations.GENERATED_FROM) .superclass(Types.CRAFT_BLOCK_DATA) - .addSuperinterface(this.baseClass); + .addSuperinterface(Types.typed(this.baseClass)); + + // since javapoet lack of context (doesn't know the api anymore), type clash with the super interface + Map> ambiguousNames = DataFileLoader.get(DataFiles.BLOCK_STATE_AMBIGUOUS_NAMES); + for (Map.Entry> entry : ambiguousNames.entrySet()) { + if (entry.getValue().contains(this.blockData.implName())) { + typeBuilder.alwaysQualify(entry.getKey()); + } + } ParameterSpec parameter = ParameterSpec.builder(BlockState.class, "state").build(); MethodSpec constructor = MethodSpec.constructorBuilder() @@ -135,10 +148,10 @@ public class CraftBlockDataGenerator extends OverriddenClas typeBuilder.addField(field); ConverterBase converter = Converters.getOrDefault(property, propertyMaker); - Class apiClass = converter.getApiType(); + TypeName apiType = converter.getApiType(); NamingManager.AccessKeyword accessKeyword = null; - if (apiClass == Boolean.TYPE) { + if (apiType.equals(TypeName.BOOLEAN)) { accessKeyword = keywordGet("is"); } accessKeyword = FLUENT_KEYWORD.getOrDefault(property, accessKeyword); @@ -148,18 +161,18 @@ public class CraftBlockDataGenerator extends OverriddenClas { MethodSpec.Builder methodBuilder = createMethod(propertyNaming.simpleGetterName(name -> !name.startsWith("is_") && !name.startsWith("has_"))); converter.convertGetter(methodBuilder, field); - methodBuilder.returns(apiClass); + methodBuilder.returns(apiType); typeBuilder.addMethod(methodBuilder.build()); } // set { - String paramName = propertyNaming.paramName(apiClass); - ParameterSpec parameter = ParameterSpec.builder(apiClass, paramName, FINAL).build(); + String paramName = propertyNaming.paramName(apiType); + ParameterSpec parameter = ParameterSpec.builder(apiType, paramName, FINAL).build(); - MethodSpec.Builder methodBuilder = createMethod(propertyNaming.simpleSetterName(name -> !name.startsWith("is_")), apiClass).addParameter(parameter); - if (!apiClass.isPrimitive()) { + MethodSpec.Builder methodBuilder = createUnsafeMethod(propertyNaming.simpleSetterName(name -> !name.startsWith("is_"))).addParameter(parameter); + if (!apiType.isPrimitive()) { methodBuilder.addStatement("$T.checkArgument($N != null, $S)", Preconditions.class, parameter, "%s cannot be null!".formatted(paramName)); } if (SETTER_PRECONDITIONS.containsKey(property)) { @@ -188,20 +201,20 @@ public class CraftBlockDataGenerator extends OverriddenClas typeBuilder.addField(field); DataConverter converter = DataConverters.getOrThrow(dataPropertyMaker.getType()); - Class apiClass = propertyConverter.getApiType(); + TypeName apiClass = propertyConverter.getApiType(); NamingManager.AccessKeyword accessKeyword = null; - if (apiClass == Boolean.TYPE) { + if (apiClass.equals(TypeName.BOOLEAN)) { accessKeyword = NamingManager.keywordGet("has"); } accessKeyword = FLUENT_KEYWORD.getOrDefault(firstProperty, accessKeyword); NamingManager baseNaming = new NamingManager(accessKeyword, CaseFormat.UPPER_UNDERSCORE, dataPropertyMaker.getBaseName()); - ParameterSpec indexParameter = ParameterSpec.builder(dataPropertyMaker.getIndexClass(), dataPropertyMaker.getIndexClass() == Integer.TYPE ? CommonVariable.INDEX : baseNaming.paramName(dataPropertyMaker.getIndexClass()), FINAL).build(); + ParameterSpec indexParameter = ParameterSpec.builder(dataPropertyMaker.getIndexClass(), dataPropertyMaker.getIndexClass().equals(TypeName.INT) ? CommonVariable.INDEX : baseNaming.paramName(dataPropertyMaker.getIndexClass()), FINAL).build(); // get { - MethodSpec.Builder methodBuilder = createMethod(baseNaming.simpleGetterName(name -> true), dataPropertyMaker.getIndexClass()) + MethodSpec.Builder methodBuilder = createUnsafeMethod(baseNaming.simpleGetterName(name -> true)) .addParameter(indexParameter); if (!dataPropertyMaker.getIndexClass().isPrimitive()) { methodBuilder.addStatement("$T.checkArgument($N != null, $S)", Preconditions.class, indexParameter, "%s cannot be null!".formatted(indexParameter.name)); @@ -217,7 +230,7 @@ public class CraftBlockDataGenerator extends OverriddenClas String paramName = baseNaming.paramName(apiClass); ParameterSpec parameter = ParameterSpec.builder(apiClass, paramName, FINAL).build(); - MethodSpec.Builder methodBuilder = createMethod(baseNaming.simpleSetterName(name -> true), dataPropertyMaker.getIndexClass(), apiClass) + MethodSpec.Builder methodBuilder = createUnsafeMethod(baseNaming.simpleSetterName(name -> true)) .addParameter(indexParameter) .addParameter(parameter); if (!dataPropertyMaker.getIndexClass().isPrimitive()) { diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/EnumPropertyWriter.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/EnumPropertyWriter.java index 9c38001d09..68d1af7a71 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/EnumPropertyWriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/EnumPropertyWriter.java @@ -4,7 +4,8 @@ import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; -import io.papermc.generator.utils.BlockStateMapping; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; import net.minecraft.util.StringRepresentable; import net.minecraft.world.level.block.state.properties.EnumProperty; import org.jspecify.annotations.NullMarked; @@ -25,13 +26,9 @@ public class EnumPropertyWriter & StringRepresentable> extends } @Override - protected Class processApiType() { - Class apiClass = this.property.getValueClass(); - apiClass = BlockStateMapping.ENUM_BRIDGE.get(apiClass); - if (apiClass == null) { - throw new IllegalStateException("Unknown enum type for " + this.property); - } - return apiClass; + protected TypeName processApiType() { + Class rawClass = this.property.getValueClass(); + return DataFileLoader.get(DataFiles.BLOCK_STATE_ENUM_PROPERTY_TYPES).get(rawClass); } @Override diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/IntegerPropertyWriter.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/IntegerPropertyWriter.java index 5d5fb8c8be..0b54ce8b15 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/IntegerPropertyWriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/IntegerPropertyWriter.java @@ -18,14 +18,14 @@ public class IntegerPropertyWriter extends PropertyWriter { } @Override - public void addExtras(TypeSpec.Builder builder, FieldSpec field, CraftBlockDataGenerator generator, NamingManager naming) { + public void addExtras(TypeSpec.Builder builder, FieldSpec field, CraftBlockDataGenerator generator, NamingManager naming) { if (Converters.has(this.property)) { return; } IntegerProperty property = (IntegerProperty) this.property; - if (property.min != 0 || property.getName().equals(BlockStateProperties.LEVEL.getName())) { // special case (levelled: composter) + if (property.getPossibleValues().getFirst() != 0 || property.getName().equals(BlockStateProperties.LEVEL.getName())) { // special case (levelled: composter) MethodSpec.Builder methodBuilder = generator.createMethod(naming.getterName(name -> true).pre("Minimum").concat()); methodBuilder.addStatement("return $N.min", field); methodBuilder.returns(this.getApiType()); diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/PropertyWriter.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/PropertyWriter.java index 60c93f27a9..05789d93c3 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/PropertyWriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/PropertyWriter.java @@ -23,7 +23,7 @@ import org.jspecify.annotations.NullMarked; public class PropertyWriter> implements PropertyMaker { protected final Property property; - private final Supplier> apiClassSupplier; + private final Supplier apiClassSupplier; protected PropertyWriter(Property property) { this.property = property; @@ -35,16 +35,16 @@ public class PropertyWriter> implements PropertyMaker { return TypeName.get(this.property.getClass()); } - protected Class processApiType() { + protected TypeName processApiType() { Class apiClass = this.property.getValueClass(); if (Primitives.isWrapperType(apiClass)) { apiClass = Primitives.unwrap(apiClass); } - return apiClass; + return TypeName.get(apiClass); } @Override - public Class getApiType() { + public TypeName getApiType() { return this.apiClassSupplier.get(); } @@ -59,24 +59,27 @@ public class PropertyWriter> implements PropertyMaker { } @Override - public void addExtras(TypeSpec.Builder builder, FieldSpec field, CraftBlockDataGenerator generator, NamingManager naming) { + public void addExtras(TypeSpec.Builder builder, FieldSpec field, CraftBlockDataGenerator generator, NamingManager naming) { PropertyAppenders.ifPresent(this.property, appender -> appender.addExtras(builder, field, generator, naming)); } public static Pair, String> referenceField(Class from, Property property, Map, Field> fields) { Class fieldAccess = from; Field field = fields.get(property); + String fieldName; if (field == null || !Modifier.isPublic(field.getModifiers())) { fieldAccess = BlockStateProperties.class; - field = BlockStateMapping.FALLBACK_GENERIC_FIELDS.get(property); + fieldName = BlockStateMapping.GENERIC_FIELD_NAMES.get(property); + } else { + fieldName = field.getName(); } - return Pair.of(fieldAccess, field.getName()); + return Pair.of(fieldAccess, fieldName); } public static Pair, String> referenceFieldFromVar(Class from, Property property, Map, Field> fields) { Class fieldAccess = from; Field field = fields.get(property); - Field genericField = BlockStateMapping.FALLBACK_GENERIC_FIELDS.get(property); + Field genericField = BlockStateMapping.GENERIC_FIELDS.get(property); if (field == null || !Modifier.isPublic(field.getModifiers()) || !genericField.getType().equals(field.getType())) { // field type can differ from BlockStateProperties constants (that's the case for the shulker box (#FACING) and the vault (#STATE)) ref: 1.20.5 // in that case fallback to the more accurate type to avoid compile error diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/AppenderBase.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/AppenderBase.java index b1e149e75b..970a727754 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/AppenderBase.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/AppenderBase.java @@ -9,5 +9,5 @@ import org.jspecify.annotations.NullMarked; @NullMarked public interface AppenderBase { - void addExtras(TypeSpec.Builder builder, FieldSpec field, CraftBlockDataGenerator generator, NamingManager naming); + void addExtras(TypeSpec.Builder builder, FieldSpec field, CraftBlockDataGenerator generator, NamingManager naming); } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/EnumValuesAppender.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/EnumValuesAppender.java index 0898c37475..145b516597 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/EnumValuesAppender.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/EnumValuesAppender.java @@ -1,8 +1,10 @@ package io.papermc.generator.types.craftblockdata.property.appender; +import com.squareup.javapoet.ClassName; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import io.papermc.generator.types.craftblockdata.CraftBlockDataGenerator; import io.papermc.generator.utils.NamingManager; @@ -12,13 +14,13 @@ import net.minecraft.world.level.block.state.properties.EnumProperty; import org.jspecify.annotations.NullMarked; @NullMarked -public class EnumValuesAppender & StringRepresentable, A extends Enum> implements PropertyAppender { +public class EnumValuesAppender & StringRepresentable> implements PropertyAppender { private final EnumProperty property; - private final Class apiType; + private final TypeName apiType; private final String methodName; - public EnumValuesAppender(EnumProperty property, Class apiType, String methodName) { + public EnumValuesAppender(EnumProperty property, TypeName apiType, String methodName) { this.property = property; this.apiType = apiType; this.methodName = methodName; @@ -30,15 +32,15 @@ public class EnumValuesAppender & StringRepresentable, A exten } @Override - public Class getApiType() { + public TypeName getApiType() { return this.apiType; } @Override - public void addExtras(TypeSpec.Builder builder, FieldSpec field, CraftBlockDataGenerator generator, NamingManager naming) { + public void addExtras(TypeSpec.Builder builder, FieldSpec field, CraftBlockDataGenerator generator, NamingManager naming) { MethodSpec.Builder methodBuilder = generator.createMethod(this.methodName); methodBuilder.addStatement("return this.getValues($N, $T.class)", field, this.apiType); - methodBuilder.returns(ParameterizedTypeName.get(Set.class, this.apiType)); + methodBuilder.returns(ParameterizedTypeName.get(ClassName.get(Set.class), this.apiType)); builder.addMethod(methodBuilder.build()); } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/PropertyAppender.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/PropertyAppender.java index 63bc0dbd28..0165257fbf 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/PropertyAppender.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/PropertyAppender.java @@ -1,12 +1,13 @@ package io.papermc.generator.types.craftblockdata.property.appender; +import com.squareup.javapoet.TypeName; import net.minecraft.world.level.block.state.properties.Property; import org.jspecify.annotations.NullMarked; @NullMarked -public interface PropertyAppender, A> extends AppenderBase { +public interface PropertyAppender> extends AppenderBase { Property getProperty(); - Class getApiType(); + TypeName getApiType(); } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/PropertyAppenders.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/PropertyAppenders.java index 9ddfe158c6..0e36879a6c 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/PropertyAppenders.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/appender/PropertyAppenders.java @@ -1,28 +1,26 @@ package io.papermc.generator.types.craftblockdata.property.appender; +import io.papermc.generator.types.Types; import java.util.Map; import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.Property; -import org.bukkit.Axis; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Rail; import org.jspecify.annotations.NullMarked; @NullMarked public final class PropertyAppenders { private static final Map, AppenderBase> APPENDERS = Stream.of( - new EnumValuesAppender<>(BlockStateProperties.AXIS, Axis.class, "getAxes"), - new EnumValuesAppender<>(BlockStateProperties.HORIZONTAL_AXIS, Axis.class, "getAxes"), - new EnumValuesAppender<>(BlockStateProperties.FACING, BlockFace.class, "getFaces"), - new EnumValuesAppender<>(BlockStateProperties.HORIZONTAL_FACING, BlockFace.class, "getFaces"), - new EnumValuesAppender<>(BlockStateProperties.FACING_HOPPER, BlockFace.class, "getFaces"), - new EnumValuesAppender<>(BlockStateProperties.RAIL_SHAPE, Rail.Shape.class, "getShapes"), - new EnumValuesAppender<>(BlockStateProperties.RAIL_SHAPE_STRAIGHT, Rail.Shape.class, "getShapes"), - new EnumValuesAppender<>(BlockStateProperties.VERTICAL_DIRECTION, BlockFace.class, "getVerticalDirections") + new EnumValuesAppender<>(BlockStateProperties.AXIS, Types.AXIS, "getAxes"), + new EnumValuesAppender<>(BlockStateProperties.HORIZONTAL_AXIS, Types.AXIS, "getAxes"), + new EnumValuesAppender<>(BlockStateProperties.FACING, Types.BLOCK_FACE, "getFaces"), + new EnumValuesAppender<>(BlockStateProperties.HORIZONTAL_FACING, Types.BLOCK_FACE, "getFaces"), + new EnumValuesAppender<>(BlockStateProperties.FACING_HOPPER, Types.BLOCK_FACE, "getFaces"), + new EnumValuesAppender<>(BlockStateProperties.RAIL_SHAPE, Types.BLOCK_DATA_RAIL_SHAPE, "getShapes"), + new EnumValuesAppender<>(BlockStateProperties.RAIL_SHAPE_STRAIGHT, Types.BLOCK_DATA_RAIL_SHAPE, "getShapes"), + new EnumValuesAppender<>(BlockStateProperties.VERTICAL_DIRECTION, Types.BLOCK_FACE, "getVerticalDirections") ).collect(Collectors.toUnmodifiableMap(PropertyAppender::getProperty, key -> key)); public static void ifPresent(Property property, Consumer callback) { diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/Converter.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/Converter.java index f4c3205c84..0e6bacae1d 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/Converter.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/Converter.java @@ -1,13 +1,14 @@ package io.papermc.generator.types.craftblockdata.property.converter; +import com.squareup.javapoet.TypeName; import net.minecraft.world.level.block.state.properties.Property; import org.jspecify.annotations.NullMarked; @NullMarked -public interface Converter, A> extends ConverterBase { +public interface Converter> extends ConverterBase { Property getProperty(); @Override - Class getApiType(); + TypeName getApiType(); } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/ConverterBase.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/ConverterBase.java index cbe2e0f59a..c189456427 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/ConverterBase.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/ConverterBase.java @@ -3,12 +3,13 @@ package io.papermc.generator.types.craftblockdata.property.converter; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.TypeName; import org.jspecify.annotations.NullMarked; @NullMarked public interface ConverterBase { - Class getApiType(); + TypeName getApiType(); default void convertSetter(MethodSpec.Builder method, FieldSpec field, ParameterSpec parameter) { method.addStatement(this.rawSetExprent().formatted("$N"), field, parameter); diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/NoteConverter.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/NoteConverter.java index 91189dd6a5..3e75134d8b 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/NoteConverter.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/NoteConverter.java @@ -2,13 +2,14 @@ package io.papermc.generator.types.craftblockdata.property.converter; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeName; +import io.papermc.generator.types.Types; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.Property; -import org.bukkit.Note; import org.jspecify.annotations.NullMarked; @NullMarked -public class NoteConverter implements Converter { +public class NoteConverter implements Converter { @Override public Property getProperty() { @@ -16,8 +17,8 @@ public class NoteConverter implements Converter { } @Override - public Class getApiType() { - return Note.class; + public TypeName getApiType() { + return Types.NOTE; } @Override diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/RotationConverter.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/RotationConverter.java index 7726efd33c..f07be2cf0c 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/RotationConverter.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/converter/RotationConverter.java @@ -3,15 +3,15 @@ package io.papermc.generator.types.craftblockdata.property.converter; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.TypeName; +import io.papermc.generator.types.Types; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.block.state.properties.RotationSegment; -import org.bukkit.block.BlockFace; -import org.bukkit.util.Vector; import org.jspecify.annotations.NullMarked; @NullMarked -public class RotationConverter implements Converter { +public class RotationConverter implements Converter { private static final String DIRECTION_VAR = "dir"; private static final String ANGLE_VAR = "angle"; @@ -22,13 +22,13 @@ public class RotationConverter implements Converter { } @Override - public Class getApiType() { - return BlockFace.class; + public TypeName getApiType() { + return Types.BLOCK_FACE; } @Override public void convertSetter(MethodSpec.Builder method, FieldSpec field, ParameterSpec parameter) { - method.addStatement("$T $L = $N.getDirection()", Vector.class, DIRECTION_VAR, parameter); + method.addStatement("$T $L = $N.getDirection()", Types.VECTOR, DIRECTION_VAR, parameter); method.addStatement("$1T $2L = ($1T) -$3T.toDegrees($3T.atan2($4L.getX(), $4L.getZ()))", Float.TYPE, ANGLE_VAR, Math.class, DIRECTION_VAR); method.addStatement(this.rawSetExprent().formatted("$N", ANGLE_VAR), field, RotationSegment.class); } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyMaker.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyMaker.java index 117b2cd8a2..13f01deb40 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyMaker.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyMaker.java @@ -2,6 +2,7 @@ package io.papermc.generator.types.craftblockdata.property.holder; import com.mojang.datafixers.util.Either; import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.TypeName; import io.papermc.generator.types.craftblockdata.property.holder.appender.DataAppender; import java.lang.reflect.Field; import java.util.Collection; @@ -15,7 +16,7 @@ public interface DataPropertyMaker extends DataAppender { FieldSpec.Builder getOrCreateField(Map, Field> fields); - Class getIndexClass(); + TypeName getIndexClass(); @Override DataHolderType getType(); diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyWriter.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyWriter.java index 6b94183df3..8330e9f885 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyWriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyWriter.java @@ -7,11 +7,12 @@ import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; import io.papermc.generator.types.Types; import io.papermc.generator.types.craftblockdata.CraftBlockDataGenerator; import io.papermc.generator.types.craftblockdata.property.converter.ConverterBase; import io.papermc.generator.types.craftblockdata.property.holder.appender.DataAppenders; -import io.papermc.generator.utils.BlockStateMapping; import io.papermc.generator.utils.ClassHelper; import io.papermc.generator.utils.CommonVariable; import io.papermc.generator.utils.NamingManager; @@ -28,7 +29,6 @@ import net.minecraft.world.level.block.ChiseledBookShelfBlock; import net.minecraft.world.level.block.MossyCarpetBlock; import net.minecraft.world.level.block.WallBlock; import net.minecraft.world.level.block.state.properties.Property; -import org.bukkit.block.BlockFace; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.jspecify.annotations.NullMarked; @@ -58,7 +58,8 @@ public class DataPropertyWriter extends DataPropertyWriterBase { protected final Field field; protected @MonotonicNonNull DataHolderType type; - protected @MonotonicNonNull Class indexClass, internalIndexClass; + protected @MonotonicNonNull TypeName indexClass; + protected @MonotonicNonNull Class internalIndexClass; protected @MonotonicNonNull TypeName fieldType; protected DataPropertyWriter(Field field, Collection> properties, Class blockClass) { @@ -72,22 +73,26 @@ public class DataPropertyWriter extends DataPropertyWriterBase { if (field.getType().isArray()) { this.type = DataHolderType.ARRAY; - this.indexClass = Integer.TYPE; + this.indexClass = TypeName.INT; } else if (List.class.isAssignableFrom(field.getType())) { this.type = DataHolderType.LIST; - this.indexClass = Integer.TYPE; + this.indexClass = TypeName.INT; } else if (Map.class.isAssignableFrom(field.getType()) && field.getGenericType() instanceof ParameterizedType complexType) { this.type = DataHolderType.MAP; this.internalIndexClass = ClassHelper.eraseType(complexType.getActualTypeArguments()[0]); if (this.internalIndexClass.isEnum()) { - this.indexClass = BlockStateMapping.ENUM_BRIDGE.getOrDefault(this.internalIndexClass, (Class>) this.internalIndexClass); + TypeName indexClass = DataFileLoader.get(DataFiles.BLOCK_STATE_ENUM_PROPERTY_TYPES).get(this.internalIndexClass); + if (indexClass == null) { + indexClass = TypeName.get(this.internalIndexClass); + } + this.indexClass = indexClass; this.fieldType = ParameterizedTypeName.get( ClassName.get(field.getType()), - ClassName.get(this.indexClass), - ClassName.get(complexType.getActualTypeArguments()[1]) + this.indexClass, + TypeName.get(complexType.getActualTypeArguments()[1]) ); } else { - this.indexClass = this.internalIndexClass; + this.indexClass = TypeName.get(this.internalIndexClass); } } else { throw new IllegalStateException("Don't know how to turn " + field + " into api"); @@ -100,7 +105,7 @@ public class DataPropertyWriter extends DataPropertyWriterBase { if (Modifier.isPublic(this.field.getModifiers())) { // accessible phew if (this.type == DataHolderType.MAP && - this.internalIndexClass == Direction.class && this.indexClass == BlockFace.class) { // Direction -> BlockFace + this.internalIndexClass == Direction.class && this.indexClass.equals(Types.BLOCK_FACE)) { // Direction -> BlockFace // convert the key manually only this one is needed for now fieldBuilder.initializer("$[$1T.$2L.entrySet().stream()\n.collect($3T.toMap($4L -> $5T.notchToBlockFace($4L.getKey()), $4L -> $4L.getValue()))$]", this.blockClass, this.field.getName(), Collectors.class, CommonVariable.MAP_ENTRY, Types.CRAFT_BLOCK); @@ -122,7 +127,7 @@ public class DataPropertyWriter extends DataPropertyWriterBase { } @Override - public Class getIndexClass() { + public TypeName getIndexClass() { return this.indexClass; } @@ -158,7 +163,7 @@ public class DataPropertyWriter extends DataPropertyWriterBase { } @Override - public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator generator, NamingManager baseNaming) { + public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator generator, NamingManager baseNaming) { DataAppenders.ifPresent(this.type, appender -> appender.addExtras(builder, field, indexParameter, childConverter, generator, baseNaming)); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyWriterBase.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyWriterBase.java index 593e6bce3b..b5645879cf 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyWriterBase.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/DataPropertyWriterBase.java @@ -1,6 +1,7 @@ package io.papermc.generator.types.craftblockdata.property.holder; import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.TypeName; import io.papermc.generator.types.craftblockdata.property.PropertyWriter; import io.papermc.generator.utils.Formatting; import it.unimi.dsi.fastutil.Pair; @@ -46,7 +47,7 @@ public abstract class DataPropertyWriterBase implements DataPropertyMaker { code.unindent().add(isArray ? "}" : ")"); } - protected void createSyntheticMap(CodeBlock.Builder code, Class indexClass, Map, Field> fields) { + protected void createSyntheticMap(CodeBlock.Builder code, TypeName indexClass, Map, Field> fields) { // assume indexClass is an enum with its values matching the property names code.add("$T.of(\n", Map.class).indent(); Iterator> properties = this.properties.iterator(); @@ -64,5 +65,5 @@ public abstract class DataPropertyWriterBase implements DataPropertyMaker { } @Override - public abstract Class getIndexClass(); + public abstract TypeName getIndexClass(); } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/VirtualDataPropertyWriter.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/VirtualDataPropertyWriter.java index d68d36920b..8accc77d57 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/VirtualDataPropertyWriter.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/VirtualDataPropertyWriter.java @@ -1,15 +1,17 @@ package io.papermc.generator.types.craftblockdata.property.holder; import com.squareup.javapoet.ArrayTypeName; +import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; import io.papermc.generator.types.craftblockdata.CraftBlockDataGenerator; import io.papermc.generator.types.craftblockdata.property.converter.ConverterBase; -import io.papermc.generator.utils.BlockStateMapping; import io.papermc.generator.utils.NamingManager; import java.lang.reflect.Field; import java.util.Collection; @@ -28,7 +30,7 @@ import static javax.lang.model.element.Modifier.STATIC; public class VirtualDataPropertyWriter extends DataPropertyWriterBase { private final VirtualField virtualField; - protected @MonotonicNonNull Class indexClass; + protected @MonotonicNonNull TypeName indexClass; protected @MonotonicNonNull TypeName fieldType; protected VirtualDataPropertyWriter(VirtualField virtualField, Collection> properties, Class blockClass) { @@ -40,23 +42,25 @@ public class VirtualDataPropertyWriter extends DataPropertyWriterBase { protected void computeTypes(VirtualField virtualField) { switch (virtualField.holderType()) { case ARRAY -> { - this.indexClass = Integer.TYPE; + this.indexClass = TypeName.INT; this.fieldType = ArrayTypeName.of(virtualField.valueType()); } case LIST -> { - this.indexClass = Integer.TYPE; + this.indexClass = TypeName.INT; this.fieldType = ParameterizedTypeName.get(List.class, virtualField.valueType()); } case MAP -> { if (virtualField.keyClass() != null) { - this.indexClass = virtualField.keyClass(); + this.indexClass = TypeName.get(virtualField.keyClass()); } else { - this.indexClass = this.properties.iterator().next().getValueClass(); - if (this.indexClass.isEnum()) { - this.indexClass = BlockStateMapping.ENUM_BRIDGE.getOrDefault(this.indexClass, (Class>) this.indexClass); + Class valueClass = this.properties.iterator().next().getValueClass(); + if (valueClass.isEnum()) { + this.indexClass = DataFileLoader.get(DataFiles.BLOCK_STATE_ENUM_PROPERTY_TYPES).get(valueClass); + } else { + this.indexClass = TypeName.get(valueClass); } } - this.fieldType = ParameterizedTypeName.get(Map.class, this.indexClass, virtualField.valueType()); + this.fieldType = ParameterizedTypeName.get(ClassName.get(Map.class), this.indexClass, TypeName.get(virtualField.valueType())); } } } @@ -78,7 +82,7 @@ public class VirtualDataPropertyWriter extends DataPropertyWriterBase { } @Override - public Class getIndexClass() { + public TypeName getIndexClass() { return this.indexClass; } @@ -93,7 +97,7 @@ public class VirtualDataPropertyWriter extends DataPropertyWriterBase { } @Override - public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase converter, CraftBlockDataGenerator generator, NamingManager baseNaming) { + public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase converter, CraftBlockDataGenerator generator, NamingManager baseNaming) { } } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/VirtualField.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/VirtualField.java index 26245f80d7..a0a9181db8 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/VirtualField.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/VirtualField.java @@ -48,9 +48,9 @@ public record VirtualField( private final String baseName; private final @Nullable Class keyClass; - private @Nullable Collection values; + private @Nullable Collection properties; - public FieldValue(String name, TypeToken valueTypeToken, DataHolderType holderType, String baseName, @Nullable Class keyClass) { + private FieldValue(String name, TypeToken valueTypeToken, DataHolderType holderType, String baseName, @Nullable Class keyClass) { this.name = name; this.valueTypeToken = valueTypeToken; this.holderType = holderType; @@ -59,14 +59,15 @@ public record VirtualField( } @Contract(value = "_ -> this", mutates = "this") - public FieldValue withValues(Collection properties) { - this.values = List.copyOf(properties); + public FieldValue group(Collection properties) { + this.properties = List.copyOf(properties); return this; } + @Contract(value = "-> new", pure = true) public VirtualField make() { - Preconditions.checkState(this.values != null && !this.values.isEmpty(), "The field should doesn't have any content"); - return new VirtualField(this.name, this.valueTypeToken.getType(), this.holderType, this.baseName, this.keyClass, this.values); + Preconditions.checkState(this.properties != null && !this.properties.isEmpty(), "The field doesn't have any content"); + return new VirtualField(this.name, this.valueTypeToken.getType(), this.holderType, this.baseName, this.keyClass, this.properties); } } } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/ArrayAppender.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/ArrayAppender.java index 578af077fd..f344deb55a 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/ArrayAppender.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/ArrayAppender.java @@ -5,6 +5,7 @@ import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import io.papermc.generator.types.craftblockdata.CraftBlockDataGenerator; import io.papermc.generator.types.craftblockdata.property.converter.ConverterBase; @@ -23,8 +24,8 @@ public class ArrayAppender implements DataAppender { } @Override - public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator generator, NamingManager baseNaming) { - if (childConverter.getApiType() == Boolean.TYPE) { + public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator generator, NamingManager baseNaming) { + if (childConverter.getApiType().equals(TypeName.BOOLEAN)) { String collectVarName = baseNaming.getVariableNameWrapper().post("s").concat(); MethodSpec.Builder methodBuilder = generator.createMethod(baseNaming.getMethodNameWrapper().post("s").concat()); methodBuilder.addStatement("$T $L = $T.builder()", ParameterizedTypeName.get(ImmutableSet.Builder.class, Integer.class), collectVarName, ImmutableSet.class); diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/DataAppender.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/DataAppender.java index 9f97a383a1..f667a41110 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/DataAppender.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/DataAppender.java @@ -14,5 +14,5 @@ public interface DataAppender { DataHolderType getType(); - void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase converter, CraftBlockDataGenerator generator, NamingManager baseNaming); + void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase converter, CraftBlockDataGenerator generator, NamingManager baseNaming); } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/ListAppender.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/ListAppender.java index 850e44a33e..1b111fb4d9 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/ListAppender.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/ListAppender.java @@ -5,6 +5,7 @@ import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import io.papermc.generator.types.craftblockdata.CraftBlockDataGenerator; import io.papermc.generator.types.craftblockdata.property.converter.ConverterBase; @@ -28,16 +29,16 @@ public class ListAppender implements DataAppender { } @Override - public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator generator, NamingManager baseNaming) { + public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator generator, NamingManager baseNaming) { NamingManager.NameWrapper methodName = NamingManager.NameWrapper.wrap("get", METHOD_BASE_RENAMES.getOrDefault(baseNaming.getMethodBaseName(), baseNaming.getMethodBaseName())); - if (childConverter.getApiType() == Boolean.TYPE) { + if (childConverter.getApiType().equals(TypeName.BOOLEAN)) { String collectVarName = baseNaming.getVariableNameWrapper().post("s").concat(); MethodSpec.Builder methodBuilder = generator.createMethod(methodName.post("s").concat()); methodBuilder.addStatement("$T $L = $T.builder()", ParameterizedTypeName.get(ImmutableSet.Builder.class, Integer.class), collectVarName, ImmutableSet.class); methodBuilder.beginControlFlow("for (int $1L = 0, size = $2N.size(); $1L < size; $1L++)", CommonVariable.INDEX, field); { - methodBuilder.beginControlFlow("if (" + childConverter.rawGetExprent().formatted("$N.get($N)") + ")", field, indexParameter); + methodBuilder.beginControlFlow("if (" + childConverter.rawGetExprent().formatted("$N.get($N)") + ")", field, CommonVariable.INDEX); { methodBuilder.addStatement("$L.add($L)", collectVarName, CommonVariable.INDEX); } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/MapAppender.java b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/MapAppender.java index e643dd2312..9797981d52 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/MapAppender.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/craftblockdata/property/holder/appender/MapAppender.java @@ -1,62 +1,49 @@ package io.papermc.generator.types.craftblockdata.property.holder.appender; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; +import io.papermc.generator.resources.predicate.BlockPredicate; +import io.papermc.generator.rewriter.types.Types; import io.papermc.generator.types.craftblockdata.CraftBlockDataGenerator; import io.papermc.generator.types.craftblockdata.property.converter.ConverterBase; import io.papermc.generator.types.craftblockdata.property.holder.DataHolderType; +import io.papermc.generator.utils.BlockStateMapping; import io.papermc.generator.utils.CommonVariable; import io.papermc.generator.utils.NamingManager; +import io.papermc.typewriter.ClassNamed; import java.util.Collections; +import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.properties.BooleanProperty; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.MultipleFacing; -import org.bukkit.block.data.type.RedstoneWire; +import net.minecraft.world.level.block.state.properties.Property; import org.jspecify.annotations.NullMarked; @NullMarked public class MapAppender implements DataAppender { - private static final Map INDEX_NAMES = ImmutableMap.builder() - .put(BlockFace.class.getSimpleName(), "Face") - .buildOrThrow(); - - // no real rule here some has some don't mossy carpet and wall could have it - private static final Set> HAS_ALLOWED_METHOD = Set.of( - MultipleFacing.class, - RedstoneWire.class - ); - - private static boolean supportsExtraMethod(Class clazz) { - for (Class supported : HAS_ALLOWED_METHOD) { - if (supported.isAssignableFrom(clazz)) { - return true; - } - } - return false; - } - @Override public DataHolderType getType() { return DataHolderType.MAP; } @Override - public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator generator, NamingManager baseNaming) { - if (childConverter.getApiType() == Boolean.TYPE) { + public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator generator, NamingManager baseNaming) { + if (childConverter.getApiType().equals(TypeName.BOOLEAN)) { String collectVarName = baseNaming.getVariableNameWrapper().post("s").concat(); MethodSpec.Builder methodBuilder = generator.createMethod(baseNaming.getMethodNameWrapper().post("s").concat()); methodBuilder.addStatement("$T $L = $T.builder()", ParameterizedTypeName.get(ClassName.get(ImmutableSet.Builder.class), indexParameter.type), collectVarName, ImmutableSet.class); - methodBuilder.beginControlFlow("for ($T $N : $N.entrySet())", ParameterizedTypeName.get(ClassName.get(Map.Entry.class), indexParameter.type, ClassName.get(BooleanProperty.class)), CommonVariable.MAP_ENTRY, field); + methodBuilder.beginControlFlow("for ($T $N : $N.entrySet())", ParameterizedTypeName.get(ClassName.get(Map.Entry.class), indexParameter.type, TypeName.get(BooleanProperty.class)), CommonVariable.MAP_ENTRY, field); { methodBuilder.beginControlFlow("if (" + childConverter.rawGetExprent().formatted("$L.getValue()") + ")", CommonVariable.MAP_ENTRY); { @@ -71,15 +58,33 @@ public class MapAppender implements DataAppender { builder.addMethod(methodBuilder.build()); } - if (supportsExtraMethod(generator.getBaseClass()) && - indexParameter.type instanceof ClassName className && !className.isPrimitive() && !className.isBoxedPrimitive()) { - NamingManager.NameWrapper indexNaming = NamingManager.NameWrapper.wrap("get", INDEX_NAMES.getOrDefault(className.simpleName(), className.simpleName())); + if (indexParameter.type instanceof ClassName className) { + if (generator.getBaseClass().equals(Types.BLOCK_DATA_MULTIPLE_FACING) || + generator.getBaseClass().equals(Types.BLOCK_DATA_REDSTONE_WIRE) || + isImplementing(generator.getBlock(), Types.BLOCK_DATA_MULTIPLE_FACING)) { - MethodSpec.Builder methodBuilder = generator.createMethod(indexNaming.pre("Allowed").post("s").concat()); - methodBuilder.addStatement("return $T.unmodifiableSet($N.keySet())", Collections.class, field); - methodBuilder.returns(ParameterizedTypeName.get(ClassName.get(Set.class), className)); + MethodSpec.Builder methodBuilder = generator.createMethod(baseNaming.getMethodNameWrapper().pre("Allowed").post("s").concat()); + methodBuilder.addStatement("return $T.unmodifiableSet($N.keySet())", Collections.class, field); + methodBuilder.returns(ParameterizedTypeName.get(ClassName.get(Set.class), className)); - builder.addMethod(methodBuilder.build()); + builder.addMethod(methodBuilder.build()); + } } } + + public boolean isImplementing(Class block, ClassNamed type) { + Set> propertySet = new HashSet<>(BlockStateMapping.STATEFUL_BLOCKS.get(block)); + for (Map.Entry> predicateEntry : DataFileLoader.get(DataFiles.BLOCK_STATE_PREDICATES).entrySet()) { + for (BlockPredicate predicate : predicateEntry.getValue()) { + if (!predicate.matches(block, propertySet)) { + continue; + } + if (predicateEntry.getKey().equals(type)) { + return true; + } + } + } + + return false; + } } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/goal/GoalKey.java b/paper-generator/src/main/java/io/papermc/generator/types/goal/GoalKey.java new file mode 100644 index 0000000000..a1f897c073 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/types/goal/GoalKey.java @@ -0,0 +1,7 @@ +package io.papermc.generator.types.goal; + +import com.squareup.javapoet.ClassName; +import net.minecraft.resources.ResourceLocation; + +record GoalKey(ClassName type, ResourceLocation key) { +} diff --git a/paper-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java b/paper-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java index 0740f0d3bd..ea8006cfde 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java @@ -1,6 +1,5 @@ package io.papermc.generator.types.goal; -import com.destroystokyo.paper.entity.ai.GoalKey; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; @@ -12,6 +11,7 @@ import com.squareup.javapoet.TypeVariableName; import io.github.classgraph.ClassGraph; import io.github.classgraph.ScanResult; import io.papermc.generator.types.SimpleGenerator; +import io.papermc.generator.types.Types; import io.papermc.generator.utils.Annotations; import io.papermc.generator.utils.Formatting; import io.papermc.generator.utils.Javadocs; @@ -22,8 +22,6 @@ import java.util.stream.Stream; import net.minecraft.world.entity.ai.goal.Goal; import net.minecraft.world.entity.ai.goal.GoalSelector; import net.minecraft.world.entity.ai.goal.WrappedGoal; -import org.bukkit.NamespacedKey; -import org.bukkit.entity.Mob; import org.jspecify.annotations.NullMarked; import static javax.lang.model.element.Modifier.FINAL; @@ -42,9 +40,9 @@ public class MobGoalGenerator extends SimpleGenerator { @Override protected TypeSpec getTypeSpec() { - TypeVariableName type = TypeVariableName.get("T", Mob.class); + TypeVariableName type = TypeVariableName.get("T", Types.MOB); TypeSpec.Builder typeBuilder = TypeSpec.interfaceBuilder(this.className) - .addSuperinterface(ParameterizedTypeName.get(ClassName.get(com.destroystokyo.paper.entity.ai.Goal.class), type)) + .addSuperinterface(ParameterizedTypeName.get(Types.GOAL, type)) .addModifiers(PUBLIC) .addTypeVariable(type) .addAnnotations(Annotations.CLASS_HEADER) @@ -58,31 +56,31 @@ public class MobGoalGenerator extends SimpleGenerator { .addModifiers(PRIVATE, STATIC) .addParameter(keyParam) .addParameter(typeParam) - .addCode("return $T.of($N, $T.minecraft($N));", GoalKey.class, typeParam, NamespacedKey.class, keyParam) + .addCode("return $T.of($N, $T.minecraft($N));", Types.GOAL_KEY, typeParam, Types.NAMESPACED_KEY, keyParam) .addTypeVariable(type) - .returns(ParameterizedTypeName.get(ClassName.get(GoalKey.class), type)); + .returns(ParameterizedTypeName.get(Types.GOAL_KEY, type)); List> classes; - try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { + try (ScanResult scanResult = new ClassGraph().enableAllInfo().acceptPackages("net.minecraft").scan()) { classes = scanResult.getSubclasses(Goal.class.getName()).loadClasses(Goal.class); } - Stream> vanillaGoals = classes.stream() + Stream vanillaGoals = classes.stream() .filter(clazz -> !java.lang.reflect.Modifier.isAbstract(clazz.getModifiers())) .filter(clazz -> !clazz.isAnonymousClass() || ClassHelper.getTopLevelClass(clazz) != GoalSelector.class) .filter(clazz -> !WrappedGoal.class.equals(clazz)) // TODO - properly fix .map(MobGoalNames::getKey) - .sorted(Comparator., String>comparing(o -> o.getEntityClass().getSimpleName()) - .thenComparing(vanillaGoalKey -> vanillaGoalKey.getNamespacedKey().getKey()) + .sorted(Comparator.comparing(o -> o.type().simpleName()) + .thenComparing(vanillaGoalKey -> vanillaGoalKey.key().getPath()) ); vanillaGoals.forEach(goalKey -> { - String keyPath = goalKey.getNamespacedKey().getKey(); + String keyPath = goalKey.key().getPath(); String fieldName = Formatting.formatKeyAsField(keyPath); - TypeName typedKey = ParameterizedTypeName.get(GoalKey.class, goalKey.getEntityClass()); + TypeName typedKey = ParameterizedTypeName.get(Types.GOAL_KEY, goalKey.type()); FieldSpec.Builder fieldBuilder = FieldSpec.builder(typedKey, fieldName, PUBLIC, STATIC, FINAL) - .initializer("$N($S, $T.class)", createMethod.build(), keyPath, goalKey.getEntityClass()); + .initializer("$N($S, $T.class)", createMethod.build(), keyPath, goalKey.type()); typeBuilder.addField(fieldBuilder.build()); }); diff --git a/paper-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java b/paper-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java index 105dad1d01..16beefcffa 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java @@ -1,10 +1,11 @@ package io.papermc.generator.types.goal; -import com.destroystokyo.paper.entity.RangedEntity; -import com.destroystokyo.paper.entity.ai.GoalKey; import com.google.common.base.CaseFormat; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; +import io.papermc.generator.resources.data.EntityClassData; +import io.papermc.generator.types.Types; import io.papermc.generator.utils.Formatting; -import io.papermc.paper.entity.SchoolableFish; import io.papermc.typewriter.util.ClassHelper; import it.unimi.dsi.fastutil.ints.Int2BooleanFunction; import java.lang.reflect.Constructor; @@ -12,260 +13,29 @@ import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; -import java.util.Set; import net.minecraft.Util; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.ai.goal.Goal; import net.minecraft.world.entity.monster.RangedAttackMob; import org.apache.commons.lang3.math.NumberUtils; -import org.bukkit.NamespacedKey; -import org.bukkit.entity.AbstractCow; -import org.bukkit.entity.AbstractHorse; -import org.bukkit.entity.AbstractSkeleton; -import org.bukkit.entity.AbstractVillager; -import org.bukkit.entity.Ageable; -import org.bukkit.entity.Allay; -import org.bukkit.entity.Ambient; -import org.bukkit.entity.Animals; -import org.bukkit.entity.Armadillo; -import org.bukkit.entity.Axolotl; -import org.bukkit.entity.Bat; -import org.bukkit.entity.Bee; -import org.bukkit.entity.Blaze; -import org.bukkit.entity.Bogged; -import org.bukkit.entity.Breeze; -import org.bukkit.entity.Cat; -import org.bukkit.entity.CaveSpider; -import org.bukkit.entity.ChestedHorse; -import org.bukkit.entity.Chicken; -import org.bukkit.entity.Cod; -import org.bukkit.entity.Cow; -import org.bukkit.entity.Creaking; -import org.bukkit.entity.Creature; -import org.bukkit.entity.Creeper; -import org.bukkit.entity.Dolphin; -import org.bukkit.entity.Donkey; -import org.bukkit.entity.Drowned; -import org.bukkit.entity.ElderGuardian; -import org.bukkit.entity.EnderDragon; -import org.bukkit.entity.Enderman; -import org.bukkit.entity.Endermite; -import org.bukkit.entity.Evoker; -import org.bukkit.entity.Fish; -import org.bukkit.entity.Fox; -import org.bukkit.entity.Frog; -import org.bukkit.entity.Ghast; -import org.bukkit.entity.Giant; -import org.bukkit.entity.GlowSquid; -import org.bukkit.entity.Goat; -import org.bukkit.entity.Golem; -import org.bukkit.entity.Guardian; -import org.bukkit.entity.HappyGhast; -import org.bukkit.entity.Hoglin; -import org.bukkit.entity.Horse; -import org.bukkit.entity.Husk; -import org.bukkit.entity.Illager; -import org.bukkit.entity.Illusioner; -import org.bukkit.entity.IronGolem; -import org.bukkit.entity.Llama; -import org.bukkit.entity.MagmaCube; -import org.bukkit.entity.Mob; -import org.bukkit.entity.Monster; -import org.bukkit.entity.Mule; -import org.bukkit.entity.MushroomCow; -import org.bukkit.entity.Ocelot; -import org.bukkit.entity.Panda; -import org.bukkit.entity.Parrot; -import org.bukkit.entity.Phantom; -import org.bukkit.entity.Pig; -import org.bukkit.entity.PigZombie; -import org.bukkit.entity.Piglin; -import org.bukkit.entity.PiglinAbstract; -import org.bukkit.entity.PiglinBrute; -import org.bukkit.entity.Pillager; -import org.bukkit.entity.PolarBear; -import org.bukkit.entity.PufferFish; -import org.bukkit.entity.Rabbit; -import org.bukkit.entity.Raider; -import org.bukkit.entity.Ravager; -import org.bukkit.entity.Salmon; -import org.bukkit.entity.Sheep; -import org.bukkit.entity.Shulker; -import org.bukkit.entity.Silverfish; -import org.bukkit.entity.Skeleton; -import org.bukkit.entity.SkeletonHorse; -import org.bukkit.entity.Slime; -import org.bukkit.entity.Sniffer; -import org.bukkit.entity.Snowman; -import org.bukkit.entity.Spellcaster; -import org.bukkit.entity.Spider; -import org.bukkit.entity.Squid; -import org.bukkit.entity.Stray; -import org.bukkit.entity.Strider; -import org.bukkit.entity.Tadpole; -import org.bukkit.entity.Tameable; -import org.bukkit.entity.TraderLlama; -import org.bukkit.entity.TropicalFish; -import org.bukkit.entity.Turtle; -import org.bukkit.entity.Vex; -import org.bukkit.entity.Villager; -import org.bukkit.entity.Vindicator; -import org.bukkit.entity.WanderingTrader; -import org.bukkit.entity.Warden; -import org.bukkit.entity.WaterMob; -import org.bukkit.entity.Witch; -import org.bukkit.entity.Wither; -import org.bukkit.entity.WitherSkeleton; -import org.bukkit.entity.Wolf; -import org.bukkit.entity.Zoglin; -import org.bukkit.entity.Zombie; -import org.bukkit.entity.ZombieHorse; -import org.bukkit.entity.ZombieVillager; import org.jspecify.annotations.NullMarked; @NullMarked public final class MobGoalNames { // todo sync with MobGoalHelper ideally this should not be duplicated - private static final Map, Class> GENERIC_TYPE_CACHE = new HashMap<>(); - public static final Map, Class> BUKKIT_BRIDGE = Util.make(new LinkedHashMap<>(), map -> { - // - map.put(net.minecraft.world.entity.Mob.class, Mob.class); - map.put(net.minecraft.world.entity.AgeableMob.class, Ageable.class); - map.put(net.minecraft.world.entity.ambient.AmbientCreature.class, Ambient.class); - map.put(net.minecraft.world.entity.animal.Animal.class, Animals.class); - map.put(net.minecraft.world.entity.ambient.Bat.class, Bat.class); - map.put(net.minecraft.world.entity.animal.Bee.class, Bee.class); - map.put(net.minecraft.world.entity.monster.Blaze.class, Blaze.class); - map.put(net.minecraft.world.entity.animal.Cat.class, Cat.class); - map.put(net.minecraft.world.entity.monster.CaveSpider.class, CaveSpider.class); - map.put(net.minecraft.world.entity.animal.Chicken.class, Chicken.class); - map.put(net.minecraft.world.entity.animal.Cod.class, Cod.class); - map.put(net.minecraft.world.entity.animal.Cow.class, Cow.class); - map.put(net.minecraft.world.entity.PathfinderMob.class, Creature.class); - map.put(net.minecraft.world.entity.monster.Creeper.class, Creeper.class); - map.put(net.minecraft.world.entity.animal.Dolphin.class, Dolphin.class); - map.put(net.minecraft.world.entity.monster.Drowned.class, Drowned.class); - map.put(net.minecraft.world.entity.boss.enderdragon.EnderDragon.class, EnderDragon.class); - map.put(net.minecraft.world.entity.monster.EnderMan.class, Enderman.class); - map.put(net.minecraft.world.entity.monster.Endermite.class, Endermite.class); - map.put(net.minecraft.world.entity.monster.Evoker.class, Evoker.class); - map.put(net.minecraft.world.entity.animal.AbstractFish.class, Fish.class); - map.put(net.minecraft.world.entity.animal.AbstractSchoolingFish.class, SchoolableFish.class); - map.put(net.minecraft.world.entity.animal.Fox.class, Fox.class); - map.put(net.minecraft.world.entity.monster.Ghast.class, Ghast.class); - map.put(net.minecraft.world.entity.monster.Giant.class, Giant.class); - map.put(net.minecraft.world.entity.animal.AbstractGolem.class, Golem.class); - map.put(net.minecraft.world.entity.monster.Guardian.class, Guardian.class); - map.put(net.minecraft.world.entity.monster.ElderGuardian.class, ElderGuardian.class); - map.put(net.minecraft.world.entity.animal.horse.Horse.class, Horse.class); - map.put(net.minecraft.world.entity.animal.horse.AbstractHorse.class, AbstractHorse.class); - map.put(net.minecraft.world.entity.animal.horse.AbstractChestedHorse.class, ChestedHorse.class); - map.put(net.minecraft.world.entity.animal.horse.Donkey.class, Donkey.class); - map.put(net.minecraft.world.entity.animal.horse.Mule.class, Mule.class); - map.put(net.minecraft.world.entity.animal.horse.SkeletonHorse.class, SkeletonHorse.class); - map.put(net.minecraft.world.entity.animal.horse.ZombieHorse.class, ZombieHorse.class); - map.put(net.minecraft.world.entity.animal.camel.Camel.class, org.bukkit.entity.Camel.class); - map.put(net.minecraft.world.entity.monster.AbstractIllager.class, Illager.class); - map.put(net.minecraft.world.entity.monster.Illusioner.class, Illusioner.class); - map.put(net.minecraft.world.entity.monster.SpellcasterIllager.class, Spellcaster.class); - map.put(net.minecraft.world.entity.animal.IronGolem.class, IronGolem.class); - map.put(net.minecraft.world.entity.animal.horse.Llama.class, Llama.class); - map.put(net.minecraft.world.entity.animal.horse.TraderLlama.class, TraderLlama.class); - map.put(net.minecraft.world.entity.monster.MagmaCube.class, MagmaCube.class); - map.put(net.minecraft.world.entity.monster.Monster.class, Monster.class); - map.put(net.minecraft.world.entity.monster.PatrollingMonster.class, Raider.class); // close enough - map.put(net.minecraft.world.entity.animal.MushroomCow.class, MushroomCow.class); - map.put(net.minecraft.world.entity.animal.Ocelot.class, Ocelot.class); - map.put(net.minecraft.world.entity.animal.Panda.class, Panda.class); - map.put(net.minecraft.world.entity.animal.Parrot.class, Parrot.class); - map.put(net.minecraft.world.entity.animal.ShoulderRidingEntity.class, Parrot.class); // close enough - map.put(net.minecraft.world.entity.monster.Phantom.class, Phantom.class); - map.put(net.minecraft.world.entity.animal.Pig.class, Pig.class); - map.put(net.minecraft.world.entity.monster.ZombifiedPiglin.class, PigZombie.class); - map.put(net.minecraft.world.entity.monster.Pillager.class, Pillager.class); - map.put(net.minecraft.world.entity.animal.PolarBear.class, PolarBear.class); - map.put(net.minecraft.world.entity.animal.Pufferfish.class, PufferFish.class); - map.put(net.minecraft.world.entity.animal.Rabbit.class, Rabbit.class); - map.put(net.minecraft.world.entity.raid.Raider.class, Raider.class); - map.put(net.minecraft.world.entity.monster.Ravager.class, Ravager.class); - map.put(net.minecraft.world.entity.animal.Salmon.class, Salmon.class); - map.put(net.minecraft.world.entity.animal.sheep.Sheep.class, Sheep.class); - map.put(net.minecraft.world.entity.monster.Shulker.class, Shulker.class); - map.put(net.minecraft.world.entity.monster.Silverfish.class, Silverfish.class); - map.put(net.minecraft.world.entity.monster.Skeleton.class, Skeleton.class); - map.put(net.minecraft.world.entity.monster.AbstractSkeleton.class, AbstractSkeleton.class); - map.put(net.minecraft.world.entity.monster.Stray.class, Stray.class); - map.put(net.minecraft.world.entity.monster.WitherSkeleton.class, WitherSkeleton.class); - map.put(net.minecraft.world.entity.monster.Slime.class, Slime.class); - map.put(net.minecraft.world.entity.animal.SnowGolem.class, Snowman.class); - map.put(net.minecraft.world.entity.monster.Spider.class, Spider.class); - map.put(net.minecraft.world.entity.animal.Squid.class, Squid.class); - map.put(net.minecraft.world.entity.TamableAnimal.class, Tameable.class); - map.put(net.minecraft.world.entity.animal.TropicalFish.class, TropicalFish.class); - map.put(net.minecraft.world.entity.animal.Turtle.class, Turtle.class); - map.put(net.minecraft.world.entity.monster.Vex.class, Vex.class); - map.put(net.minecraft.world.entity.npc.Villager.class, Villager.class); - map.put(net.minecraft.world.entity.npc.AbstractVillager.class, AbstractVillager.class); - map.put(net.minecraft.world.entity.npc.WanderingTrader.class, WanderingTrader.class); - map.put(net.minecraft.world.entity.monster.Vindicator.class, Vindicator.class); - map.put(net.minecraft.world.entity.animal.WaterAnimal.class, WaterMob.class); - map.put(net.minecraft.world.entity.monster.Witch.class, Witch.class); - map.put(net.minecraft.world.entity.boss.wither.WitherBoss.class, Wither.class); - map.put(net.minecraft.world.entity.animal.wolf.Wolf.class, Wolf.class); - map.put(net.minecraft.world.entity.monster.Zombie.class, Zombie.class); - map.put(net.minecraft.world.entity.monster.Husk.class, Husk.class); - map.put(net.minecraft.world.entity.monster.ZombieVillager.class, ZombieVillager.class); - map.put(net.minecraft.world.entity.monster.hoglin.Hoglin.class, Hoglin.class); - map.put(net.minecraft.world.entity.monster.piglin.Piglin.class, Piglin.class); - map.put(net.minecraft.world.entity.monster.piglin.AbstractPiglin.class, PiglinAbstract.class); - map.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class); - map.put(net.minecraft.world.entity.monster.Strider.class, Strider.class); - map.put(net.minecraft.world.entity.monster.Zoglin.class, Zoglin.class); - map.put(net.minecraft.world.entity.GlowSquid.class, GlowSquid.class); - map.put(net.minecraft.world.entity.animal.axolotl.Axolotl.class, Axolotl.class); - map.put(net.minecraft.world.entity.animal.goat.Goat.class, Goat.class); - map.put(net.minecraft.world.entity.animal.frog.Frog.class, Frog.class); - map.put(net.minecraft.world.entity.animal.frog.Tadpole.class, Tadpole.class); - map.put(net.minecraft.world.entity.monster.warden.Warden.class, Warden.class); - map.put(net.minecraft.world.entity.animal.allay.Allay.class, Allay.class); - map.put(net.minecraft.world.entity.animal.sniffer.Sniffer.class, Sniffer.class); - map.put(net.minecraft.world.entity.monster.breeze.Breeze.class, Breeze.class); - map.put(net.minecraft.world.entity.animal.armadillo.Armadillo.class, Armadillo.class); - map.put(net.minecraft.world.entity.monster.Bogged.class, Bogged.class); - map.put(net.minecraft.world.entity.monster.creaking.Creaking.class, Creaking.class); - map.put(net.minecraft.world.entity.animal.AgeableWaterCreature.class, Squid.class); // close enough - map.put(net.minecraft.world.entity.animal.AbstractCow.class, AbstractCow.class); - map.put(net.minecraft.world.entity.animal.HappyGhast.class, HappyGhast.class); - // - }); + private static final Map, EntityClassData> GENERIC_TYPE_CACHE = new HashMap<>(); // TODO these kinda should be checked on each release, in case nested classes changes - private static final Map NESTED_CLASS_NAMES = Util.make(new HashMap<>(), map -> { + private static final Map RENAMES = Util.make(new HashMap<>(), map -> { map.put("AbstractSkeleton$1", "AbstractSkeletonMelee"); // remove duplicate map.put("TraderLlama$TraderLlamaDefendWanderingTraderGoal", "TraderLlamaDefendWanderingTraderGoal"); map.put("AbstractIllager$RaiderOpenDoorGoal", "RaiderOpenDoorGoal"); - - // weird enderman case - map.put("EnderMan.EndermanFreezeWhenLookedAt", "EndermanFreezeWhenLookedAt"); - map.put("EnderMan.EndermanLeaveBlockGoal", "EndermanLeaveBlockGoal"); - map.put("EnderMan.EndermanTakeBlockGoal", "EndermanTakeBlockGoal"); - map.put("EnderMan.EndermanLookForPlayerGoal", "EndermanLookForPlayerGoal"); }); - private static final Set> NO_SPECIFIER = Set.of( - Mob.class, - Creature.class, - Animals.class, - RangedEntity.class, - Tameable.class, - Monster.class, - PufferFish.class // weird case - ); - - private static String getPathName(Class type, Class holderClass, String name) { + private static String getPathName(EntityClassData type, Class holderClass, String name) { String pathName = name.substring(name.lastIndexOf('.') + 1); boolean needRename = false; @@ -279,18 +49,18 @@ public final class MobGoalNames { // todo sync with MobGoalHelper ideally this s break; } } - if (!needRename && !NESTED_CLASS_NAMES.containsKey(pathName)) { + if (!needRename && !RENAMES.containsKey(pathName)) { pathName = innerClassNames; } } - if (!NESTED_CLASS_NAMES.containsKey(pathName)) { + if (!RENAMES.containsKey(pathName)) { if (needRename) { throw new IllegalStateException("need to map " + name + " (" + pathName + ")"); } String prefix = null; - if (!NO_SPECIFIER.contains(type)) { - prefix = type.getSimpleName(); + if (type.hasSpecifier()) { + prefix = type.name().simpleName(); } else if (!net.minecraft.world.entity.Mob.class.isAssignableFrom(holderClass)) { prefix = holderClass.getSimpleName(); } @@ -298,22 +68,21 @@ public final class MobGoalNames { // todo sync with MobGoalHelper ideally this s pathName = prefix + pathName; } } else { - pathName = NESTED_CLASS_NAMES.get(pathName); + pathName = RENAMES.get(pathName); } - pathName = Formatting.stripWordOfCamelCaseName(pathName, "TargetGoal", true); // replace last? reverse search? - pathName = Formatting.stripWordOfCamelCaseName(pathName, "Goal", true); - pathName = Formatting.stripWordOfCamelCaseName(pathName, "Abstract", true); + pathName = Formatting.stripInitialWord(pathName, "Abstract"); + pathName = pathName.replaceAll("TargetGoal|Goal", ""); pathName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, pathName); return pathName; } - public static GoalKey getKey(Class goalClass) { - Class type = getGenericType(goalClass); + static GoalKey getKey(Class goalClass) { + EntityClassData classData = getGenericType(goalClass); Class holderClass = ClassHelper.getTopLevelClass(goalClass); - String name = getPathName(type, holderClass, goalClass.getName()); - return GoalKey.of(type, NamespacedKey.minecraft(name)); + String name = getPathName(classData, holderClass, goalClass.getName()); + return new GoalKey(classData.name(), ResourceLocation.withDefaultNamespace(name)); } private static final Int2BooleanFunction[] VISIBILITY_SEARCH_STEP = { @@ -334,19 +103,18 @@ public final class MobGoalNames { // todo sync with MobGoalHelper ideally this s throw new UnsupportedOperationException("Unknown visibility: " + mod); }); - private static Class getGenericType(Class goalClass) { - //noinspection unchecked - return (Class) GENERIC_TYPE_CACHE.computeIfAbsent(goalClass, key -> { + private static EntityClassData getGenericType(Class goalClass) { + return GENERIC_TYPE_CACHE.computeIfAbsent(goalClass, key -> { Constructor[] constructors = key.getDeclaredConstructors(); Arrays.sort(constructors, VISIBILITY_ORDER); for (Constructor constructor : constructors) { - for (Class paramType : constructor.getParameterTypes()) { - if (net.minecraft.world.entity.Mob.class.isAssignableFrom(paramType)) { + for (Class param : constructor.getParameterTypes()) { + if (net.minecraft.world.entity.Mob.class.isAssignableFrom(param)) { //noinspection unchecked - return toBukkitClass((Class) paramType); - } else if (RangedAttackMob.class.isAssignableFrom(paramType)) { - return RangedEntity.class; + return toBukkitClassData((Class) param); + } else if (RangedAttackMob.class.isAssignableFrom(param)) { + return new EntityClassData(Types.RANGED_ENTITY, false); // todo move outside } } } @@ -354,11 +122,11 @@ public final class MobGoalNames { // todo sync with MobGoalHelper ideally this s }); } - private static Class toBukkitClass(Class internalClass) { - Class bukkitClass = BUKKIT_BRIDGE.get(internalClass); - if (bukkitClass == null) { + private static EntityClassData toBukkitClassData(Class internalClass) { + EntityClassData data = DataFileLoader.get(DataFiles.ENTITY_CLASS_NAMES).get(internalClass); + if (data == null) { throw new IllegalStateException("Can't figure out applicable bukkit entity for internal entity " + internalClass); // maybe just return Mob? } - return bukkitClass; + return data; } } diff --git a/paper-generator/src/main/java/io/papermc/generator/types/registry/GeneratedKeyType.java b/paper-generator/src/main/java/io/papermc/generator/types/registry/GeneratedKeyType.java index 2a64dbe6cd..c9a5feb62e 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/registry/GeneratedKeyType.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/registry/GeneratedKeyType.java @@ -9,19 +9,19 @@ import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import io.papermc.generator.registry.RegistryEntry; +import io.papermc.generator.registry.RegistryIdentifiable; import io.papermc.generator.types.SimpleGenerator; +import io.papermc.generator.types.Types; import io.papermc.generator.utils.Annotations; import io.papermc.generator.utils.Formatting; import io.papermc.generator.utils.Javadocs; import io.papermc.generator.utils.experimental.ExperimentalCollector; import io.papermc.generator.utils.experimental.SingleFlagHolder; -import io.papermc.paper.registry.RegistryKey; -import io.papermc.paper.registry.TypedKey; import java.util.Map; import java.util.function.Supplier; import javax.lang.model.SourceVersion; -import net.kyori.adventure.key.Key; import net.minecraft.core.Holder; +import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.world.flag.FeatureElement; import net.minecraft.world.flag.FeatureFlags; @@ -37,7 +37,7 @@ import static javax.lang.model.element.Modifier.PUBLIC; import static javax.lang.model.element.Modifier.STATIC; @NullMarked -public class GeneratedKeyType extends SimpleGenerator { +public class GeneratedKeyType extends SimpleGenerator implements RegistryIdentifiable { private final RegistryEntry entry; private final Supplier, SingleFlagHolder>> experimentalKeys; @@ -47,20 +47,25 @@ public class GeneratedKeyType extends SimpleGenerator { super(entry.keyClassName().concat("Keys"), packageName); this.entry = entry; this.experimentalKeys = Suppliers.memoize(() -> ExperimentalCollector.collectDataDrivenElementIds(entry.registry())); - this.isFilteredRegistry = FeatureElement.FILTERED_REGISTRIES.contains(entry.registryKey()); + this.isFilteredRegistry = FeatureElement.FILTERED_REGISTRIES.contains(entry.getRegistryKey()); + } + + @Override + public ResourceKey> getRegistryKey() { + return this.entry.getRegistryKey(); } private MethodSpec.Builder createMethod(TypeName returnType) { boolean publicCreateKeyMethod = this.entry.allowCustomKeys(); - ParameterSpec keyParam = ParameterSpec.builder(Key.class, "key", FINAL).build(); + ParameterSpec keyParam = ParameterSpec.builder(Types.KEY, "key", FINAL).build(); MethodSpec.Builder create = MethodSpec.methodBuilder("create") .addModifiers(publicCreateKeyMethod ? PUBLIC : PRIVATE, STATIC) .addParameter(keyParam) - .addCode("return $T.create($T.$L, $N);", TypedKey.class, RegistryKey.class, this.entry.registryKeyField(), keyParam) + .addCode("return $T.create($T.$L, $N);", Types.TYPED_KEY, Types.REGISTRY_KEY, this.entry.registryKeyField(), keyParam) .returns(returnType); if (publicCreateKeyMethod) { - create.addJavadoc(Javadocs.CREATE_TYPED_KEY_JAVADOC, this.entry.apiClass(), this.entry.registryKey().location().toString()); + create.addJavadoc(Javadocs.CREATE_TYPED_KEY_JAVADOC, Types.typed(this.entry.data().api().klass().name()), this.entry.getRegistryKey().location().toString()); } return create; } @@ -68,7 +73,7 @@ public class GeneratedKeyType extends SimpleGenerator { private TypeSpec.Builder keyHolderType() { return classBuilder(this.className) .addModifiers(PUBLIC, FINAL) - .addJavadoc(Javadocs.getVersionDependentClassHeader("keys", "{@link $T#$L}"), RegistryKey.class, this.entry.registryKeyField()) + .addJavadoc(Javadocs.getVersionDependentClassHeader("keys", "{@link $T#$L}"), Types.REGISTRY_KEY, this.entry.registryKeyField()) .addAnnotations(Annotations.CLASS_HEADER) .addMethod(MethodSpec.constructorBuilder() .addModifiers(PRIVATE) @@ -78,7 +83,7 @@ public class GeneratedKeyType extends SimpleGenerator { @Override protected TypeSpec getTypeSpec() { - TypeName typedKeyType = ParameterizedTypeName.get(TypedKey.class, this.entry.apiClass()); + TypeName typedKeyType = ParameterizedTypeName.get(Types.TYPED_KEY, this.entry.data().api().klass().getType()); TypeSpec.Builder typeBuilder = this.keyHolderType(); MethodSpec.Builder createMethod = this.createMethod(typedKeyType); @@ -114,7 +119,7 @@ public class GeneratedKeyType extends SimpleGenerator { @Override protected JavaFile.Builder file(JavaFile.Builder builder) { - return builder.addStaticImport(Key.class, "key"); + return builder.addStaticImport(Types.KEY, "key"); } protected @Nullable SingleFlagHolder getRequiredFeature(Holder.Reference reference) { diff --git a/paper-generator/src/main/java/io/papermc/generator/types/registry/GeneratedTagKeyType.java b/paper-generator/src/main/java/io/papermc/generator/types/registry/GeneratedTagKeyType.java index 063ebd9066..8ceed3bfca 100644 --- a/paper-generator/src/main/java/io/papermc/generator/types/registry/GeneratedTagKeyType.java +++ b/paper-generator/src/main/java/io/papermc/generator/types/registry/GeneratedTagKeyType.java @@ -9,15 +9,16 @@ import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import io.papermc.generator.Main; import io.papermc.generator.registry.RegistryEntry; +import io.papermc.generator.registry.RegistryIdentifiable; import io.papermc.generator.types.SimpleGenerator; +import io.papermc.generator.types.Types; import io.papermc.generator.utils.Annotations; import io.papermc.generator.utils.Formatting; import io.papermc.generator.utils.Javadocs; import io.papermc.generator.utils.experimental.SingleFlagHolder; -import io.papermc.paper.registry.RegistryKey; -import io.papermc.paper.registry.tag.TagKey; import java.util.concurrent.atomic.AtomicBoolean; -import net.kyori.adventure.key.Key; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; import org.jspecify.annotations.NullMarked; import static com.squareup.javapoet.TypeSpec.classBuilder; @@ -29,26 +30,31 @@ import static javax.lang.model.element.Modifier.PUBLIC; import static javax.lang.model.element.Modifier.STATIC; @NullMarked -public class GeneratedTagKeyType extends SimpleGenerator { +public class GeneratedTagKeyType extends SimpleGenerator implements RegistryIdentifiable { - private final RegistryEntry entry; + private final RegistryEntry entry; - public GeneratedTagKeyType(RegistryEntry entry, String packageName) { + public GeneratedTagKeyType(RegistryEntry entry, String packageName) { super(entry.keyClassName().concat("TagKeys"), packageName); this.entry = entry; } + @Override + public ResourceKey> getRegistryKey() { + return this.entry.getRegistryKey(); + } + private MethodSpec.Builder createMethod(TypeName returnType) { boolean publicCreateKeyMethod = true; // tag lifecycle event exists - ParameterSpec keyParam = ParameterSpec.builder(Key.class, "key", FINAL).build(); + ParameterSpec keyParam = ParameterSpec.builder(Types.KEY, "key", FINAL).build(); MethodSpec.Builder create = MethodSpec.methodBuilder("create") .addModifiers(publicCreateKeyMethod ? PUBLIC : PRIVATE, STATIC) .addParameter(keyParam) - .addCode("return $T.create($T.$L, $N);", TagKey.class, RegistryKey.class, this.entry.registryKeyField(), keyParam) + .addCode("return $T.create($T.$L, $N);", Types.TAG_KEY, Types.REGISTRY_KEY, this.entry.registryKeyField(), keyParam) .returns(returnType); if (publicCreateKeyMethod) { - create.addJavadoc(Javadocs.CREATED_TAG_KEY_JAVADOC, this.entry.apiClass(), this.entry.registryKey().location().toString()); + create.addJavadoc(Javadocs.CREATED_TAG_KEY_JAVADOC, Types.typed(this.entry.data().api().klass().name()), this.entry.getRegistryKey().location().toString()); } return create; } @@ -56,7 +62,7 @@ public class GeneratedTagKeyType extends SimpleGenerator { private TypeSpec.Builder keyHolderType() { return classBuilder(this.className) .addModifiers(PUBLIC, FINAL) - .addJavadoc(Javadocs.getVersionDependentClassHeader("tag keys", "{@link $T#$L}"), RegistryKey.class, this.entry.registryKeyField()) + .addJavadoc(Javadocs.getVersionDependentClassHeader("tag keys", "{@link $T#$L}"), Types.REGISTRY_KEY, this.entry.registryKeyField()) .addAnnotations(Annotations.CLASS_HEADER) .addMethod(MethodSpec.constructorBuilder() .addModifiers(PRIVATE) @@ -66,7 +72,7 @@ public class GeneratedTagKeyType extends SimpleGenerator { @Override protected TypeSpec getTypeSpec() { - TypeName tagKeyType = ParameterizedTypeName.get(TagKey.class, this.entry.apiClass()); + TypeName tagKeyType = ParameterizedTypeName.get(Types.TAG_KEY, this.entry.data().api().klass().getType()); TypeSpec.Builder typeBuilder = this.keyHolderType(); MethodSpec.Builder createMethod = this.createMethod(tagKeyType); @@ -95,6 +101,6 @@ public class GeneratedTagKeyType extends SimpleGenerator { @Override protected JavaFile.Builder file(JavaFile.Builder builder) { - return builder.addStaticImport(Key.class, "key"); + return builder.addStaticImport(Types.KEY, "key"); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/Annotations.java b/paper-generator/src/main/java/io/papermc/generator/utils/Annotations.java index 4a781ff658..e9b24e7fc1 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/Annotations.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/Annotations.java @@ -1,20 +1,18 @@ package io.papermc.generator.utils; import com.squareup.javapoet.AnnotationSpec; +import io.papermc.generator.types.Types; import io.papermc.generator.utils.experimental.SingleFlagHolder; -import io.papermc.paper.generated.GeneratedFrom; import java.util.List; import net.minecraft.SharedConstants; -import org.bukkit.MinecraftExperimental; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; -@NullMarked public final class Annotations { public static List experimentalAnnotations(SingleFlagHolder requiredFeature) { - AnnotationSpec.Builder builder = AnnotationSpec.builder(MinecraftExperimental.class); - builder.addMember("value", "$T.$L", MinecraftExperimental.Requires.class, requiredFeature.asAnnotationMember().name()); + AnnotationSpec.Builder builder = AnnotationSpec.builder(Types.MINECRAFT_EXPERIMENTAL); + builder.addMember("value", "$T.$L", Types.MINECRAFT_EXPERIMENTAL_REQUIRES, requiredFeature.asAnnotationMember()); return List.of( AnnotationSpec.builder(ApiStatus.Experimental.class).build(), @@ -34,7 +32,7 @@ public final class Annotations { public static final AnnotationSpec EXPERIMENTAL_API_ANNOTATION = AnnotationSpec.builder(ApiStatus.Experimental.class).build(); public static final AnnotationSpec NULL_MARKED = AnnotationSpec.builder(NullMarked.class).build(); public static final AnnotationSpec OVERRIDE = AnnotationSpec.builder(Override.class).build(); - public static final AnnotationSpec GENERATED_FROM = AnnotationSpec.builder(GeneratedFrom.class) + public static final AnnotationSpec GENERATED_FROM = AnnotationSpec.builder(Types.GENERATED_FROM) .addMember("value", "$S", SharedConstants.getCurrentVersion().id()) .build(); public static final Iterable CLASS_HEADER = List.of( diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/BasePackage.java b/paper-generator/src/main/java/io/papermc/generator/utils/BasePackage.java new file mode 100644 index 0000000000..ff6ee133e4 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/utils/BasePackage.java @@ -0,0 +1,33 @@ +package io.papermc.generator.utils; + +import com.squareup.javapoet.ClassName; +import io.papermc.typewriter.ClassNamed; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.Nullable; + +public record BasePackage(String name) { + + public static final BasePackage PAPER = new BasePackage("io.papermc.paper"); + public static final BasePackage BUKKIT = new BasePackage("org.bukkit"); + public static final BasePackage CRAFT_BUKKIT = new BasePackage("org.bukkit.craftbukkit"); + @ApiStatus.Obsolete + public static final BasePackage PAPER_LEGACY = new BasePackage("com.destroystokyo.paper"); + @Deprecated + public static final BasePackage SPIGOT = new BasePackage("org.spigotmc"); + + public ClassName rootClass(String simpleName, String... simpleNames) { + return relativeClass(null, simpleName, simpleNames); + } + + public ClassName relativeClass(@Nullable String packageName, String simpleName, String... simpleNames) { + return ClassName.get(packageName == null ? this.name : String.join(".", this.name, packageName), simpleName, simpleNames); + } + + public ClassNamed rootClassNamed(String simpleName, String... simpleNames) { + return relativeClassNamed(null, simpleName, simpleNames); + } + + public ClassNamed relativeClassNamed(@Nullable String packageName, String simpleName, String... simpleNames) { + return ClassNamed.of(packageName == null ? this.name : String.join(".", this.name, packageName), simpleName, simpleNames); + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/BlockEntityMapping.java b/paper-generator/src/main/java/io/papermc/generator/utils/BlockEntityMapping.java index d8d7d0f56a..0b4258eca6 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/BlockEntityMapping.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/BlockEntityMapping.java @@ -8,9 +8,7 @@ import java.util.Map; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.block.entity.BlockEntityType; -import org.jspecify.annotations.NullMarked; -@NullMarked public final class BlockEntityMapping { // if this become painful/too weird like the blockdata just rename the impl directly again diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/BlockStateMapping.java b/paper-generator/src/main/java/io/papermc/generator/utils/BlockStateMapping.java index 6cbb05e886..e70455ebde 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/BlockStateMapping.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/BlockStateMapping.java @@ -1,179 +1,121 @@ package io.papermc.generator.utils; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.BiMap; +import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; import com.mojang.datafixers.util.Either; +import io.papermc.generator.Main; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; +import io.papermc.generator.resources.predicate.BlockPredicate; import io.papermc.generator.types.craftblockdata.property.holder.VirtualField; +import io.papermc.typewriter.ClassNamed; +import io.papermc.typewriter.util.ClassNamedView; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; -import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; -import net.minecraft.core.Direction; -import net.minecraft.core.FrontAndTop; +import java.util.stream.Collectors; +import net.minecraft.Util; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.util.StringRepresentable; -import net.minecraft.world.level.block.AbstractFurnaceBlock; -import net.minecraft.world.level.block.BigDripleafStemBlock; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.CommandBlock; -import net.minecraft.world.level.block.IronBarsBlock; -import net.minecraft.world.level.block.MultifaceBlock; import net.minecraft.world.level.block.NoteBlock; -import net.minecraft.world.level.block.PipeBlock; import net.minecraft.world.level.block.StructureBlock; import net.minecraft.world.level.block.TestBlock; import net.minecraft.world.level.block.TestInstanceBlock; -import net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState; -import net.minecraft.world.level.block.entity.vault.VaultState; -import net.minecraft.world.level.block.state.properties.AttachFace; -import net.minecraft.world.level.block.state.properties.BambooLeaves; -import net.minecraft.world.level.block.state.properties.BedPart; -import net.minecraft.world.level.block.state.properties.BellAttachType; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.ChestType; -import net.minecraft.world.level.block.state.properties.ComparatorMode; -import net.minecraft.world.level.block.state.properties.CreakingHeartState; -import net.minecraft.world.level.block.state.properties.DoorHingeSide; -import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.level.block.state.properties.DripstoneThickness; -import net.minecraft.world.level.block.state.properties.Half; -import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; -import net.minecraft.world.level.block.state.properties.PistonType; import net.minecraft.world.level.block.state.properties.Property; -import net.minecraft.world.level.block.state.properties.RailShape; -import net.minecraft.world.level.block.state.properties.RedstoneSide; -import net.minecraft.world.level.block.state.properties.SculkSensorPhase; -import net.minecraft.world.level.block.state.properties.SlabType; -import net.minecraft.world.level.block.state.properties.StairsShape; -import net.minecraft.world.level.block.state.properties.StructureMode; -import net.minecraft.world.level.block.state.properties.TestBlockMode; -import net.minecraft.world.level.block.state.properties.Tilt; -import net.minecraft.world.level.block.state.properties.WallSide; -import org.bukkit.Axis; -import org.bukkit.Instrument; -import org.bukkit.block.BlockFace; -import org.bukkit.block.Orientation; -import org.bukkit.block.data.Ageable; -import org.bukkit.block.data.AnaloguePowerable; -import org.bukkit.block.data.Bisected; -import org.bukkit.block.data.Brushable; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.FaceAttachable; -import org.bukkit.block.data.Hangable; -import org.bukkit.block.data.Hatchable; -import org.bukkit.block.data.Levelled; -import org.bukkit.block.data.Lightable; -import org.bukkit.block.data.MultipleFacing; -import org.bukkit.block.data.Openable; -import org.bukkit.block.data.Orientable; -import org.bukkit.block.data.Powerable; -import org.bukkit.block.data.Rail; -import org.bukkit.block.data.Rotatable; -import org.bukkit.block.data.Segmentable; -import org.bukkit.block.data.Snowable; -import org.bukkit.block.data.Waterlogged; -import org.bukkit.block.data.type.Bamboo; -import org.bukkit.block.data.type.Bed; -import org.bukkit.block.data.type.Bell; -import org.bukkit.block.data.type.BigDripleaf; -import org.bukkit.block.data.type.Chest; -import org.bukkit.block.data.type.Comparator; -import org.bukkit.block.data.type.CreakingHeart; -import org.bukkit.block.data.type.Door; -import org.bukkit.block.data.type.Dripleaf; -import org.bukkit.block.data.type.Fence; -import org.bukkit.block.data.type.Furnace; -import org.bukkit.block.data.type.PointedDripstone; -import org.bukkit.block.data.type.RedstoneRail; -import org.bukkit.block.data.type.RedstoneWire; -import org.bukkit.block.data.type.ResinClump; -import org.bukkit.block.data.type.SculkSensor; -import org.bukkit.block.data.type.Slab; -import org.bukkit.block.data.type.Stairs; -import org.bukkit.block.data.type.Switch; -import org.bukkit.block.data.type.TechnicalPiston; -import org.bukkit.block.data.type.TrialSpawner; -import org.bukkit.block.data.type.Vault; -import org.bukkit.block.data.type.Wall; -import org.jspecify.annotations.NullMarked; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.jspecify.annotations.Nullable; -@NullMarked public final class BlockStateMapping { - public record BlockData(String implName, @Nullable Class api, + public record BlockData(String implName, ClassNamed api, Collection> properties, Map, Field> propertyFields, Multimap, Property> complexPropertyFields) { } - private static final Map API_RENAMES = ImmutableMap.builder() - .put("SnowLayer", "Snow") - .put("StainedGlassPane", "GlassPane") // weird that this one implements glass pane but not the regular glass pane - .put("CeilingHangingSign", "HangingSign") - .put("RedStoneWire", "RedstoneWire") - .put("TripWire", "Tripwire") - .put("TripWireHook", "TripwireHook") - .put("Tnt", "TNT") - .put("BambooStalk", "Bamboo") - .put("Farm", "Farmland") - .put("ChiseledBookShelf", "ChiseledBookshelf") - .put("UntintedParticleLeaves", "Leaves") - .put("TintedParticleLeaves", "Leaves") - .put("StandingSign", "Sign") - .put("FenceGate", "Gate") - .buildOrThrow(); - - private static final Set> BLOCK_SUFFIX_INTENDED = Set.of( - CommandBlock.class, - StructureBlock.class, - NoteBlock.class, - TestBlock.class, - TestInstanceBlock.class - ); - - // virtual data that doesn't exist as constant in the source but still organized this way in the api - public static final ImmutableMultimap, VirtualField> VIRTUAL_NODES = ImmutableMultimap., VirtualField>builder() - .build(); - - public static final Map, Field> FALLBACK_GENERIC_FIELDS; + public static final BiMap, Field> GENERIC_FIELDS; static { - Map, Field> fallbackGenericFields = new HashMap<>(); - fetchProperties(BlockStateProperties.class, (field, property) -> fallbackGenericFields.put(property, field), null); - FALLBACK_GENERIC_FIELDS = Collections.unmodifiableMap(fallbackGenericFields); + ImmutableBiMap.Builder, Field> genericFields = ImmutableBiMap.builder(); + fetchProperties(BlockStateProperties.class, (field, property) -> genericFields.put(property, field), null); + GENERIC_FIELDS = genericFields.buildOrThrow(); } - public static final Map, BlockData> MAPPING; + public static final Map, String> GENERIC_FIELD_NAMES = BlockStateMapping.GENERIC_FIELDS.entrySet().stream().collect(Collectors.toUnmodifiableMap( + Map.Entry::getKey, entry -> entry.getValue().getName() + )); - static { - Map, Collection>> specialBlocks = new IdentityHashMap<>(); + public static final Set PROPERTY_NAMES = BlockStateMapping.GENERIC_FIELDS.keySet().stream() + .map(Property::getName).collect(Collectors.toUnmodifiableSet()); + + public static final Map, Collection>> STATEFUL_BLOCKS = Collections.unmodifiableMap(Util.make(new IdentityHashMap<>(), map -> { for (Block block : BuiltInRegistries.BLOCK) { if (!block.getStateDefinition().getProperties().isEmpty()) { - specialBlocks.put(block.getClass(), block.getStateDefinition().getProperties()); + map.put(block.getClass(), block.getStateDefinition().getProperties()); } } + })); + + private static Map, BlockData> create(Path rootDir) { + class ExtraData { + public static final Map API_RENAMES = ImmutableMap.builder() + .put("SnowLayer", "Snow") + .put("StainedGlassPane", "GlassPane") // weird that this one implements glass pane but not the regular glass pane + .put("CeilingHangingSign", "HangingSign") + .put("RedStoneWire", "RedstoneWire") + .put("TripWire", "Tripwire") + .put("TripWireHook", "TripwireHook") + .put("Tnt", "TNT") + .put("BambooStalk", "Bamboo") + .put("Farm", "Farmland") + .put("ChiseledBookShelf", "ChiseledBookshelf") + .put("UntintedParticleLeaves", "Leaves") + .put("TintedParticleLeaves", "Leaves") + .put("StandingSign", "Sign") + .put("FenceGate", "Gate") + .buildOrThrow(); + + public static final Set> BLOCK_SUFFIX_INTENDED = Set.of( + CommandBlock.class, + StructureBlock.class, + NoteBlock.class, + TestBlock.class, + TestInstanceBlock.class + ); + + // virtual data that doesn't exist as constant in the source but still organized this way in the api + public static final ImmutableMultimap, VirtualField> VIRTUAL_NODES = ImmutableMultimap., VirtualField>builder() + .build(); + } Map, BlockData> map = new IdentityHashMap<>(); - for (Map.Entry, Collection>> entry : specialBlocks.entrySet()) { - Class specialBlock = entry.getKey(); + for (Map.Entry, Collection>> entry : STATEFUL_BLOCKS.entrySet()) { + Class statefulBlock = entry.getKey(); Collection> properties = new ArrayList<>(entry.getValue()); Map, Field> propertyFields = new HashMap<>(properties.size()); Multimap, Property> complexPropertyFields = ArrayListMultimap.create(); - fetchProperties(specialBlock, (field, property) -> { + fetchProperties(statefulBlock, (field, property) -> { if (properties.contains(property)) { propertyFields.put(property, field); } @@ -184,186 +126,78 @@ public final class BlockStateMapping { }); // virtual nodes - if (VIRTUAL_NODES.containsKey(specialBlock)) { - for (VirtualField virtualField : VIRTUAL_NODES.get(specialBlock)) { + if (ExtraData.VIRTUAL_NODES.containsKey(statefulBlock)) { + for (VirtualField virtualField : ExtraData.VIRTUAL_NODES.get(statefulBlock)) { for (Property property : virtualField.values()) { if (properties.remove(property)) { complexPropertyFields.put(Either.right(virtualField), property); } else { - throw new IllegalStateException("Unhandled virtual node " + virtualField.name() + " for " + property + " in " + specialBlock.getCanonicalName()); + throw new IllegalStateException("Unhandled virtual node " + virtualField.name() + " for " + property + " in " + statefulBlock.getCanonicalName()); } } } } - String apiName = formatApiName(specialBlock); + String apiName = formatApiName(ExtraData.BLOCK_SUFFIX_INTENDED, statefulBlock); String implName = "Craft".concat(apiName); // before renames - apiName = Formatting.stripWordOfCamelCaseName(apiName, "Base", true); - apiName = API_RENAMES.getOrDefault(apiName, apiName); + apiName = Formatting.stripInitialWord(apiName, "Base"); + apiName = ExtraData.API_RENAMES.getOrDefault(apiName, apiName); - Class api = ClassHelper.classOr("org.bukkit.block.data.type." + apiName, null); - if (api == null) { - Class directParent = specialBlock.getSuperclass(); - if (specialBlocks.containsKey(directParent)) { + ClassNamedView view = new ClassNamedView(rootDir.resolve("paper-api/src/main/java"), 1, "org/bukkit/block/data/type"); + ClassNamed api = view.tryFindFirst("org/bukkit/block/data/type/" + apiName).or(() -> { + Class directParent = statefulBlock.getSuperclass(); + if (STATEFUL_BLOCKS.containsKey(directParent)) { // if the properties are the same then always consider the parent // check deeper in the tree? - if (specialBlocks.get(directParent).equals(entry.getValue())) { - String parentApiName = formatApiName(directParent); - parentApiName = Formatting.stripWordOfCamelCaseName(parentApiName, "Base", true); - parentApiName = API_RENAMES.getOrDefault(parentApiName, parentApiName); - api = ClassHelper.classOr("org.bukkit.block.data.type." + parentApiName, api); + if (STATEFUL_BLOCKS.get(directParent).equals(entry.getValue())) { + String parentApiName = formatApiName(ExtraData.BLOCK_SUFFIX_INTENDED, directParent); + parentApiName = Formatting.stripInitialWord(parentApiName, "Base"); + parentApiName = ExtraData.API_RENAMES.getOrDefault(parentApiName, parentApiName); + return view.tryFindFirst("org/bukkit/block/data/type/" + parentApiName); } } - } - if (api == null) { // todo remove this part - if (AbstractFurnaceBlock.class.isAssignableFrom(specialBlock)) { - api = Furnace.class; // for smoker and blast furnace - } else if (specialBlock == BigDripleafStemBlock.class) { - api = Dripleaf.class; - } else if (specialBlock == IronBarsBlock.class) { - api = Fence.class; // for glass pane (regular) and iron bars - } else if (specialBlock == MultifaceBlock.class) { - api = ResinClump.class; + return Optional.empty(); + }).orElseGet(() -> { + Set> propertySet = new HashSet<>(entry.getValue()); + for (Map.Entry> predicateEntry : DataFileLoader.get(DataFiles.BLOCK_STATE_PREDICATES).entrySet()) { + for (BlockPredicate predicate : predicateEntry.getValue()) { + if (predicate.matches(statefulBlock, propertySet)) { + return predicateEntry.getKey(); + } + } } - } - map.put(specialBlock, new BlockData(implName, api, properties, propertyFields, complexPropertyFields)); + return null; + }); + + map.put(statefulBlock, new BlockData(implName, Objects.requireNonNull(api, () -> "Unknown block data for " + statefulBlock.getCanonicalName()), properties, propertyFields, complexPropertyFields)); } - MAPPING = Collections.unmodifiableMap(map); + return Collections.unmodifiableMap(map); } - private static final Map> NAME_TO_DATA = Map.of( - BlockStateProperties.AGE_1.getName(), Ageable.class, - BlockStateProperties.LEVEL.getName(), Levelled.class - ); + public static @MonotonicNonNull Map, BlockData> MAPPING; - private static final Map, Class> PROPERTY_TO_DATA = ImmutableMap., Class>builder() - // levelled and ageable are done using the property name - .put(BlockStateProperties.POWER, AnaloguePowerable.class) - .put(BlockStateProperties.HALF, Bisected.class) - .put(BlockStateProperties.DOUBLE_BLOCK_HALF, Bisected.class) - .put(BlockStateProperties.DUSTED, Brushable.class) - .put(BlockStateProperties.FACING, Directional.class) - .put(BlockStateProperties.HORIZONTAL_FACING, Directional.class) - .put(BlockStateProperties.ATTACH_FACE, FaceAttachable.class) - .put(BlockStateProperties.HANGING, Hangable.class) - .put(BlockStateProperties.HATCH, Hatchable.class) - .put(BlockStateProperties.LIT, Lightable.class) - // multiple facing is done by matching two or more pipe block properties - .put(BlockStateProperties.OPEN, Openable.class) - .put(BlockStateProperties.HORIZONTAL_AXIS, Orientable.class) - .put(BlockStateProperties.AXIS, Orientable.class) - .put(BlockStateProperties.POWERED, Powerable.class) - .put(BlockStateProperties.RAIL_SHAPE, Rail.class) - .put(BlockStateProperties.RAIL_SHAPE_STRAIGHT, Rail.class) - .put(BlockStateProperties.ROTATION_16, Rotatable.class) - .put(BlockStateProperties.SNOWY, Snowable.class) - .put(BlockStateProperties.WATERLOGGED, Waterlogged.class) - .put(BlockStateProperties.SEGMENT_AMOUNT, Segmentable.class) - .buildOrThrow(); + public static Map, BlockData> getOrCreate() { + if (MAPPING == null) { + MAPPING = create(Main.ROOT_DIR); + } - private static final Map, Class> MAIN_PROPERTY_TO_DATA = Map.of( - BlockStateProperties.PISTON_TYPE, TechnicalPiston.class, - BlockStateProperties.STAIRS_SHAPE, Stairs.class - ); + return MAPPING; + } - public static final Map>, Class>> ENUM_BRIDGE = ImmutableMap.>, Class>>builder() - .put(DoorHingeSide.class, Door.Hinge.class) - .put(SlabType.class, Slab.Type.class) - .put(StructureMode.class, org.bukkit.block.data.type.StructureBlock.Mode.class) - .put(DripstoneThickness.class, PointedDripstone.Thickness.class) - .put(WallSide.class, Wall.Height.class) - .put(BellAttachType.class, Bell.Attachment.class) - .put(NoteBlockInstrument.class, Instrument.class) - .put(StairsShape.class, Stairs.Shape.class) - .put(Direction.class, BlockFace.class) - .put(ComparatorMode.class, Comparator.Mode.class) - .put(PistonType.class, TechnicalPiston.Type.class) - .put(BedPart.class, Bed.Part.class) - .put(Half.class, Bisected.Half.class) - .put(AttachFace.class, FaceAttachable.AttachedFace.class) - .put(RailShape.class, Rail.Shape.class) - .put(SculkSensorPhase.class, SculkSensor.Phase.class) - .put(DoubleBlockHalf.class, Bisected.Half.class) - .put(Tilt.class, BigDripleaf.Tilt.class) - .put(ChestType.class, Chest.Type.class) - .put(RedstoneSide.class, RedstoneWire.Connection.class) - .put(Direction.Axis.class, Axis.class) - .put(BambooLeaves.class, Bamboo.Leaves.class) - .put(TrialSpawnerState.class, TrialSpawner.State.class) - .put(FrontAndTop.class, Orientation.class) - .put(VaultState.class, Vault.State.class) - .put(CreakingHeartState.class, CreakingHeart.State.class) - .put(TestBlockMode.class, org.bukkit.block.data.type.TestBlock.Mode.class) - .buildOrThrow(); - - public static @Nullable Class getBestSuitedApiClass(Class block) { - if (!MAPPING.containsKey(block)) { + public static @Nullable ClassNamed getBestSuitedApiClass(Class block) { + if (!getOrCreate().containsKey(block)) { return null; } - return getBestSuitedApiClass(MAPPING.get(block)); + return getOrCreate().get(block).api(); } - public static @Nullable Class getBestSuitedApiClass(BlockData data) { - if (data.api() != null) { - return data.api(); - } - - int pipeProps = 0; - Set> extensions = new LinkedHashSet<>(); - for (Property property : data.properties()) { - if (MAIN_PROPERTY_TO_DATA.containsKey(property)) { - return MAIN_PROPERTY_TO_DATA.get(property); - } - - if (NAME_TO_DATA.containsKey(property.getName())) { - extensions.add(NAME_TO_DATA.get(property.getName())); - continue; - } - - if (PROPERTY_TO_DATA.containsKey(property)) { - extensions.add(PROPERTY_TO_DATA.get(property)); - continue; - } - - if (PipeBlock.PROPERTY_BY_DIRECTION.containsValue(property)) { - pipeProps++; - } - } - - if (!extensions.isEmpty()) { - if (isExactly(extensions, Switch.class)) { - return Switch.class; - } - if (isExactly(extensions, RedstoneRail.class)) { - return RedstoneRail.class; - } - - return extensions.iterator().next(); - } - - for (Property property : data.complexPropertyFields().values()) { - if (PipeBlock.PROPERTY_BY_DIRECTION.containsValue(property)) { - pipeProps++; - } - } - - if (pipeProps >= 2) { - return MultipleFacing.class; - } - return null; - } - - private static boolean isExactly(Set> extensions, Class globClass) { - return extensions.equals(ClassHelper.getAllInterfaces(globClass, org.bukkit.block.data.BlockData.class, new HashSet<>())); - } - - private static String formatApiName(Class specialBlock) { + public static String formatApiName(Set> withBlockSuffix, Class specialBlock) { String apiName = specialBlock.getSimpleName(); - if (!BLOCK_SUFFIX_INTENDED.contains(specialBlock)) { - return apiName.substring(0, apiName.length() - "Block".length()); + if (!withBlockSuffix.contains(specialBlock)) { + return Formatting.stripInitialWord(apiName, "Block", true); } return apiName; } diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/ClassHelper.java b/paper-generator/src/main/java/io/papermc/generator/utils/ClassHelper.java index 51e3df843e..54a18637de 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/ClassHelper.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/ClassHelper.java @@ -4,27 +4,10 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Set; -import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; -@NullMarked public final class ClassHelper { - public static Set> getAllInterfaces(Class clazz, Class ignored, Set> interfaces) { - Class[] classes = clazz.getInterfaces(); - interfaces.addAll(Arrays.asList(classes)); - for (Class farClass : classes) { - if (farClass == ignored) { - continue; - } - getAllInterfaces(farClass, ignored, interfaces); - } - interfaces.remove(ignored); - return interfaces; - } - public static @Nullable Type getNestedTypeParameter(Type type, @Nullable Class... classes) { for (Class clazz : classes) { if (!(type instanceof ParameterizedType complexType)) { @@ -59,14 +42,6 @@ public final class ClassHelper { return (field.getModifiers() & flags) == flags; } - public static @Nullable Class classOr(String className, @Nullable Class defaultClass) { - try { - return (Class) Class.forName(className); - } catch (ClassNotFoundException ignored) { - return defaultClass; - } - } - private ClassHelper() { } } diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/CommonVariable.java b/paper-generator/src/main/java/io/papermc/generator/utils/CommonVariable.java index 55ea8c742f..d149d80c6e 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/CommonVariable.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/CommonVariable.java @@ -1,8 +1,5 @@ package io.papermc.generator.utils; -import org.jspecify.annotations.NullMarked; - -@NullMarked public final class CommonVariable { public static final String INDEX = "index"; diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/Formatting.java b/paper-generator/src/main/java/io/papermc/generator/utils/Formatting.java index 7009304f57..69a69a0c78 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/Formatting.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/Formatting.java @@ -5,17 +5,15 @@ import java.util.Locale; import java.util.Optional; import java.util.function.Function; import java.util.regex.Pattern; -import java.util.stream.IntStream; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.tags.TagKey; import org.apache.commons.lang3.math.NumberUtils; -import org.jspecify.annotations.NullMarked; +import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.Nullable; -@NullMarked public final class Formatting { private static final Pattern ILLEGAL_FIELD_CHARACTERS = Pattern.compile("[.-/]"); @@ -24,6 +22,7 @@ public final class Formatting { return ILLEGAL_FIELD_CHARACTERS.matcher(path.toUpperCase(Locale.ENGLISH)).replaceAll("_"); } + @ApiStatus.Obsolete public static String formatTagFieldPrefix(String name, ResourceKey> registryKey) { if (registryKey == Registries.BLOCK) { return ""; @@ -34,45 +33,42 @@ public final class Formatting { return name.toUpperCase(Locale.ENGLISH) + "_"; } - public static Optional formatTagKey(String tagDir, String resourcePath) { + public static Optional findTagKeyPath(String tagDir, String resourcePath) { int tagsIndex = resourcePath.indexOf(tagDir); int dotIndex = resourcePath.lastIndexOf('.'); if (tagsIndex == -1 || dotIndex == -1) { return Optional.empty(); } - return Optional.of(resourcePath.substring(tagsIndex + tagDir.length() + 1, dotIndex)); // namespace/tags/registry_key/[tag_key].json + return Optional.of(resourcePath.substring(tagsIndex + tagDir.length() + 1, dotIndex)); // namespace/tags/registry_key/[tag_key_path].json } public static String quoted(String value) { return "\"" + value + "\""; } - public static String[] asCode(int... values) { - return IntStream.of(values).mapToObj(Integer::toString).toArray(String[]::new); + public static String stripInitialWord(String name, String word) { // both ends + if (name.startsWith(word)) { + return name.substring(word.length()); + } + + if (name.endsWith(word)) { + return name.substring(0, name.length() - word.length()); + } + + return name; } - public static String stripWordOfCamelCaseName(String name, String word, boolean onlyOnce) { - String newName = name; - int startIndex = 0; - while (true) { - int baseIndex = newName.indexOf(word, startIndex); - if (baseIndex == -1) { - return newName; + public static String stripInitialWord(String name, String word, boolean fromEnd) { + if (fromEnd) { + if (name.endsWith(word)) { + return name.substring(0, name.length() - word.length()); } - - if ((baseIndex > 0 && !Character.isLowerCase(newName.charAt(baseIndex - 1))) || - (baseIndex + word.length() < newName.length() && !Character.isUpperCase(newName.charAt(baseIndex + word.length())))) { - startIndex = baseIndex + word.length(); - continue; - } - - newName = newName.substring(0, baseIndex) + newName.substring(baseIndex + word.length()); - startIndex = baseIndex; - if (onlyOnce) { - break; + } else { + if (name.startsWith(word)) { + return name.substring(word.length()); } } - return newName; + return name; } public static final Comparator> HOLDER_ORDER = alphabeticKeyOrder(reference -> reference.key().location().getPath()); diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/Javadocs.java b/paper-generator/src/main/java/io/papermc/generator/utils/Javadocs.java index 4c52440793..b83fd96430 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/Javadocs.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/Javadocs.java @@ -1,11 +1,8 @@ package io.papermc.generator.utils; -import org.jspecify.annotations.NullMarked; - -@NullMarked public final class Javadocs { - public static String getVersionDependentClassHeader(String objectIdentifier, String headerIdentifier) { + public static String getVersionDependentClassHeader(String valueId, String holderId) { return """ Vanilla %s for %s. @@ -14,15 +11,15 @@ public final class Javadocs { changed (including removals) on any Minecraft version bump, so cross-version compatibility is not provided on the same level as it is on most of the other API. - """.formatted(objectIdentifier, headerIdentifier); + """.formatted(valueId, holderId); } - public static String getVersionDependentField(String headerIdentifier) { + public static String getVersionDependentField(String id) { return """ %s @apiNote This field is version-dependant and may be removed in future Minecraft versions - """.formatted(headerIdentifier); + """.formatted(id); } public static final String CREATE_TYPED_KEY_JAVADOC = """ diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/NamingManager.java b/paper-generator/src/main/java/io/papermc/generator/utils/NamingManager.java index d5ca379ae7..b7cebdc9c8 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/NamingManager.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/NamingManager.java @@ -1,14 +1,14 @@ package io.papermc.generator.utils; import com.google.common.base.CaseFormat; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.TypeName; import java.util.Optional; import java.util.function.Predicate; import javax.lang.model.SourceVersion; import org.jetbrains.annotations.Contract; -import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; -@NullMarked public class NamingManager { private final @Nullable AccessKeyword accessKeyword; @@ -77,6 +77,16 @@ public class NamingManager { return ensureValidName(paramName); } + public String paramName(TypeName type) { + final String paramName; + if (type.isPrimitive()) { + paramName = this.lowerCamelName; + } else { + paramName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, type instanceof ClassName className ? className.simpleName() : type.toString()); + } + return ensureValidName(paramName); + } + public static String ensureValidName(String name) { if (!SourceVersion.isIdentifier(name) || SourceVersion.isKeyword(name)) { return "_" + name; diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/SourceCodecs.java b/paper-generator/src/main/java/io/papermc/generator/utils/SourceCodecs.java new file mode 100644 index 0000000000..307bb4cc69 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/utils/SourceCodecs.java @@ -0,0 +1,140 @@ +package io.papermc.generator.utils; + +import com.google.common.reflect.TypeToken; +import com.mojang.datafixers.util.Either; +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.DynamicOps; +import com.squareup.javapoet.ClassName; +import io.papermc.typewriter.ClassNamed; +import java.util.Optional; +import java.util.function.Predicate; +import javax.lang.model.SourceVersion; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderGetter; +import net.minecraft.core.Registry; +import net.minecraft.resources.RegistryFixedCodec; +import net.minecraft.resources.RegistryOps; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; + +public final class SourceCodecs { + + private SourceCodecs() { + } + + public static final Codec IDENTIFIER = Codec.STRING.validate(name -> { + return SourceVersion.isIdentifier(name) && !SourceVersion.isKeyword(name) ? DataResult.success(name) : DataResult.error(() -> "Invalid identifier: '%s'".formatted(name)); + }); + + public static final Codec QUALIFIED_NAME = Codec.STRING.validate(name -> { + return SourceVersion.isName(name) ? DataResult.success(name) : DataResult.error(() -> "Invalid qualified name: '%s'".formatted(name)); + }); + + private static final Codec BINARY_NAME = Codec.STRING.validate(name -> { + return SourceVersion.isName(name.replace('$', '.')) ? DataResult.success(name) : DataResult.error(() -> "Invalid binary name: '%s'".formatted(name)); + }); + + public static Codec fieldNameCodec(Class fieldHolder, Predicate checker) { + return IDENTIFIER.comapFlatMap(name -> { + if (!checker.test(name)) { + return DataResult.error(() -> "Unknown field '%s' in %s".formatted(name, fieldHolder.getSimpleName())); + } + + return DataResult.success(name); + }, name -> name); + } + + public static Codec fieldCodec(Class fieldHolder, Predicate checker) { + String className = fieldHolder.getSimpleName(); + return QUALIFIED_NAME.comapFlatMap(name -> { + if (!name.startsWith(className + ".")) { + return DataResult.error(() -> "Invalid field '%s', field must belong to %s".formatted(name, className)); + } + + String fieldName = name.substring(className.length() + 1); + if (!checker.test(fieldName)) { + return DataResult.error(() -> "Unknown field '%s' in %s".formatted(fieldName, className)); + } + + return DataResult.success(name.substring(className.length() + 1)); + }, fieldName -> String.join(".", className, fieldName)); + } + + public static final Codec> CLASS = BINARY_NAME.comapFlatMap(name -> { + try { + return DataResult.success(Class.forName(name)); + } catch (ClassNotFoundException e) { + return DataResult.error(() -> "Class not found: %s".formatted(e.getMessage())); + } + }, Class::getName); + + public static Codec> classCodec(Class baseClass) { + return CLASS.comapFlatMap(klass -> { + if (baseClass.isAssignableFrom(klass)) { + return DataResult.success((Class) klass); + } + return DataResult.error(() -> "Class constraint failed: %s doesn't extends %s".formatted(klass, baseClass)); + }, klass -> klass); + } + + public static Codec> classCodec(TypeToken baseClass) { + return CLASS.comapFlatMap(klass -> { + if (baseClass.isSupertypeOf(klass)) { + return DataResult.success((Class) klass); + } + return DataResult.error(() -> "Class constraint failed: %s doesn't extends %s".formatted(klass, baseClass)); + }, klass -> klass); + } + + public static final Codec CLASS_NAMED = BINARY_NAME.xmap(name -> { + int lastDotIndex = name.lastIndexOf('.'); + if (lastDotIndex != -1) { + return ClassNamed.of(name.substring(0, lastDotIndex), name.substring(lastDotIndex + 1)); + } + + return ClassNamed.of("", name); + }, ClassNamed::binaryName); + + public static final Codec CLASS_NAME = CLASS_NAMED.xmap( + io.papermc.generator.types.Types::typed, io.papermc.generator.rewriter.types.Types::typed + ); + + public static final Codec>> REGISTRY_KEY = ResourceLocation.CODEC.xmap(ResourceKey::createRegistryKey, ResourceKey::location); + + public static Codec, Holder>> elementOrTagCodec(ResourceKey> registryKey) { + return Codec.either(RegistryAwareTagKeyCodec.hashedCodec(registryKey), RegistryFixedCodec.create(registryKey)); + } + + private record RegistryAwareTagKeyCodec(Codec> delegate, ResourceKey> registryKey) implements Codec> { + + public static RegistryAwareTagKeyCodec hashedCodec(ResourceKey> registryKey) { + return new RegistryAwareTagKeyCodec<>(TagKey.hashedCodec(registryKey), registryKey); + } + + @Override + public DataResult, T>> decode(DynamicOps ops, T input) { + if (ops instanceof RegistryOps registryOps) { + Optional> getter = registryOps.getter(this.registryKey); + if (getter.isPresent()) { + return this.delegate.decode(ops, input).flatMap(pair -> { + TagKey result = pair.getFirst(); + if (getter.get().get(result).isPresent()) { + return DataResult.success(pair); + } + return DataResult.error(() -> "Missing tag: '%s' in registry '%s'".formatted(result.location(), result.registry().location())); + }); + } + } + + return DataResult.error(() -> "Can't access registry " + this.registryKey); + } + + @Override + public DataResult encode(TagKey tagKey, DynamicOps ops, T input) { + return this.delegate.encode(tagKey, ops, input); + } + } +} diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/experimental/ExperimentalCollector.java b/paper-generator/src/main/java/io/papermc/generator/utils/experimental/ExperimentalCollector.java index 5e715d0383..d789732658 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/experimental/ExperimentalCollector.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/experimental/ExperimentalCollector.java @@ -119,8 +119,8 @@ public final class ExperimentalCollector { // without having at least one of the two values String tagDir = Registries.tagsDirPath(entry.key()); pack.listResources(PackType.SERVER_DATA, namespace, tagDir, (id, supplier) -> { - Formatting.formatTagKey(tagDir, id.getPath()).ifPresentOrElse(path -> output.accept(entry, path), () -> { - LOGGER.warn("Unable to parse the path: {}/{}/{}.json in the data-pack {} into a tag key", namespace, tagDir, id.getPath(), pack.packId()); + Formatting.findTagKeyPath(tagDir, id.getPath()).ifPresentOrElse(path -> output.accept(entry, path), () -> { + LOGGER.warn("Unable to find the tag key's path from the absolute path: {} in the data-pack '{}'", id.getPath(), pack.packId()); }); }); }); diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/experimental/FlagHolders.java b/paper-generator/src/main/java/io/papermc/generator/utils/experimental/FlagHolders.java index 1472ebb594..4c120538ed 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/experimental/FlagHolders.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/experimental/FlagHolders.java @@ -1,12 +1,6 @@ package io.papermc.generator.utils.experimental; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; -import net.minecraft.Util; -import net.minecraft.world.flag.FeatureFlag; import net.minecraft.world.flag.FeatureFlags; -import org.bukkit.MinecraftExperimental; import org.jspecify.annotations.NullMarked; @NullMarked @@ -15,10 +9,4 @@ public class FlagHolders { public static final SingleFlagHolder TRADE_REBALANCE = SingleFlagHolder.fromValue(FeatureFlags.TRADE_REBALANCE); public static final SingleFlagHolder REDSTONE_EXPERIMENTS = SingleFlagHolder.fromValue(FeatureFlags.REDSTONE_EXPERIMENTS); public static final SingleFlagHolder MINECART_IMPROVEMENTS = SingleFlagHolder.fromValue(FeatureFlags.MINECART_IMPROVEMENTS); - - static final Map ANNOTATION_EQUIVALENT = Util.make(new HashMap(), map -> { - map.put(TRADE_REBALANCE, MinecraftExperimental.Requires.TRADE_REBALANCE); - map.put(REDSTONE_EXPERIMENTS, MinecraftExperimental.Requires.REDSTONE_EXPERIMENTS); - map.put(MINECART_IMPROVEMENTS, MinecraftExperimental.Requires.MINECART_IMPROVEMENTS); - }).entrySet().stream().collect(Collectors.toMap(entry -> entry.getKey().flag(), Map.Entry::getValue)); } diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/experimental/SingleFlagHolder.java b/paper-generator/src/main/java/io/papermc/generator/utils/experimental/SingleFlagHolder.java index 497805310f..2e34923c4e 100644 --- a/paper-generator/src/main/java/io/papermc/generator/utils/experimental/SingleFlagHolder.java +++ b/paper-generator/src/main/java/io/papermc/generator/utils/experimental/SingleFlagHolder.java @@ -2,13 +2,13 @@ package io.papermc.generator.utils.experimental; import com.google.common.base.Preconditions; import com.google.common.collect.HashBiMap; +import io.papermc.generator.utils.Formatting; import java.util.HashMap; import java.util.Map; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.flag.FeatureFlag; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.flag.FeatureFlags; -import org.bukkit.MinecraftExperimental; import org.jspecify.annotations.NullMarked; @NullMarked @@ -39,11 +39,7 @@ public record SingleFlagHolder(FeatureFlag flag) implements FlagHolder { // todo })); } - public MinecraftExperimental.Requires asAnnotationMember() { - MinecraftExperimental.Requires annotationMember = FlagHolders.ANNOTATION_EQUIVALENT.get(this.flag); - if (annotationMember == null) { - throw new UnsupportedOperationException("Don't know that feature flag: " + FEATURE_FLAG_NAME.get(this.flag)); - } - return annotationMember; + public String asAnnotationMember() { + return Formatting.formatKeyAsField(FEATURE_FLAG_NAME.get(this.flag).getPath()); } } diff --git a/paper-generator/src/main/java/io/papermc/generator/utils/package-info.java b/paper-generator/src/main/java/io/papermc/generator/utils/package-info.java new file mode 100644 index 0000000000..e770418683 --- /dev/null +++ b/paper-generator/src/main/java/io/papermc/generator/utils/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package io.papermc.generator.utils; + +import org.jspecify.annotations.NullMarked; diff --git a/paper-generator/src/main/resources/data/block_state/ambiguous_names.json b/paper-generator/src/main/resources/data/block_state/ambiguous_names.json new file mode 100644 index 0000000000..d0075e6a0d --- /dev/null +++ b/paper-generator/src/main/resources/data/block_state/ambiguous_names.json @@ -0,0 +1,15 @@ +{ + "Tilt": [ + "CraftBigDripleaf" + ], + "Orientation": [ + "CraftCrafter", + "CraftJigsaw" + ], + "Half": [ + "CraftStair", + "CraftTrapDoor", + "CraftWeatheringCopperStair", + "CraftWeatheringCopperTrapDoor" + ] +} diff --git a/paper-generator/src/main/resources/data/block_state/enum_property_types.json b/paper-generator/src/main/resources/data/block_state/enum_property_types.json new file mode 100644 index 0000000000..17dcf7947d --- /dev/null +++ b/paper-generator/src/main/resources/data/block_state/enum_property_types.json @@ -0,0 +1,29 @@ +{ + "net.minecraft.core.Direction": "org.bukkit.block.BlockFace", + "net.minecraft.core.Direction$Axis": "org.bukkit.Axis", + "net.minecraft.core.FrontAndTop": "org.bukkit.block.Orientation", + "net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState": "org.bukkit.block.data.type.TrialSpawner$State", + "net.minecraft.world.level.block.entity.vault.VaultState": "org.bukkit.block.data.type.Vault$State", + "net.minecraft.world.level.block.state.properties.AttachFace": "org.bukkit.block.data.FaceAttachable$AttachedFace", + "net.minecraft.world.level.block.state.properties.BambooLeaves": "org.bukkit.block.data.type.Bamboo$Leaves", + "net.minecraft.world.level.block.state.properties.BedPart": "org.bukkit.block.data.type.Bed$Part", + "net.minecraft.world.level.block.state.properties.BellAttachType": "org.bukkit.block.data.type.Bell$Attachment", + "net.minecraft.world.level.block.state.properties.ChestType": "org.bukkit.block.data.type.Chest$Type", + "net.minecraft.world.level.block.state.properties.ComparatorMode": "org.bukkit.block.data.type.Comparator$Mode", + "net.minecraft.world.level.block.state.properties.CreakingHeartState": "org.bukkit.block.data.type.CreakingHeart$State", + "net.minecraft.world.level.block.state.properties.DoorHingeSide": "org.bukkit.block.data.type.Door$Hinge", + "net.minecraft.world.level.block.state.properties.DoubleBlockHalf": "org.bukkit.block.data.Bisected$Half", + "net.minecraft.world.level.block.state.properties.DripstoneThickness": "org.bukkit.block.data.type.PointedDripstone$Thickness", + "net.minecraft.world.level.block.state.properties.Half": "org.bukkit.block.data.Bisected$Half", + "net.minecraft.world.level.block.state.properties.NoteBlockInstrument": "org.bukkit.Instrument", + "net.minecraft.world.level.block.state.properties.PistonType": "org.bukkit.block.data.type.TechnicalPiston$Type", + "net.minecraft.world.level.block.state.properties.RailShape": "org.bukkit.block.data.Rail$Shape", + "net.minecraft.world.level.block.state.properties.RedstoneSide": "org.bukkit.block.data.type.RedstoneWire$Connection", + "net.minecraft.world.level.block.state.properties.SculkSensorPhase": "org.bukkit.block.data.type.SculkSensor$Phase", + "net.minecraft.world.level.block.state.properties.SlabType": "org.bukkit.block.data.type.Slab$Type", + "net.minecraft.world.level.block.state.properties.StairsShape": "org.bukkit.block.data.type.Stairs$Shape", + "net.minecraft.world.level.block.state.properties.StructureMode": "org.bukkit.block.data.type.StructureBlock$Mode", + "net.minecraft.world.level.block.state.properties.TestBlockMode": "org.bukkit.block.data.type.TestBlock$Mode", + "net.minecraft.world.level.block.state.properties.Tilt": "org.bukkit.block.data.type.BigDripleaf$Tilt", + "net.minecraft.world.level.block.state.properties.WallSide": "org.bukkit.block.data.type.Wall$Height" +} diff --git a/paper-generator/src/main/resources/data/block_state/predicates.json b/paper-generator/src/main/resources/data/block_state/predicates.json new file mode 100644 index 0000000000..994c327192 --- /dev/null +++ b/paper-generator/src/main/resources/data/block_state/predicates.json @@ -0,0 +1,135 @@ +{ + "org.bukkit.block.data.type.Furnace": { + "type": "instance_of", + "value": "net.minecraft.world.level.block.AbstractFurnaceBlock" + }, + "org.bukkit.block.data.type.Dripleaf": { + "type": "is_class", + "value": "net.minecraft.world.level.block.BigDripleafStemBlock" + }, + "org.bukkit.block.data.type.Fence": { + "type": "is_class", + "value": "net.minecraft.world.level.block.IronBarsBlock" + }, + "org.bukkit.block.data.type.ResinClump": { + "type": "is_class", + "value": "net.minecraft.world.level.block.MultifaceBlock" + }, + "org.bukkit.block.data.type.Switch": [ + { + "type": "is_class", + "value": "net.minecraft.world.level.block.LeverBlock" + }, + { + "type": "is_class", + "value": "net.minecraft.world.level.block.ButtonBlock" + } + ], + "org.bukkit.block.data.type.RedstoneRail": { + "type": "instance_of", + "value": "net.minecraft.world.level.block.BaseRailBlock", + "has_property": "BlockStateProperties.POWERED" + }, + "org.bukkit.block.data.Rail": { + "type": "instance_of", + "value": "net.minecraft.world.level.block.BaseRailBlock" + }, + "org.bukkit.block.data.type.Stairs": { + "type": "has_property", + "value": "BlockStateProperties.STAIRS_SHAPE" + }, + "org.bukkit.block.data.type.TechnicalPiston": { + "type": "has_property", + "value": "BlockStateProperties.PISTON_TYPE" + }, + "org.bukkit.block.data.FaceAttachable": { + "type": "has_property", + "value": "BlockStateProperties.ATTACH_FACE" + }, + "org.bukkit.block.data.Orientable": { + "type": "has_property", + "value": [ + "BlockStateProperties.AXIS", + "BlockStateProperties.HORIZONTAL_AXIS" + ] + }, + "org.bukkit.block.data.Bisected": { + "type": "has_property", + "value": [ + "BlockStateProperties.DOUBLE_BLOCK_HALF", + "BlockStateProperties.HALF" + ] + }, + "org.bukkit.block.data.Brushable": { + "type": "has_property", + "value": "BlockStateProperties.DUSTED" + }, + "org.bukkit.block.data.Hangable": { + "type": "has_property", + "value": "BlockStateProperties.HANGING" + }, + "org.bukkit.block.data.Hatchable": { + "type": "has_property", + "value": "BlockStateProperties.HATCH" + }, + "org.bukkit.block.data.Directional": { + "type": "has_property", + "value": [ + "BlockStateProperties.HORIZONTAL_FACING", + "BlockStateProperties.FACING" + ] + }, + "org.bukkit.block.data.Lightable": { + "type": "has_property", + "value": "BlockStateProperties.LIT" + }, + "org.bukkit.block.data.Openable": { + "type": "has_property", + "value": "BlockStateProperties.OPEN" + }, + "org.bukkit.block.data.AnaloguePowerable": { + "type": "has_property", + "value": "BlockStateProperties.POWER" + }, + "org.bukkit.block.data.Powerable": { + "type": "has_property", + "value": "BlockStateProperties.POWERED" + }, + "org.bukkit.block.data.Rotatable": { + "type": "has_property", + "value": "BlockStateProperties.ROTATION_16" + }, + "org.bukkit.block.data.Segmentable": { + "type": "has_property", + "value": "BlockStateProperties.SEGMENT_AMOUNT" + }, + "org.bukkit.block.data.Snowable": { + "type": "has_property", + "value": "BlockStateProperties.SNOWY" + }, + "org.bukkit.block.data.Waterlogged": { + "type": "has_property", + "value": "BlockStateProperties.WATERLOGGED" + }, + "org.bukkit.block.data.Ageable": { + "type": "has_property", + "value": "age" + }, + "org.bukkit.block.data.Levelled": { + "type": "has_property", + "value": "level" + }, + "org.bukkit.block.data.MultipleFacing": { + "type": "contains_property", + "value": [ + "BlockStateProperties.NORTH", + "BlockStateProperties.EAST", + "BlockStateProperties.SOUTH", + "BlockStateProperties.WEST", + "BlockStateProperties.UP", + "BlockStateProperties.DOWN" + ], + "count": 2, + "strategy": "at_least" + } +} diff --git a/paper-generator/src/main/resources/data/entity_class_names.json b/paper-generator/src/main/resources/data/entity_class_names.json new file mode 100644 index 0000000000..562cc06fff --- /dev/null +++ b/paper-generator/src/main/resources/data/entity_class_names.json @@ -0,0 +1,127 @@ +{ + "net.minecraft.world.entity.AgeableMob": "org.bukkit.entity.Ageable", + "net.minecraft.world.entity.GlowSquid": "org.bukkit.entity.GlowSquid", + "net.minecraft.world.entity.Mob": { + "name": "org.bukkit.entity.Mob", + "has_specifier": false + }, + "net.minecraft.world.entity.PathfinderMob": { + "name": "org.bukkit.entity.Creature", + "has_specifier": false + }, + "net.minecraft.world.entity.TamableAnimal": { + "name": "org.bukkit.entity.Tameable", + "has_specifier": false + }, + "net.minecraft.world.entity.ambient.AmbientCreature": "org.bukkit.entity.Ambient", + "net.minecraft.world.entity.ambient.Bat": "org.bukkit.entity.Bat", + "net.minecraft.world.entity.animal.AbstractCow": "org.bukkit.entity.AbstractCow", + "net.minecraft.world.entity.animal.AbstractFish": "org.bukkit.entity.Fish", + "net.minecraft.world.entity.animal.AbstractGolem": "org.bukkit.entity.Golem", + "net.minecraft.world.entity.animal.AbstractSchoolingFish": "io.papermc.paper.entity.SchoolableFish", + "net.minecraft.world.entity.animal.AgeableWaterCreature": "org.bukkit.entity.Squid", + "net.minecraft.world.entity.animal.Animal": { + "name": "org.bukkit.entity.Animals", + "has_specifier": false + }, + "net.minecraft.world.entity.animal.Bee": "org.bukkit.entity.Bee", + "net.minecraft.world.entity.animal.Cat": "org.bukkit.entity.Cat", + "net.minecraft.world.entity.animal.Chicken": "org.bukkit.entity.Chicken", + "net.minecraft.world.entity.animal.Cod": "org.bukkit.entity.Cod", + "net.minecraft.world.entity.animal.Cow": "org.bukkit.entity.Cow", + "net.minecraft.world.entity.animal.Dolphin": "org.bukkit.entity.Dolphin", + "net.minecraft.world.entity.animal.Fox": "org.bukkit.entity.Fox", + "net.minecraft.world.entity.animal.HappyGhast": "org.bukkit.entity.HappyGhast", + "net.minecraft.world.entity.animal.IronGolem": "org.bukkit.entity.IronGolem", + "net.minecraft.world.entity.animal.MushroomCow": "org.bukkit.entity.MushroomCow", + "net.minecraft.world.entity.animal.Ocelot": "org.bukkit.entity.Ocelot", + "net.minecraft.world.entity.animal.Panda": "org.bukkit.entity.Panda", + "net.minecraft.world.entity.animal.Parrot": "org.bukkit.entity.Parrot", + "net.minecraft.world.entity.animal.Pig": "org.bukkit.entity.Pig", + "net.minecraft.world.entity.animal.PolarBear": "org.bukkit.entity.PolarBear", + "net.minecraft.world.entity.animal.Pufferfish": { + "name": "org.bukkit.entity.PufferFish", + "has_specifier": false + }, + "net.minecraft.world.entity.animal.Rabbit": "org.bukkit.entity.Rabbit", + "net.minecraft.world.entity.animal.Salmon": "org.bukkit.entity.Salmon", + "net.minecraft.world.entity.animal.ShoulderRidingEntity": "org.bukkit.entity.Parrot", + "net.minecraft.world.entity.animal.SnowGolem": "org.bukkit.entity.Snowman", + "net.minecraft.world.entity.animal.Squid": "org.bukkit.entity.Squid", + "net.minecraft.world.entity.animal.TropicalFish": "org.bukkit.entity.TropicalFish", + "net.minecraft.world.entity.animal.Turtle": "org.bukkit.entity.Turtle", + "net.minecraft.world.entity.animal.WaterAnimal": "org.bukkit.entity.WaterMob", + "net.minecraft.world.entity.animal.allay.Allay": "org.bukkit.entity.Allay", + "net.minecraft.world.entity.animal.armadillo.Armadillo": "org.bukkit.entity.Armadillo", + "net.minecraft.world.entity.animal.axolotl.Axolotl": "org.bukkit.entity.Axolotl", + "net.minecraft.world.entity.animal.camel.Camel": "org.bukkit.entity.Camel", + "net.minecraft.world.entity.animal.frog.Frog": "org.bukkit.entity.Frog", + "net.minecraft.world.entity.animal.frog.Tadpole": "org.bukkit.entity.Tadpole", + "net.minecraft.world.entity.animal.goat.Goat": "org.bukkit.entity.Goat", + "net.minecraft.world.entity.animal.horse.AbstractChestedHorse": "org.bukkit.entity.ChestedHorse", + "net.minecraft.world.entity.animal.horse.AbstractHorse": "org.bukkit.entity.AbstractHorse", + "net.minecraft.world.entity.animal.horse.Donkey": "org.bukkit.entity.Donkey", + "net.minecraft.world.entity.animal.horse.Horse": "org.bukkit.entity.Horse", + "net.minecraft.world.entity.animal.horse.Llama": "org.bukkit.entity.Llama", + "net.minecraft.world.entity.animal.horse.Mule": "org.bukkit.entity.Mule", + "net.minecraft.world.entity.animal.horse.SkeletonHorse": "org.bukkit.entity.SkeletonHorse", + "net.minecraft.world.entity.animal.horse.TraderLlama": "org.bukkit.entity.TraderLlama", + "net.minecraft.world.entity.animal.horse.ZombieHorse": "org.bukkit.entity.ZombieHorse", + "net.minecraft.world.entity.animal.sheep.Sheep": "org.bukkit.entity.Sheep", + "net.minecraft.world.entity.animal.sniffer.Sniffer": "org.bukkit.entity.Sniffer", + "net.minecraft.world.entity.animal.wolf.Wolf": "org.bukkit.entity.Wolf", + "net.minecraft.world.entity.boss.enderdragon.EnderDragon": "org.bukkit.entity.EnderDragon", + "net.minecraft.world.entity.boss.wither.WitherBoss": "org.bukkit.entity.Wither", + "net.minecraft.world.entity.monster.AbstractIllager": "org.bukkit.entity.Illager", + "net.minecraft.world.entity.monster.AbstractSkeleton": "org.bukkit.entity.AbstractSkeleton", + "net.minecraft.world.entity.monster.Blaze": "org.bukkit.entity.Blaze", + "net.minecraft.world.entity.monster.Bogged": "org.bukkit.entity.Bogged", + "net.minecraft.world.entity.monster.CaveSpider": "org.bukkit.entity.CaveSpider", + "net.minecraft.world.entity.monster.Creeper": "org.bukkit.entity.Creeper", + "net.minecraft.world.entity.monster.Drowned": "org.bukkit.entity.Drowned", + "net.minecraft.world.entity.monster.ElderGuardian": "org.bukkit.entity.ElderGuardian", + "net.minecraft.world.entity.monster.EnderMan": "org.bukkit.entity.Enderman", + "net.minecraft.world.entity.monster.Endermite": "org.bukkit.entity.Endermite", + "net.minecraft.world.entity.monster.Evoker": "org.bukkit.entity.Evoker", + "net.minecraft.world.entity.monster.Ghast": "org.bukkit.entity.Ghast", + "net.minecraft.world.entity.monster.Giant": "org.bukkit.entity.Giant", + "net.minecraft.world.entity.monster.Guardian": "org.bukkit.entity.Guardian", + "net.minecraft.world.entity.monster.Husk": "org.bukkit.entity.Husk", + "net.minecraft.world.entity.monster.Illusioner": "org.bukkit.entity.Illusioner", + "net.minecraft.world.entity.monster.MagmaCube": "org.bukkit.entity.MagmaCube", + "net.minecraft.world.entity.monster.Monster": { + "name": "org.bukkit.entity.Monster", + "has_specifier": false + }, + "net.minecraft.world.entity.monster.PatrollingMonster": "org.bukkit.entity.Raider", + "net.minecraft.world.entity.monster.Phantom": "org.bukkit.entity.Phantom", + "net.minecraft.world.entity.monster.Pillager": "org.bukkit.entity.Pillager", + "net.minecraft.world.entity.monster.Ravager": "org.bukkit.entity.Ravager", + "net.minecraft.world.entity.monster.Shulker": "org.bukkit.entity.Shulker", + "net.minecraft.world.entity.monster.Silverfish": "org.bukkit.entity.Silverfish", + "net.minecraft.world.entity.monster.Skeleton": "org.bukkit.entity.Skeleton", + "net.minecraft.world.entity.monster.Slime": "org.bukkit.entity.Slime", + "net.minecraft.world.entity.monster.SpellcasterIllager": "org.bukkit.entity.Spellcaster", + "net.minecraft.world.entity.monster.Spider": "org.bukkit.entity.Spider", + "net.minecraft.world.entity.monster.Stray": "org.bukkit.entity.Stray", + "net.minecraft.world.entity.monster.Strider": "org.bukkit.entity.Strider", + "net.minecraft.world.entity.monster.Vex": "org.bukkit.entity.Vex", + "net.minecraft.world.entity.monster.Vindicator": "org.bukkit.entity.Vindicator", + "net.minecraft.world.entity.monster.Witch": "org.bukkit.entity.Witch", + "net.minecraft.world.entity.monster.WitherSkeleton": "org.bukkit.entity.WitherSkeleton", + "net.minecraft.world.entity.monster.Zoglin": "org.bukkit.entity.Zoglin", + "net.minecraft.world.entity.monster.Zombie": "org.bukkit.entity.Zombie", + "net.minecraft.world.entity.monster.ZombieVillager": "org.bukkit.entity.ZombieVillager", + "net.minecraft.world.entity.monster.ZombifiedPiglin": "org.bukkit.entity.PigZombie", + "net.minecraft.world.entity.monster.breeze.Breeze": "org.bukkit.entity.Breeze", + "net.minecraft.world.entity.monster.creaking.Creaking": "org.bukkit.entity.Creaking", + "net.minecraft.world.entity.monster.hoglin.Hoglin": "org.bukkit.entity.Hoglin", + "net.minecraft.world.entity.monster.piglin.AbstractPiglin": "org.bukkit.entity.PiglinAbstract", + "net.minecraft.world.entity.monster.piglin.Piglin": "org.bukkit.entity.Piglin", + "net.minecraft.world.entity.monster.piglin.PiglinBrute": "org.bukkit.entity.PiglinBrute", + "net.minecraft.world.entity.monster.warden.Warden": "org.bukkit.entity.Warden", + "net.minecraft.world.entity.npc.AbstractVillager": "org.bukkit.entity.AbstractVillager", + "net.minecraft.world.entity.npc.Villager": "org.bukkit.entity.Villager", + "net.minecraft.world.entity.npc.WanderingTrader": "org.bukkit.entity.WanderingTrader", + "net.minecraft.world.entity.raid.Raider": "org.bukkit.entity.Raider" +} diff --git a/paper-generator/src/main/resources/data/entity_types.json b/paper-generator/src/main/resources/data/entity_types.json new file mode 100644 index 0000000000..e6f3c4fcd2 --- /dev/null +++ b/paper-generator/src/main/resources/data/entity_types.json @@ -0,0 +1,399 @@ +{ + "minecraft:acacia_boat": "org.bukkit.entity.boat.AcaciaBoat", + "minecraft:acacia_chest_boat": "org.bukkit.entity.boat.AcaciaChestBoat", + "minecraft:allay": "org.bukkit.entity.Allay", + "minecraft:area_effect_cloud": { + "api": "org.bukkit.entity.AreaEffectCloud", + "legacy_id": 3 + }, + "minecraft:armadillo": "org.bukkit.entity.Armadillo", + "minecraft:armor_stand": { + "api": "org.bukkit.entity.ArmorStand", + "legacy_id": 30 + }, + "minecraft:arrow": { + "api": "org.bukkit.entity.Arrow", + "legacy_id": 10 + }, + "minecraft:axolotl": "org.bukkit.entity.Axolotl", + "minecraft:bamboo_chest_raft": "org.bukkit.entity.boat.BambooChestRaft", + "minecraft:bamboo_raft": "org.bukkit.entity.boat.BambooRaft", + "minecraft:bat": { + "api": "org.bukkit.entity.Bat", + "legacy_id": 65 + }, + "minecraft:bee": "org.bukkit.entity.Bee", + "minecraft:birch_boat": "org.bukkit.entity.boat.BirchBoat", + "minecraft:birch_chest_boat": "org.bukkit.entity.boat.BirchChestBoat", + "minecraft:blaze": { + "api": "org.bukkit.entity.Blaze", + "legacy_id": 61 + }, + "minecraft:block_display": "org.bukkit.entity.BlockDisplay", + "minecraft:bogged": "org.bukkit.entity.Bogged", + "minecraft:breeze": "org.bukkit.entity.Breeze", + "minecraft:breeze_wind_charge": "org.bukkit.entity.BreezeWindCharge", + "minecraft:camel": "org.bukkit.entity.Camel", + "minecraft:cat": "org.bukkit.entity.Cat", + "minecraft:cave_spider": { + "api": "org.bukkit.entity.CaveSpider", + "legacy_id": 59 + }, + "minecraft:cherry_boat": "org.bukkit.entity.boat.CherryBoat", + "minecraft:cherry_chest_boat": "org.bukkit.entity.boat.CherryChestBoat", + "minecraft:chest_minecart": { + "api": "org.bukkit.entity.minecart.StorageMinecart", + "legacy_id": 43 + }, + "minecraft:chicken": { + "api": "org.bukkit.entity.Chicken", + "legacy_id": 93 + }, + "minecraft:cod": "org.bukkit.entity.Cod", + "minecraft:command_block_minecart": { + "api": "org.bukkit.entity.minecart.CommandMinecart", + "legacy_id": 40 + }, + "minecraft:cow": { + "api": "org.bukkit.entity.Cow", + "legacy_id": 92 + }, + "minecraft:creaking": "org.bukkit.entity.Creaking", + "minecraft:creeper": { + "api": "org.bukkit.entity.Creeper", + "legacy_id": 50 + }, + "minecraft:dark_oak_boat": "org.bukkit.entity.boat.DarkOakBoat", + "minecraft:dark_oak_chest_boat": "org.bukkit.entity.boat.DarkOakChestBoat", + "minecraft:dolphin": "org.bukkit.entity.Dolphin", + "minecraft:donkey": { + "api": "org.bukkit.entity.Donkey", + "legacy_id": 31 + }, + "minecraft:dragon_fireball": { + "api": "org.bukkit.entity.DragonFireball", + "legacy_id": 26 + }, + "minecraft:drowned": "org.bukkit.entity.Drowned", + "minecraft:egg": { + "api": "org.bukkit.entity.Egg", + "legacy_id": 7 + }, + "minecraft:elder_guardian": { + "api": "org.bukkit.entity.ElderGuardian", + "legacy_id": 4 + }, + "minecraft:end_crystal": { + "api": "org.bukkit.entity.EnderCrystal", + "legacy_id": 200 + }, + "minecraft:ender_dragon": { + "api": "org.bukkit.entity.EnderDragon", + "legacy_id": 63 + }, + "minecraft:ender_pearl": { + "api": "org.bukkit.entity.EnderPearl", + "legacy_id": 14 + }, + "minecraft:enderman": { + "api": "org.bukkit.entity.Enderman", + "legacy_id": 58 + }, + "minecraft:endermite": { + "api": "org.bukkit.entity.Endermite", + "legacy_id": 67 + }, + "minecraft:evoker": { + "api": "org.bukkit.entity.Evoker", + "legacy_id": 34 + }, + "minecraft:evoker_fangs": { + "api": "org.bukkit.entity.EvokerFangs", + "legacy_id": 33 + }, + "minecraft:experience_bottle": { + "api": "org.bukkit.entity.ThrownExpBottle", + "legacy_id": 17 + }, + "minecraft:experience_orb": { + "api": "org.bukkit.entity.ExperienceOrb", + "legacy_id": 2 + }, + "minecraft:eye_of_ender": { + "api": "org.bukkit.entity.EnderSignal", + "legacy_id": 15 + }, + "minecraft:falling_block": { + "api": "org.bukkit.entity.FallingBlock", + "legacy_id": 21 + }, + "minecraft:fireball": { + "api": "org.bukkit.entity.Fireball", + "legacy_id": 12 + }, + "minecraft:firework_rocket": { + "api": "org.bukkit.entity.Firework", + "legacy_id": 22 + }, + "minecraft:fishing_bobber": "org.bukkit.entity.FishHook", + "minecraft:fox": "org.bukkit.entity.Fox", + "minecraft:frog": "org.bukkit.entity.Frog", + "minecraft:furnace_minecart": { + "api": "org.bukkit.entity.minecart.PoweredMinecart", + "legacy_id": 44 + }, + "minecraft:ghast": { + "api": "org.bukkit.entity.Ghast", + "legacy_id": 56 + }, + "minecraft:giant": { + "api": "org.bukkit.entity.Giant", + "legacy_id": 53 + }, + "minecraft:glow_item_frame": "org.bukkit.entity.GlowItemFrame", + "minecraft:glow_squid": "org.bukkit.entity.GlowSquid", + "minecraft:goat": "org.bukkit.entity.Goat", + "minecraft:guardian": { + "api": "org.bukkit.entity.Guardian", + "legacy_id": 68 + }, + "minecraft:happy_ghast": "org.bukkit.entity.HappyGhast", + "minecraft:hoglin": "org.bukkit.entity.Hoglin", + "minecraft:hopper_minecart": { + "api": "org.bukkit.entity.minecart.HopperMinecart", + "legacy_id": 46 + }, + "minecraft:horse": { + "api": "org.bukkit.entity.Horse", + "legacy_id": 100 + }, + "minecraft:husk": { + "api": "org.bukkit.entity.Husk", + "legacy_id": 23 + }, + "minecraft:illusioner": { + "api": "org.bukkit.entity.Illusioner", + "legacy_id": 37 + }, + "minecraft:interaction": "org.bukkit.entity.Interaction", + "minecraft:iron_golem": { + "api": "org.bukkit.entity.IronGolem", + "legacy_id": 99 + }, + "minecraft:item": { + "api": "org.bukkit.entity.Item", + "legacy_id": 1 + }, + "minecraft:item_display": "org.bukkit.entity.ItemDisplay", + "minecraft:item_frame": { + "api": "org.bukkit.entity.ItemFrame", + "legacy_id": 18 + }, + "minecraft:jungle_boat": "org.bukkit.entity.boat.JungleBoat", + "minecraft:jungle_chest_boat": "org.bukkit.entity.boat.JungleChestBoat", + "minecraft:leash_knot": { + "api": "org.bukkit.entity.LeashHitch", + "legacy_id": 8 + }, + "minecraft:lightning_bolt": "org.bukkit.entity.LightningStrike", + "minecraft:lingering_potion": "org.bukkit.entity.LingeringPotion", + "minecraft:llama": { + "api": "org.bukkit.entity.Llama", + "legacy_id": 103 + }, + "minecraft:llama_spit": { + "api": "org.bukkit.entity.LlamaSpit", + "legacy_id": 104 + }, + "minecraft:magma_cube": { + "api": "org.bukkit.entity.MagmaCube", + "legacy_id": 62 + }, + "minecraft:mangrove_boat": "org.bukkit.entity.boat.MangroveBoat", + "minecraft:mangrove_chest_boat": "org.bukkit.entity.boat.MangroveChestBoat", + "minecraft:marker": "org.bukkit.entity.Marker", + "minecraft:minecart": { + "api": "org.bukkit.entity.minecart.RideableMinecart", + "legacy_id": 42 + }, + "minecraft:mooshroom": { + "api": "org.bukkit.entity.MushroomCow", + "legacy_id": 96 + }, + "minecraft:mule": { + "api": "org.bukkit.entity.Mule", + "legacy_id": 32 + }, + "minecraft:oak_boat": "org.bukkit.entity.boat.OakBoat", + "minecraft:oak_chest_boat": "org.bukkit.entity.boat.OakChestBoat", + "minecraft:ocelot": { + "api": "org.bukkit.entity.Ocelot", + "legacy_id": 98 + }, + "minecraft:ominous_item_spawner": "org.bukkit.entity.OminousItemSpawner", + "minecraft:painting": { + "api": "org.bukkit.entity.Painting", + "legacy_id": 9 + }, + "minecraft:pale_oak_boat": "org.bukkit.entity.boat.PaleOakBoat", + "minecraft:pale_oak_chest_boat": "org.bukkit.entity.boat.PaleOakChestBoat", + "minecraft:panda": "org.bukkit.entity.Panda", + "minecraft:parrot": { + "api": "org.bukkit.entity.Parrot", + "legacy_id": 105 + }, + "minecraft:phantom": "org.bukkit.entity.Phantom", + "minecraft:pig": { + "api": "org.bukkit.entity.Pig", + "legacy_id": 90 + }, + "minecraft:piglin": "org.bukkit.entity.Piglin", + "minecraft:piglin_brute": "org.bukkit.entity.PiglinBrute", + "minecraft:pillager": "org.bukkit.entity.Pillager", + "minecraft:player": "org.bukkit.entity.Player", + "minecraft:polar_bear": { + "api": "org.bukkit.entity.PolarBear", + "legacy_id": 102 + }, + "minecraft:pufferfish": "org.bukkit.entity.PufferFish", + "minecraft:rabbit": { + "api": "org.bukkit.entity.Rabbit", + "legacy_id": 101 + }, + "minecraft:ravager": "org.bukkit.entity.Ravager", + "minecraft:salmon": "org.bukkit.entity.Salmon", + "minecraft:sheep": { + "api": "org.bukkit.entity.Sheep", + "legacy_id": 91 + }, + "minecraft:shulker": { + "api": "org.bukkit.entity.Shulker", + "legacy_id": 69 + }, + "minecraft:shulker_bullet": { + "api": "org.bukkit.entity.ShulkerBullet", + "legacy_id": 25 + }, + "minecraft:silverfish": { + "api": "org.bukkit.entity.Silverfish", + "legacy_id": 60 + }, + "minecraft:skeleton": { + "api": "org.bukkit.entity.Skeleton", + "legacy_id": 51 + }, + "minecraft:skeleton_horse": { + "api": "org.bukkit.entity.SkeletonHorse", + "legacy_id": 28 + }, + "minecraft:slime": { + "api": "org.bukkit.entity.Slime", + "legacy_id": 55 + }, + "minecraft:small_fireball": { + "api": "org.bukkit.entity.SmallFireball", + "legacy_id": 13 + }, + "minecraft:sniffer": "org.bukkit.entity.Sniffer", + "minecraft:snow_golem": { + "api": "org.bukkit.entity.Snowman", + "legacy_id": 97 + }, + "minecraft:snowball": { + "api": "org.bukkit.entity.Snowball", + "legacy_id": 11 + }, + "minecraft:spawner_minecart": { + "api": "org.bukkit.entity.minecart.SpawnerMinecart", + "legacy_id": 47 + }, + "minecraft:spectral_arrow": { + "api": "org.bukkit.entity.SpectralArrow", + "legacy_id": 24 + }, + "minecraft:spider": { + "api": "org.bukkit.entity.Spider", + "legacy_id": 52 + }, + "minecraft:splash_potion": { + "api": "org.bukkit.entity.SplashPotion", + "legacy_id": 16 + }, + "minecraft:spruce_boat": "org.bukkit.entity.boat.SpruceBoat", + "minecraft:spruce_chest_boat": "org.bukkit.entity.boat.SpruceChestBoat", + "minecraft:squid": { + "api": "org.bukkit.entity.Squid", + "legacy_id": 94 + }, + "minecraft:stray": { + "api": "org.bukkit.entity.Stray", + "legacy_id": 6 + }, + "minecraft:strider": "org.bukkit.entity.Strider", + "minecraft:tadpole": "org.bukkit.entity.Tadpole", + "minecraft:text_display": "org.bukkit.entity.TextDisplay", + "minecraft:tnt": { + "api": "org.bukkit.entity.TNTPrimed", + "legacy_id": 20 + }, + "minecraft:tnt_minecart": { + "api": "org.bukkit.entity.minecart.ExplosiveMinecart", + "legacy_id": 45 + }, + "minecraft:trader_llama": "org.bukkit.entity.TraderLlama", + "minecraft:trident": "org.bukkit.entity.Trident", + "minecraft:tropical_fish": "org.bukkit.entity.TropicalFish", + "minecraft:turtle": "org.bukkit.entity.Turtle", + "minecraft:vex": { + "api": "org.bukkit.entity.Vex", + "legacy_id": 35 + }, + "minecraft:villager": { + "api": "org.bukkit.entity.Villager", + "legacy_id": 120 + }, + "minecraft:vindicator": { + "api": "org.bukkit.entity.Vindicator", + "legacy_id": 36 + }, + "minecraft:wandering_trader": "org.bukkit.entity.WanderingTrader", + "minecraft:warden": "org.bukkit.entity.Warden", + "minecraft:wind_charge": "org.bukkit.entity.WindCharge", + "minecraft:witch": { + "api": "org.bukkit.entity.Witch", + "legacy_id": 66 + }, + "minecraft:wither": { + "api": "org.bukkit.entity.Wither", + "legacy_id": 64 + }, + "minecraft:wither_skeleton": { + "api": "org.bukkit.entity.WitherSkeleton", + "legacy_id": 5 + }, + "minecraft:wither_skull": { + "api": "org.bukkit.entity.WitherSkull", + "legacy_id": 19 + }, + "minecraft:wolf": { + "api": "org.bukkit.entity.Wolf", + "legacy_id": 95 + }, + "minecraft:zoglin": "org.bukkit.entity.Zoglin", + "minecraft:zombie": { + "api": "org.bukkit.entity.Zombie", + "legacy_id": 54 + }, + "minecraft:zombie_horse": { + "api": "org.bukkit.entity.ZombieHorse", + "legacy_id": 29 + }, + "minecraft:zombie_villager": { + "api": "org.bukkit.entity.ZombieVillager", + "legacy_id": 27 + }, + "minecraft:zombified_piglin": { + "api": "org.bukkit.entity.PigZombie", + "legacy_id": 57 + } +} diff --git a/paper-generator/src/main/resources/data/item_meta/bridge.json b/paper-generator/src/main/resources/data/item_meta/bridge.json new file mode 100644 index 0000000000..8db8a1ee1e --- /dev/null +++ b/paper-generator/src/main/resources/data/item_meta/bridge.json @@ -0,0 +1,106 @@ +{ + "org.bukkit.craftbukkit.inventory.CraftMetaArmor": { + "api": "org.bukkit.inventory.meta.ArmorMeta", + "field": "ARMOR_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaArmorStand": { + "api": "com.destroystokyo.paper.inventory.meta.ArmorStandMeta", + "field": "ARMOR_STAND_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaAxolotlBucket": { + "api": "org.bukkit.inventory.meta.AxolotlBucketMeta", + "field": "AXOLOTL_BUCKET_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaBanner": { + "api": "org.bukkit.inventory.meta.BannerMeta", + "field": "BANNER_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaBlockState": { + "api": "org.bukkit.inventory.meta.BlockStateMeta", + "field": "BLOCK_STATE_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaBook": { + "api": "org.bukkit.inventory.meta.BookMeta", + "field": "WRITABLE_BOOK_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaBookSigned": { + "api": "org.bukkit.inventory.meta.BookMeta", + "field": "SIGNED_BOOK_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaBundle": { + "api": "org.bukkit.inventory.meta.BundleMeta", + "field": "BUNDLE_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaCharge": { + "api": "org.bukkit.inventory.meta.FireworkEffectMeta", + "field": "CHARGE_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaColorableArmor": { + "api": "org.bukkit.inventory.meta.ColorableArmorMeta", + "field": "COLORABLE_ARMOR_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaCompass": { + "api": "org.bukkit.inventory.meta.CompassMeta", + "field": "COMPASS_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaCrossbow": { + "api": "org.bukkit.inventory.meta.CrossbowMeta", + "field": "CROSSBOW_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaEnchantedBook": { + "api": "org.bukkit.inventory.meta.EnchantmentStorageMeta", + "field": "ENCHANTED_BOOK_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaEntityTag": { + "api": "org.bukkit.inventory.meta.ItemMeta", + "field": "ENTITY_TAG_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaFirework": { + "api": "org.bukkit.inventory.meta.FireworkMeta", + "field": "FIREWORK_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaKnowledgeBook": { + "api": "org.bukkit.inventory.meta.KnowledgeBookMeta", + "field": "KNOWLEDGE_BOOK_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaLeatherArmor": { + "api": "org.bukkit.inventory.meta.LeatherArmorMeta", + "field": "LEATHER_ARMOR_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaMap": { + "api": "org.bukkit.inventory.meta.MapMeta", + "field": "MAP_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaMusicInstrument": { + "api": "org.bukkit.inventory.meta.MusicInstrumentMeta", + "field": "MUSIC_INSTRUMENT_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaOminousBottle": { + "api": "org.bukkit.inventory.meta.OminousBottleMeta", + "field": "OMINOUS_BOTTLE_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaPotion": { + "api": "org.bukkit.inventory.meta.PotionMeta", + "field": "POTION_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaShield": { + "api": "org.bukkit.inventory.meta.ShieldMeta", + "field": "SHIELD_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaSkull": { + "api": "org.bukkit.inventory.meta.SkullMeta", + "field": "SKULL_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaSpawnEgg": { + "api": "org.bukkit.inventory.meta.SpawnEggMeta", + "field": "SPAWN_EGG_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaSuspiciousStew": { + "api": "org.bukkit.inventory.meta.SuspiciousStewMeta", + "field": "SUSPICIOUS_STEW_META_DATA" + }, + "org.bukkit.craftbukkit.inventory.CraftMetaTropicalFishBucket": { + "api": "org.bukkit.inventory.meta.TropicalFishBucketMeta", + "field": "TROPICAL_FISH_BUCKET_META_DATA" + } +} diff --git a/paper-generator/src/main/resources/data/item_meta/predicates.json b/paper-generator/src/main/resources/data/item_meta/predicates.json new file mode 100644 index 0000000000..5f38ca6172 --- /dev/null +++ b/paper-generator/src/main/resources/data/item_meta/predicates.json @@ -0,0 +1,103 @@ +{ + "org.bukkit.craftbukkit.inventory.CraftMetaBookSigned": [ + "minecraft:written_book" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaBook": [ + "minecraft:writable_book" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaColorableArmor": [ + "minecraft:leather_boots", + "minecraft:leather_leggings", + "minecraft:leather_chestplate", + "minecraft:leather_helmet", + "minecraft:wolf_armor" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaArmor": [ + "#minecraft:foot_armor", + "#minecraft:leg_armor", + "#minecraft:chest_armor", + "#minecraft:head_armor" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaLeatherArmor": [ + "minecraft:leather_horse_armor" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaPotion": [ + "minecraft:potion", + "minecraft:splash_potion", + "minecraft:lingering_potion", + "minecraft:tipped_arrow" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaMap": [ + "minecraft:filled_map" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaFirework": [ + "minecraft:firework_rocket" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaCharge": [ + "minecraft:firework_star" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaEnchantedBook": [ + "minecraft:enchanted_book" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaSpawnEgg": [ + { + "type": "instance_of", + "value": "net.minecraft.world.item.SpawnEggItem" + } + ], + "org.bukkit.craftbukkit.inventory.CraftMetaArmorStand": [ + "minecraft:armor_stand" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaKnowledgeBook": [ + "minecraft:knowledge_book" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaSkull": [ + "#minecraft:skulls" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaBanner": [ + "#minecraft:banners" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaBlockState": [ + { + "type": "instance_of", + "value": "net.minecraft.world.level.block.EntityBlock", + "against_block": true + } + ], + "org.bukkit.craftbukkit.inventory.CraftMetaShield": [ + "minecraft:shield" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaTropicalFishBucket": [ + "minecraft:tropical_fish_bucket" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaAxolotlBucket": [ + "minecraft:axolotl_bucket" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaCrossbow": [ + "minecraft:crossbow" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaSuspiciousStew": [ + "minecraft:suspicious_stew" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaEntityTag": [ + "minecraft:cod_bucket", + "minecraft:pufferfish_bucket", + "minecraft:tadpole_bucket", + "minecraft:salmon_bucket", + "minecraft:item_frame", + "minecraft:glow_item_frame", + "minecraft:painting" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaCompass": [ + "minecraft:compass" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaBundle": [ + "#minecraft:bundles" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaMusicInstrument": [ + "minecraft:goat_horn" + ], + "org.bukkit.craftbukkit.inventory.CraftMetaOminousBottle": [ + "minecraft:ominous_bottle" + ] +} diff --git a/paper-generator/src/main/resources/data/registry/built_in.json b/paper-generator/src/main/resources/data/registry/built_in.json new file mode 100644 index 0000000000..23206074fd --- /dev/null +++ b/paper-generator/src/main/resources/data/registry/built_in.json @@ -0,0 +1,136 @@ +{ + "minecraft:game_event": { + "api": { + "class": "org.bukkit.GameEvent", + "holder_class": { + "is_interface": false + } + }, + "impl": "org.bukkit.craftbukkit.CraftGameEvent", + "builder": { + "api": "io.papermc.paper.registry.data.GameEventRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperGameEventRegistryEntry$PaperBuilder" + } + }, + "minecraft:worldgen/structure_type": { + "api": { + "class": "org.bukkit.generator.structure.StructureType", + "holder_class": { + "is_interface": false + } + }, + "impl": "org.bukkit.craftbukkit.generator.structure.CraftStructureType" + }, + "minecraft:mob_effect": { + "api": { + "class": "org.bukkit.potion.PotionEffectType", + "holder_class": { + "is_interface": false + } + }, + "impl": "org.bukkit.craftbukkit.potion.CraftPotionEffectType" + }, + "minecraft:block": { + "api": { + "class": "org.bukkit.block.BlockType", + "key_class_name_relate": true + }, + "impl": "org.bukkit.craftbukkit.block.CraftBlockType" + }, + "minecraft:item": { + "api": { + "class": "org.bukkit.inventory.ItemType", + "key_class_name_relate": true + }, + "impl": "org.bukkit.craftbukkit.inventory.CraftItemType" + }, + "minecraft:villager_profession": { + "api": "org.bukkit.entity.Villager$Profession", + "impl": "org.bukkit.craftbukkit.entity.CraftVillager$CraftProfession" + }, + "minecraft:villager_type": { + "api": "org.bukkit.entity.Villager$Type", + "impl": "org.bukkit.craftbukkit.entity.CraftVillager$CraftType" + }, + "minecraft:map_decoration_type": { + "api": "org.bukkit.map.MapCursor$Type", + "impl": "org.bukkit.craftbukkit.map.CraftMapCursor$CraftType" + }, + "minecraft:menu": { + "api": "org.bukkit.inventory.MenuType", + "impl": "org.bukkit.craftbukkit.inventory.CraftMenuType" + }, + "minecraft:attribute": { + "api": "org.bukkit.attribute.Attribute", + "impl": "org.bukkit.craftbukkit.attribute.CraftAttribute", + "serialization_updater_field": "ATTRIBUTE_RENAME" + }, + "minecraft:fluid": { + "api": "org.bukkit.Fluid", + "impl": "org.bukkit.craftbukkit.CraftFluid" + }, + "minecraft:sound_event": { + "api": { + "class": "org.bukkit.Sound", + "registry_field": "SOUND_EVENT" + }, + "impl": "org.bukkit.craftbukkit.CraftSound", + "builder": { + "api": "io.papermc.paper.registry.data.SoundEventRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperSoundEventRegistryEntry$PaperBuilder", + "capability": "none" + }, + "allow_inline": true + }, + "minecraft:data_component_type": { + "api": { + "class": "io.papermc.paper.datacomponent.DataComponentType", + "holder_class": { + "name": "io.papermc.paper.datacomponent.DataComponentTypes", + "is_interface": false + } + }, + "impl": { + "class": "io.papermc.paper.datacomponent.PaperDataComponentType", + "instance_method": "of" + } + }, + "minecraft:entity_type": { + "api": { + "class": { + "name": "org.bukkit.entity.EntityType", + "legacy_enum": true + } + }, + "impl": "org.bukkit.craftbukkit.entity.CraftEntityType" + }, + "minecraft:particle_type": { + "api": { + "class": { + "name": "org.bukkit.Particle", + "legacy_enum": true + } + }, + "impl": "org.bukkit.craftbukkit.CraftParticle" + }, + "minecraft:potion": { + "api": { + "class": { + "name": "org.bukkit.potion.PotionType", + "legacy_enum": true + } + }, + "impl": "org.bukkit.craftbukkit.potion.CraftPotionType" + }, + "minecraft:memory_module_type": { + "api": { + "class": { + "name": "org.bukkit.entity.memory.MemoryKey" + }, + "holder_class": { + "is_interface": false + } + }, + "impl": "org.bukkit.craftbukkit.entity.memory.CraftMemoryKey" + } +} diff --git a/paper-generator/src/main/resources/data/registry/data_driven.json b/paper-generator/src/main/resources/data/registry/data_driven.json new file mode 100644 index 0000000000..c91e2394e6 --- /dev/null +++ b/paper-generator/src/main/resources/data/registry/data_driven.json @@ -0,0 +1,189 @@ +{ + "minecraft:worldgen/biome": { + "api": "org.bukkit.block.Biome", + "impl": { + "class": "org.bukkit.craftbukkit.block.CraftBiome", + "delayed": true + } + }, + "minecraft:worldgen/structure": { + "api": { + "class": "org.bukkit.generator.structure.Structure", + "holder_class": { + "is_interface": false + } + }, + "impl": { + "class": "org.bukkit.craftbukkit.generator.structure.CraftStructure", + "delayed": true + } + }, + "minecraft:trim_material": { + "api": "org.bukkit.inventory.meta.trim.TrimMaterial", + "impl": { + "class": "org.bukkit.craftbukkit.inventory.trim.CraftTrimMaterial", + "delayed": true + }, + "allow_inline": true + }, + "minecraft:trim_pattern": { + "api": "org.bukkit.inventory.meta.trim.TrimPattern", + "impl": { + "class": "org.bukkit.craftbukkit.inventory.trim.CraftTrimPattern", + "delayed": true + }, + "allow_inline": true + }, + "minecraft:damage_type": { + "api": "org.bukkit.damage.DamageType", + "impl": { + "class": "org.bukkit.craftbukkit.damage.CraftDamageType", + "delayed": true + }, + "builder": { + "api": "io.papermc.paper.registry.data.DamageTypeRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperDamageTypeRegistryEntry$PaperBuilder" + } + }, + "minecraft:wolf_variant": { + "api": "org.bukkit.entity.Wolf$Variant", + "impl": { + "class": "org.bukkit.craftbukkit.entity.CraftWolf$CraftVariant", + "delayed": true + }, + "builder": { + "api": "io.papermc.paper.registry.data.WolfVariantRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperWolfVariantRegistryEntry$PaperBuilder" + } + }, + "minecraft:wolf_sound_variant": { + "api": "org.bukkit.entity.Wolf$SoundVariant", + "impl": "org.bukkit.craftbukkit.entity.CraftWolf$CraftSoundVariant" + }, + "minecraft:enchantment": { + "api": { + "class": "org.bukkit.enchantments.Enchantment", + "holder_class": { + "is_interface": false + } + }, + "impl": { + "class": "org.bukkit.craftbukkit.enchantments.CraftEnchantment", + "delayed": true + }, + "builder": { + "api": "io.papermc.paper.registry.data.EnchantmentRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperEnchantmentRegistryEntry$PaperBuilder" + }, + "serialization_updater_field": "ENCHANTMENT_RENAME" + }, + "minecraft:jukebox_song": { + "api": "org.bukkit.JukeboxSong", + "impl": { + "class": "org.bukkit.craftbukkit.CraftJukeboxSong", + "delayed": true + }, + "builder": { + "api": "io.papermc.paper.registry.data.JukeboxSongRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperJukeboxSongRegistryEntry$PaperBuilder" + } + }, + "minecraft:banner_pattern": { + "api": "org.bukkit.block.banner.PatternType", + "impl": { + "class": "org.bukkit.craftbukkit.block.banner.CraftPatternType", + "delayed": true + }, + "builder": { + "api": "io.papermc.paper.registry.data.BannerPatternRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperBannerPatternRegistryEntry$PaperBuilder" + }, + "allow_inline": true + }, + "minecraft:painting_variant": { + "api": { + "class": "org.bukkit.Art", + "registry_field": "ART" + }, + "impl": { + "class": "org.bukkit.craftbukkit.CraftArt", + "delayed": true + }, + "builder": { + "api": "io.papermc.paper.registry.data.PaintingVariantRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperPaintingVariantRegistryEntry$PaperBuilder" + } + }, + "minecraft:instrument": { + "api": { + "class": "org.bukkit.MusicInstrument", + "holder_class": { + "is_interface": false + } + }, + "impl": { + "class": "org.bukkit.craftbukkit.CraftMusicInstrument", + "delayed": true + }, + "builder": { + "api": "io.papermc.paper.registry.data.InstrumentRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperInstrumentRegistryEntry$PaperBuilder" + }, + "allow_inline": true + }, + "minecraft:cat_variant": { + "api": "org.bukkit.entity.Cat$Type", + "impl": { + "class": "org.bukkit.craftbukkit.entity.CraftCat$CraftType", + "delayed": true + }, + "builder": { + "api": "io.papermc.paper.registry.data.CatTypeRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperCatTypeRegistryEntry$PaperBuilder" + } + }, + "minecraft:frog_variant": { + "api": "org.bukkit.entity.Frog$Variant", + "impl": { + "class": "org.bukkit.craftbukkit.entity.CraftFrog$CraftVariant", + "delayed": true + }, + "builder": { + "api": "io.papermc.paper.registry.data.FrogVariantRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperFrogVariantRegistryEntry$PaperBuilder" + } + }, + "minecraft:chicken_variant": { + "api": "org.bukkit.entity.Chicken$Variant", + "impl": "org.bukkit.craftbukkit.entity.CraftChicken$CraftVariant", + "builder": { + "api": "io.papermc.paper.registry.data.ChickenVariantRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperChickenVariantRegistryEntry$PaperBuilder" + } + }, + "minecraft:cow_variant": { + "api": "org.bukkit.entity.Cow$Variant", + "impl": "org.bukkit.craftbukkit.entity.CraftCow$CraftVariant", + "builder": { + "api": "io.papermc.paper.registry.data.CowVariantRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperCowVariantRegistryEntry$PaperBuilder" + } + }, + "minecraft:pig_variant": { + "api": "org.bukkit.entity.Pig$Variant", + "impl": "org.bukkit.craftbukkit.entity.CraftPig$CraftVariant", + "builder": { + "api": "io.papermc.paper.registry.data.PigVariantRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.PaperPigVariantRegistryEntry$PaperBuilder" + } + }, + "minecraft:dialog": { + "api": "io.papermc.paper.dialog.Dialog", + "impl": "io.papermc.paper.dialog.PaperDialog", + "builder": { + "api": "io.papermc.paper.registry.data.dialog.DialogRegistryEntry$Builder", + "impl": "io.papermc.paper.registry.data.dialog.PaperDialogRegistryEntry$PaperBuilder" + }, + "allow_inline": true + } +} diff --git a/paper-generator/src/test/java/io/papermc/generator/BlockStatePropertyTest.java b/paper-generator/src/test/java/io/papermc/generator/BlockStatePropertyTest.java index 32b5b56163..0af735d9b6 100644 --- a/paper-generator/src/test/java/io/papermc/generator/BlockStatePropertyTest.java +++ b/paper-generator/src/test/java/io/papermc/generator/BlockStatePropertyTest.java @@ -1,55 +1,15 @@ package io.papermc.generator; -import io.papermc.generator.utils.BlockStateMapping; -import io.papermc.generator.utils.ClassHelper; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Collections; -import java.util.HashSet; -import java.util.IdentityHashMap; import java.util.List; import java.util.Map; -import java.util.Set; -import net.minecraft.SharedConstants; -import net.minecraft.server.Bootstrap; import net.minecraft.world.level.block.ChiseledBookShelfBlock; import net.minecraft.world.level.block.MossyCarpetBlock; import net.minecraft.world.level.block.PipeBlock; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; +import net.minecraft.world.level.block.WallBlock; import org.junit.jupiter.api.Test; -public class BlockStatePropertyTest { - - private static Set>> ENUM_PROPERTY_VALUES; - - @BeforeAll - public static void getAllProperties() { - // bootstrap - SharedConstants.tryDetectVersion(); - Bootstrap.bootStrap(); - Bootstrap.validate(); - - // get all properties - Set>> enumPropertyValues = Collections.newSetFromMap(new IdentityHashMap<>()); - try { - for (Field field : BlockStateProperties.class.getDeclaredFields()) { - if (ClassHelper.isStaticConstant(field, Modifier.PUBLIC)) { - if (!EnumProperty.class.isAssignableFrom(field.getType())) { - continue; - } - - enumPropertyValues.add(((EnumProperty) field.get(null)).getValueClass()); - } - } - ENUM_PROPERTY_VALUES = Collections.unmodifiableSet(enumPropertyValues); - } catch (ReflectiveOperationException ex) { - throw new RuntimeException(ex); - } - } +public class BlockStatePropertyTest extends BootstrapTest { @Test public void testReferences() throws NoSuchFieldException, IllegalAccessException { @@ -57,18 +17,7 @@ public class BlockStatePropertyTest { MethodHandles.Lookup lookup = MethodHandles.lookup(); lookup.findStaticVarHandle(ChiseledBookShelfBlock.class, "SLOT_OCCUPIED_PROPERTIES", List.class); lookup.findStaticVarHandle(PipeBlock.class, "PROPERTY_BY_DIRECTION", Map.class); - MethodHandles.privateLookupIn(MossyCarpetBlock.class, lookup).findStaticVarHandle(MossyCarpetBlock.class, "PROPERTY_BY_DIRECTION", Map.class); - } - - @Test - public void testBridge() { - Set missingApiEquivalents = new HashSet<>(); - for (Class> value : ENUM_PROPERTY_VALUES) { - if (!BlockStateMapping.ENUM_BRIDGE.containsKey(value)) { - missingApiEquivalents.add(value.getCanonicalName()); - } - } - - Assertions.assertTrue(missingApiEquivalents.isEmpty(), () -> "Missing some api equivalent in the block state mapping enum bridge (BlockStateMapping#ENUM_BRIDGE) : " + String.join(", ", missingApiEquivalents)); + lookup.findStaticVarHandle(WallBlock.class, "PROPERTY_BY_DIRECTION", Map.class); + lookup.findStaticVarHandle(MossyCarpetBlock.class, "PROPERTY_BY_DIRECTION", Map.class); } } diff --git a/paper-generator/src/test/java/io/papermc/generator/BootstrapTest.java b/paper-generator/src/test/java/io/papermc/generator/BootstrapTest.java new file mode 100644 index 0000000000..0b4f53bbb4 --- /dev/null +++ b/paper-generator/src/test/java/io/papermc/generator/BootstrapTest.java @@ -0,0 +1,8 @@ +package io.papermc.generator; + +public abstract class BootstrapTest { + + static { + Main.bootStrap(true); + } +} diff --git a/paper-generator/src/test/java/io/papermc/generator/DataFileTest.java b/paper-generator/src/test/java/io/papermc/generator/DataFileTest.java new file mode 100644 index 0000000000..a32d8a6361 --- /dev/null +++ b/paper-generator/src/test/java/io/papermc/generator/DataFileTest.java @@ -0,0 +1,31 @@ +package io.papermc.generator; + +import io.papermc.generator.resources.DataFile; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.FlattenSliceResult; +import io.papermc.generator.resources.SliceResult; +import java.util.Collection; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertNull; + +public class DataFileTest extends BootstrapTest { + + public static Collection> files() { + return DataFileLoader.DATA_FILES_VIEW.values(); + } + + @ParameterizedTest + @MethodSource("files") + public void testFile(DataFile file) { + SliceResult result = file.slice(); + if (result.isEmpty()) { + return; + } + + FlattenSliceResult printedResult = file.print(result); + assertNull(printedResult.added(), () -> "Missing some data in " + file.path()); + assertNull(printedResult.removed(), () -> "Extra data found in " + file.path()); + } +} diff --git a/paper-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java b/paper-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java deleted file mode 100644 index 0eed5bbf4a..0000000000 --- a/paper-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.papermc.generator; - -import io.github.classgraph.ClassGraph; -import io.github.classgraph.ScanResult; -import io.papermc.generator.types.goal.MobGoalNames; -import java.util.ArrayList; -import java.util.List; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.Mob; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class MobGoalConverterTest { - - @Test - public void testBukkitMap() { - final List> classes; - try (ScanResult scanResult = new ClassGraph().enableClassInfo().whitelistPackages(Entity.class.getPackageName()).scan()) { - classes = scanResult.getSubclasses(Mob.class.getName()).loadClasses(Mob.class); - } - - assertFalse(classes.isEmpty(), "There are supposed to be more than 0 mob classes!"); - - List missingClasses = new ArrayList<>(); - for (Class nmsClass : classes) { - if (!MobGoalNames.BUKKIT_BRIDGE.containsKey(nmsClass)) { - missingClasses.add(nmsClass.getCanonicalName()); - } - } - - assertTrue(missingClasses.isEmpty(), () -> "Missing some entity classes in the bukkit map: " + String.join(", ", missingClasses)); - } -} diff --git a/paper-generator/src/test/java/io/papermc/generator/RegistryMigrationTest.java b/paper-generator/src/test/java/io/papermc/generator/RegistryMigrationTest.java deleted file mode 100644 index 61a2648438..0000000000 --- a/paper-generator/src/test/java/io/papermc/generator/RegistryMigrationTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.papermc.generator; - -import io.papermc.generator.registry.RegistryEntries; -import io.papermc.generator.registry.RegistryEntry; -import java.util.HashSet; -import java.util.Set; -import net.minecraft.SharedConstants; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.Bootstrap; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -public class RegistryMigrationTest { - - @BeforeAll - public static void setup() { - SharedConstants.tryDetectVersion(); - Bootstrap.bootStrap(); - Bootstrap.validate(); - } - - @Test - public void testBuiltInToDataDriven() { - Set migratedRegistries = new HashSet<>(); - for (RegistryEntry entry : RegistryEntries.BUILT_IN) { - ResourceKey> key = entry.registryKey(); - if (!BuiltInRegistries.REGISTRY.containsKey(key.location())) { - migratedRegistries.add(key.toString()); - } - } - - Assertions.assertTrue(migratedRegistries.isEmpty(), () -> "Some registries have become data-driven: %s".formatted(String.join(", ", migratedRegistries))); - } - - @Test - public void testDataDrivenToBuiltIn() { // shouldn't really happen but just in case - Set migratedRegistries = new HashSet<>(); - for (RegistryEntry entry : RegistryEntries.DATA_DRIVEN) { - ResourceKey> key = entry.registryKey(); - if (BuiltInRegistries.REGISTRY.containsKey(key.location())) { - migratedRegistries.add(key.toString()); - } - } - - Assertions.assertTrue(migratedRegistries.isEmpty(), () -> "Some registries have become built-in: %s".formatted(String.join(", ", migratedRegistries))); - } -} diff --git a/paper-generator/src/test/java/io/papermc/generator/RoundtripCodecTest.java b/paper-generator/src/test/java/io/papermc/generator/RoundtripCodecTest.java new file mode 100644 index 0000000000..df74556783 --- /dev/null +++ b/paper-generator/src/test/java/io/papermc/generator/RoundtripCodecTest.java @@ -0,0 +1,253 @@ +package io.papermc.generator; + +import com.google.common.collect.Multimap; +import com.google.common.collect.MultimapBuilder; +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.JavaOps; +import com.mojang.serialization.JsonOps; +import io.papermc.generator.registry.RegistryEntry; +import io.papermc.generator.resources.DataFile; +import io.papermc.generator.resources.DataFileLoader; +import io.papermc.generator.resources.DataFiles; +import io.papermc.generator.resources.ParameterizedClass; +import io.papermc.generator.resources.data.EntityClassData; +import io.papermc.generator.resources.data.EntityTypeData; +import io.papermc.generator.resources.data.ItemMetaData; +import io.papermc.generator.resources.data.RegistryData; +import io.papermc.generator.resources.predicate.BlockPredicate; +import io.papermc.generator.resources.predicate.BlockPropertyPredicate; +import io.papermc.generator.resources.predicate.ItemPredicate; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.Random; +import java.util.Set; +import java.util.stream.Stream; +import net.minecraft.Util; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.ItemTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Skeleton; +import net.minecraft.world.entity.monster.Zombie; +import net.minecraft.world.item.BedItem; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.StandingAndWallBlockItem; +import net.minecraft.world.level.block.BaseRailBlock; +import net.minecraft.world.level.block.BellBlock; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.FlowerPotBlock; +import net.minecraft.world.level.block.VaultBlock; +import net.minecraft.world.level.block.entity.vault.VaultState; +import net.minecraft.world.level.block.state.properties.CreakingHeartState; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static io.papermc.generator.utils.BasePackage.BUKKIT; +import static io.papermc.generator.utils.BasePackage.CRAFT_BUKKIT; +import static io.papermc.generator.utils.BasePackage.PAPER; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class RoundtripCodecTest extends BootstrapTest { + + private static Multimap>, ?> values() { + Random random = new Random(); + RandomSource randomSource = RandomSource.create(); + RandomStringUtils randomStr = RandomStringUtils.insecure(); + return Util.make(MultimapBuilder.hashKeys().arrayListValues().build(), map -> { + put(map, DataFiles.BLOCK_STATE_AMBIGUOUS_NAMES, Map.of("Test", List.of("CraftA"))); + put(map, DataFiles.BLOCK_STATE_AMBIGUOUS_NAMES, Map.of("Test", List.of("CraftA", "CraftA"))); + put(map, DataFiles.BLOCK_STATE_AMBIGUOUS_NAMES, Map.of("Test", List.of("CraftA", "CraftB"))); + put(map, DataFiles.BLOCK_STATE_AMBIGUOUS_NAMES, Map.of(randomStr.nextAlphabetic(5), List.of(randomStr.nextAlphabetic(10)))); + + put(map, DataFiles.BLOCK_STATE_ENUM_PROPERTY_TYPES, Map.of(VaultState.class, BUKKIT.rootClass("Vault", "State"))); + put(map, DataFiles.BLOCK_STATE_ENUM_PROPERTY_TYPES, Map.of(CreakingHeartState.class, BUKKIT.rootClass("CreakingHeartState"))); + put(map, DataFiles.BLOCK_STATE_ENUM_PROPERTY_TYPES, Map.of(CreakingHeartState.class, BUKKIT.rootClass(randomStr.nextAlphabetic(5)))); + + put(map, DataFiles.BLOCK_STATE_PREDICATES, Map.of(BUKKIT.rootClassNamed("BlockData"), List.of( + new BlockPredicate.IsClassPredicate(VaultBlock.class), + new BlockPredicate.InstanceOfPredicate(FlowerPotBlock.class, List.of()), + new BlockPredicate.InstanceOfPredicate(BaseRailBlock.class, List.of( + new BlockPropertyPredicate.IsFieldPredicate("POWERED"), + new BlockPropertyPredicate.IsNamePredicate("hatch") + )), + new BlockPredicate.ContainsPropertyPredicate(List.of( + new BlockPropertyPredicate.IsFieldPredicate("POWERED"), + new BlockPropertyPredicate.IsNamePredicate("hatch") + ), 1, BlockPredicate.ContainsPropertyPredicate.Strategy.AT_LEAST), + new BlockPredicate.ContainsPropertyPredicate(List.of( + new BlockPropertyPredicate.IsFieldPredicate("DUSTED"), + new BlockPropertyPredicate.IsNamePredicate("age") + ), 2, BlockPredicate.ContainsPropertyPredicate.Strategy.AT_LEAST), + new BlockPredicate.ContainsPropertyPredicate(List.of( + new BlockPropertyPredicate.IsFieldPredicate("POWER"), + new BlockPropertyPredicate.IsNamePredicate("level") + ), 2, BlockPredicate.ContainsPropertyPredicate.Strategy.EXACT), + new BlockPredicate.ContainsPropertyPredicate(List.of( + new BlockPropertyPredicate.IsFieldPredicate("FACING"), + new BlockPropertyPredicate.IsNamePredicate("hatch"), + new BlockPropertyPredicate.IsNamePredicate("age") + ), random.nextInt(3) + 1, Util.getRandom(BlockPredicate.ContainsPropertyPredicate.Strategy.values(), randomSource)) + ))); + + put(map, DataFiles.ITEM_META_BRIDGE, Map.of( + CRAFT_BUKKIT.rootClassNamed("CraftSomethingMeta"), new ItemMetaData( + BUKKIT.rootClassNamed("SomethingMeta"), "SOMETHING_DATA" + ), + CRAFT_BUKKIT.rootClassNamed(randomStr.nextAlphabetic(10)), new ItemMetaData( + BUKKIT.rootClassNamed(randomStr.nextAlphabetic(5)), randomStr.nextAlphabetic(10).toUpperCase(Locale.ROOT) + ) + )); + + put(map, DataFiles.ITEM_META_PREDICATES, Map.of( + CRAFT_BUKKIT.rootClassNamed("CraftSomethingMeta"), List.of( + new ItemPredicate.InstanceOfPredicate(StandingAndWallBlockItem.class, false), + new ItemPredicate.InstanceOfPredicate(EntityBlock.class, true), + new ItemPredicate.IsClassPredicate(BedItem.class, false), + new ItemPredicate.IsClassPredicate(BellBlock.class, true), + new ItemPredicate.IsElementPredicate(Either.left(ItemTags.ANVIL)), + new ItemPredicate.IsElementPredicate(Either.right(BuiltInRegistries.ITEM.wrapAsHolder(Items.APPLE))), + new ItemPredicate.IsElementPredicate(Either.right(BuiltInRegistries.ITEM.getRandom(randomSource).orElseThrow())) + ) + )); + + put(map, DataFiles.registry(RegistryEntry.Type.BUILT_IN), Map.of( + Registries.GAME_EVENT, + new RegistryData( + new RegistryData.Api(BUKKIT.rootClassNamed("GameEvent")), + new RegistryData.Impl(CRAFT_BUKKIT.rootClassNamed("CraftGameEvent")), + Optional.empty(), + Optional.empty(), + false + ), + Registries.BLOCK_ENTITY_TYPE, + new RegistryData( + new RegistryData.Api( + new RegistryData.Api.Class( + BUKKIT.rootClassNamed("BlockEntityType"), + List.of(new ParameterizedClass(BUKKIT.rootClassNamed("SuperClass"))), + false + ), + Optional.of(new RegistryData.Api.HolderClass(BUKKIT.rootClassNamed("BlockEntityTypes"))), + true, + Optional.of("BLOCK_ENTITY_TYPE") + ), + new RegistryData.Impl(CRAFT_BUKKIT.rootClassNamed("CraftBlockEntityType"), "of", true), + Optional.of( + new RegistryData.Builder( + PAPER.rootClassNamed("BlockEntityTypeRegistryEntry", "Builder"), + PAPER.rootClassNamed("PaperBlockEntityTypeRegistryEntry", "PaperBuilder"), + List.of(), + RegistryData.Builder.RegisterCapability.WRITABLE + ) + ), + Optional.of("BLOCK_ENTITY_TYPE_RENAME"), + true + ), + Registries.ATTRIBUTE, + new RegistryData( + new RegistryData.Api( + new RegistryData.Api.Class( + BUKKIT.rootClassNamed("Attribute"), + List.of(new ParameterizedClass(BUKKIT.rootClassNamed("SuperClass"), + List.of( + new ParameterizedClass(BUKKIT.rootClassNamed("SuperClass2")) + ) + )), + random.nextBoolean() + ), + Optional.of(new RegistryData.Api.HolderClass( + Optional.of(BUKKIT.rootClassNamed("Attributes")), random.nextBoolean()) + ), + random.nextBoolean(), + Optional.of("ATTRIBUTE") + ), + new RegistryData.Impl(CRAFT_BUKKIT.rootClassNamed("CraftAttribute"), "of", random.nextBoolean()), + Optional.of( + new RegistryData.Builder( + PAPER.rootClassNamed("AttributeRegistryEntry", "Builder"), + PAPER.rootClassNamed("PaperAttributeRegistryEntry", "PaperBuilder"), + List.of(), + Util.getRandom(RegistryData.Builder.RegisterCapability.values(), randomSource) + ) + ), + Optional.of("ATTRIBUTE_RENAME"), + random.nextBoolean() + ) + )); + + put(map, DataFiles.registry(RegistryEntry.Type.DATA_DRIVEN), Map.of( + Registries.DATA_COMPONENT_PREDICATE_TYPE, + new RegistryData( + new RegistryData.Api(PAPER.rootClassNamed("DataComponentPredicate", "Type")), + new RegistryData.Impl(PAPER.rootClassNamed("CraftDataComponentPredicate", "CraftType")), + Optional.empty(), + Optional.empty(), + false + ) + )); + + put(map, DataFiles.ENTITY_TYPES, Map.of( + BuiltInRegistries.ENTITY_TYPE.getResourceKey(EntityType.HUSK).orElseThrow(), + new EntityTypeData(BUKKIT.rootClassNamed("Husk")) + )); + put(map, DataFiles.ENTITY_TYPES, Map.of( + BuiltInRegistries.ENTITY_TYPE.getResourceKey(EntityType.ZOGLIN).orElseThrow(), + new EntityTypeData(BUKKIT.rootClassNamed("Zoglin"), -1) + )); + put(map, DataFiles.ENTITY_TYPES, Map.of( + BuiltInRegistries.ENTITY_TYPE.getResourceKey(EntityType.END_CRYSTAL).orElseThrow(), + new EntityTypeData(BUKKIT.rootClassNamed("EndCrystal"), 5) + )); + put(map, DataFiles.ENTITY_TYPES, Map.of( + BuiltInRegistries.ENTITY_TYPE.getRandom(randomSource).orElseThrow().key(), + new EntityTypeData(BUKKIT.rootClassNamed(randomStr.nextAlphabetic(5)), randomSource.nextIntBetweenInclusive(-1, 100)) + )); + + put(map, DataFiles.ENTITY_CLASS_NAMES, Map.of( + Zombie.class, + new EntityClassData(BUKKIT.rootClass("Zombie")) + )); + put(map, DataFiles.ENTITY_CLASS_NAMES, Map.of( + Skeleton.class, + new EntityClassData(BUKKIT.rootClass("Skeleton"), true) + )); + }); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private static void put(Multimap map, ResourceKey> key, V value) { + map.put(key, value); + } + + public static Stream data() { + Set> ops = Set.of( + JavaOps.INSTANCE, + JsonOps.INSTANCE + ); + Multimap>, ?> values = values(); + + return DataFileLoader.DATA_FILES_VIEW.entrySet().stream() + .flatMap(entry -> ops.stream().flatMap(op -> + values.get(entry.getKey()).stream().map(v -> Arguments.of(entry.getValue().getRequiredOps(op), entry.getValue().codec(), v)))); + } + + @ParameterizedTest + @MethodSource("data") + public void testCodec(DynamicOps ops, Codec codec, V value) { + DataResult encoded = codec.encodeStart(ops, value); + DataResult decoded = encoded.flatMap(r -> codec.parse(ops, r)); + assertEquals(DataResult.success(value), decoded, "read(write(x)) == x"); + + DataResult reEncoded = decoded.flatMap(r -> codec.encodeStart(ops, r)); + assertEquals(encoded, reEncoded, "write(read(x)) == x"); + } +} diff --git a/paper-generator/wideners.at b/paper-generator/wideners.at index 9e582e37be..7fb9f735c3 100644 --- a/paper-generator/wideners.at +++ b/paper-generator/wideners.at @@ -1,5 +1,4 @@ public net/minecraft/world/level/material/MapColor MATERIAL_COLORS -public net/minecraft/world/level/block/state/properties/IntegerProperty min # for auto-marking experimental stuff public net/minecraft/core/RegistrySetBuilder entries diff --git a/paper-server/build.gradle.kts b/paper-server/build.gradle.kts index 1a994c714e..9d84e895b4 100644 --- a/paper-server/build.gradle.kts +++ b/paper-server/build.gradle.kts @@ -1,10 +1,7 @@ import io.papermc.fill.model.BuildChannel import io.papermc.paperweight.attribute.DevBundleOutput import io.papermc.paperweight.util.* -import io.papermc.paperweight.util.data.FileEntry -import paper.libs.com.google.gson.annotations.SerializedName import java.time.Instant -import kotlin.io.path.readText plugins { `java-library` @@ -113,10 +110,6 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { } val alsoShade: Configuration by configurations.creating -val runtimeConfiguration by configurations.consumable("runtimeConfiguration") { - attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) -} - // Configure mockito agent that is needed in newer java versions val mockitoAgent = configurations.register("mockitoAgent") abstract class MockitoAgentProvider : CommandLineArgumentProvider { @@ -135,7 +128,6 @@ dependencies { implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21 implementation("net.minecrell:terminalconsoleappender:1.3.0") implementation("net.kyori:adventure-text-serializer-ansi:4.23.0") // Keep in sync with adventureVersion from Paper-API build file - runtimeConfiguration(sourceSets.main.map { it.runtimeClasspath }) /* Required to add the missing Log4j2Plugins.dat file from log4j-core diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftButton.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftButton.java index 0b9541867f..1c9aa03288 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftButton.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftButton.java @@ -10,6 +10,7 @@ import net.minecraft.world.level.block.state.properties.AttachFace; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; import org.bukkit.block.BlockFace; +import org.bukkit.block.data.FaceAttachable; import org.bukkit.block.data.type.Switch; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -26,13 +27,12 @@ public class CraftButton extends CraftBlockData implements Switch { } @Override - public org.bukkit.block.data.FaceAttachable.AttachedFace getAttachedFace() { - return this.get(FACE, org.bukkit.block.data.FaceAttachable.AttachedFace.class); + public FaceAttachable.AttachedFace getAttachedFace() { + return this.get(FACE, FaceAttachable.AttachedFace.class); } @Override - public void setAttachedFace( - final org.bukkit.block.data.FaceAttachable.AttachedFace attachedFace) { + public void setAttachedFace(final FaceAttachable.AttachedFace attachedFace) { Preconditions.checkArgument(attachedFace != null, "attachedFace cannot be null!"); this.set(FACE, attachedFace); } diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftCalibratedSculkSensor.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftCalibratedSculkSensor.java index b222c9acbf..c3dc060207 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftCalibratedSculkSensor.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftCalibratedSculkSensor.java @@ -12,6 +12,7 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.level.block.state.properties.SculkSensorPhase; import org.bukkit.block.BlockFace; import org.bukkit.block.data.type.CalibratedSculkSensor; +import org.bukkit.block.data.type.SculkSensor; import org.bukkit.craftbukkit.block.data.CraftBlockData; @GeneratedFrom("1.21.7") @@ -61,12 +62,12 @@ public class CraftCalibratedSculkSensor extends CraftBlockData implements Calibr } @Override - public org.bukkit.block.data.type.SculkSensor.Phase getSculkSensorPhase() { - return this.get(PHASE, org.bukkit.block.data.type.SculkSensor.Phase.class); + public SculkSensor.Phase getSculkSensorPhase() { + return this.get(PHASE, SculkSensor.Phase.class); } @Override - public void setSculkSensorPhase(final org.bukkit.block.data.type.SculkSensor.Phase phase) { + public void setSculkSensorPhase(final SculkSensor.Phase phase) { Preconditions.checkArgument(phase != null, "phase cannot be null!"); this.set(PHASE, phase); } diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftDetectorRail.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftDetectorRail.java index c3103307c7..127e000876 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftDetectorRail.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftDetectorRail.java @@ -8,6 +8,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.RailShape; +import org.bukkit.block.data.Rail; import org.bukkit.block.data.type.RedstoneRail; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -34,20 +35,20 @@ public class CraftDetectorRail extends CraftBlockData implements RedstoneRail { } @Override - public org.bukkit.block.data.Rail.Shape getShape() { - return this.get(SHAPE, org.bukkit.block.data.Rail.Shape.class); + public Rail.Shape getShape() { + return this.get(SHAPE, Rail.Shape.class); } @Override - public void setShape(final org.bukkit.block.data.Rail.Shape shape) { + public void setShape(final Rail.Shape shape) { Preconditions.checkArgument(shape != null, "shape cannot be null!"); - Preconditions.checkArgument(shape != org.bukkit.block.data.Rail.Shape.NORTH_EAST && shape != org.bukkit.block.data.Rail.Shape.NORTH_WEST && shape != org.bukkit.block.data.Rail.Shape.SOUTH_EAST && shape != org.bukkit.block.data.Rail.Shape.SOUTH_WEST, "Invalid rail shape, only straight rail are allowed for this property!"); + Preconditions.checkArgument(shape != Rail.Shape.NORTH_EAST && shape != Rail.Shape.NORTH_WEST && shape != Rail.Shape.SOUTH_EAST && shape != Rail.Shape.SOUTH_WEST, "Invalid rail shape, only straight rail are allowed for this property!"); this.set(SHAPE, shape); } @Override - public Set getShapes() { - return this.getValues(SHAPE, org.bukkit.block.data.Rail.Shape.class); + public Set getShapes() { + return this.getValues(SHAPE, Rail.Shape.class); } @Override diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftDoor.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftDoor.java index 507c9c8642..254ad3a1eb 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftDoor.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftDoor.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.level.block.state.properties.EnumProperty; import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Bisected; import org.bukkit.block.data.type.Door; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -48,12 +49,12 @@ public class CraftDoor extends CraftBlockData implements Door { } @Override - public org.bukkit.block.data.Bisected.Half getHalf() { - return this.get(HALF, org.bukkit.block.data.Bisected.Half.class); + public Bisected.Half getHalf() { + return this.get(HALF, Bisected.Half.class); } @Override - public void setHalf(final org.bukkit.block.data.Bisected.Half half) { + public void setHalf(final Bisected.Half half) { Preconditions.checkArgument(half != null, "half cannot be null!"); this.set(HALF, half); } diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftGrindstone.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftGrindstone.java index 700fa814f8..3b4f40a792 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftGrindstone.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftGrindstone.java @@ -9,6 +9,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.AttachFace; import net.minecraft.world.level.block.state.properties.EnumProperty; import org.bukkit.block.BlockFace; +import org.bukkit.block.data.FaceAttachable; import org.bukkit.block.data.type.Grindstone; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -23,13 +24,12 @@ public class CraftGrindstone extends CraftBlockData implements Grindstone { } @Override - public org.bukkit.block.data.FaceAttachable.AttachedFace getAttachedFace() { - return this.get(FACE, org.bukkit.block.data.FaceAttachable.AttachedFace.class); + public FaceAttachable.AttachedFace getAttachedFace() { + return this.get(FACE, FaceAttachable.AttachedFace.class); } @Override - public void setAttachedFace( - final org.bukkit.block.data.FaceAttachable.AttachedFace attachedFace) { + public void setAttachedFace(final FaceAttachable.AttachedFace attachedFace) { Preconditions.checkArgument(attachedFace != null, "attachedFace cannot be null!"); this.set(FACE, attachedFace); } diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftLever.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftLever.java index b76186eaa5..9ec4641b59 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftLever.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftLever.java @@ -10,6 +10,7 @@ import net.minecraft.world.level.block.state.properties.AttachFace; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; import org.bukkit.block.BlockFace; +import org.bukkit.block.data.FaceAttachable; import org.bukkit.block.data.type.Switch; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -26,13 +27,12 @@ public class CraftLever extends CraftBlockData implements Switch { } @Override - public org.bukkit.block.data.FaceAttachable.AttachedFace getAttachedFace() { - return this.get(FACE, org.bukkit.block.data.FaceAttachable.AttachedFace.class); + public FaceAttachable.AttachedFace getAttachedFace() { + return this.get(FACE, FaceAttachable.AttachedFace.class); } @Override - public void setAttachedFace( - final org.bukkit.block.data.FaceAttachable.AttachedFace attachedFace) { + public void setAttachedFace(final FaceAttachable.AttachedFace attachedFace) { Preconditions.checkArgument(attachedFace != null, "attachedFace cannot be null!"); this.set(FACE, attachedFace); } diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftMossyCarpet.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftMossyCarpet.java index f7f842987d..81a9438165 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftMossyCarpet.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftMossyCarpet.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.WallSide; import org.bukkit.block.BlockFace; import org.bukkit.block.data.type.MossyCarpet; +import org.bukkit.block.data.type.Wall; import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -36,16 +37,15 @@ public class CraftMossyCarpet extends CraftBlockData implements MossyCarpet { } @Override - public org.bukkit.block.data.type.Wall.Height getHeight(final BlockFace blockFace) { + public Wall.Height getHeight(final BlockFace blockFace) { Preconditions.checkArgument(blockFace != null, "blockFace cannot be null!"); EnumProperty property = PROPERTY_BY_DIRECTION.get(blockFace); Preconditions.checkArgument(property != null, "Invalid blockFace, only %s are allowed!", PROPERTY_BY_DIRECTION.keySet().stream().map(Enum::name).collect(Collectors.joining(", "))); - return this.get(property, org.bukkit.block.data.type.Wall.Height.class); + return this.get(property, Wall.Height.class); } @Override - public void setHeight(final BlockFace blockFace, - final org.bukkit.block.data.type.Wall.Height height) { + public void setHeight(final BlockFace blockFace, final Wall.Height height) { Preconditions.checkArgument(blockFace != null, "blockFace cannot be null!"); Preconditions.checkArgument(height != null, "height cannot be null!"); EnumProperty property = PROPERTY_BY_DIRECTION.get(blockFace); diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPistonHead.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPistonHead.java index f36032d56a..bcd5c50f35 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPistonHead.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPistonHead.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.PistonType; import org.bukkit.block.BlockFace; import org.bukkit.block.data.type.PistonHead; +import org.bukkit.block.data.type.TechnicalPiston; import org.bukkit.craftbukkit.block.data.CraftBlockData; @GeneratedFrom("1.21.7") @@ -53,12 +54,12 @@ public class CraftPistonHead extends CraftBlockData implements PistonHead { } @Override - public org.bukkit.block.data.type.TechnicalPiston.Type getType() { - return this.get(TYPE, org.bukkit.block.data.type.TechnicalPiston.Type.class); + public TechnicalPiston.Type getType() { + return this.get(TYPE, TechnicalPiston.Type.class); } @Override - public void setType(final org.bukkit.block.data.type.TechnicalPiston.Type type) { + public void setType(final TechnicalPiston.Type type) { Preconditions.checkArgument(type != null, "type cannot be null!"); this.set(TYPE, type); } diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPitcherCrop.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPitcherCrop.java index 1483a2db9a..3ecc6365cb 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPitcherCrop.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPitcherCrop.java @@ -7,6 +7,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.IntegerProperty; +import org.bukkit.block.data.Bisected; import org.bukkit.block.data.type.PitcherCrop; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -36,12 +37,12 @@ public class CraftPitcherCrop extends CraftBlockData implements PitcherCrop { } @Override - public org.bukkit.block.data.Bisected.Half getHalf() { - return this.get(HALF, org.bukkit.block.data.Bisected.Half.class); + public Bisected.Half getHalf() { + return this.get(HALF, Bisected.Half.class); } @Override - public void setHalf(final org.bukkit.block.data.Bisected.Half half) { + public void setHalf(final Bisected.Half half) { Preconditions.checkArgument(half != null, "half cannot be null!"); this.set(HALF, half); } diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPoweredRail.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPoweredRail.java index 85913805db..66949117fa 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPoweredRail.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftPoweredRail.java @@ -8,6 +8,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.RailShape; +import org.bukkit.block.data.Rail; import org.bukkit.block.data.type.RedstoneRail; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -34,20 +35,20 @@ public class CraftPoweredRail extends CraftBlockData implements RedstoneRail { } @Override - public org.bukkit.block.data.Rail.Shape getShape() { - return this.get(SHAPE, org.bukkit.block.data.Rail.Shape.class); + public Rail.Shape getShape() { + return this.get(SHAPE, Rail.Shape.class); } @Override - public void setShape(final org.bukkit.block.data.Rail.Shape shape) { + public void setShape(final Rail.Shape shape) { Preconditions.checkArgument(shape != null, "shape cannot be null!"); - Preconditions.checkArgument(shape != org.bukkit.block.data.Rail.Shape.NORTH_EAST && shape != org.bukkit.block.data.Rail.Shape.NORTH_WEST && shape != org.bukkit.block.data.Rail.Shape.SOUTH_EAST && shape != org.bukkit.block.data.Rail.Shape.SOUTH_WEST, "Invalid rail shape, only straight rail are allowed for this property!"); + Preconditions.checkArgument(shape != Rail.Shape.NORTH_EAST && shape != Rail.Shape.NORTH_WEST && shape != Rail.Shape.SOUTH_EAST && shape != Rail.Shape.SOUTH_WEST, "Invalid rail shape, only straight rail are allowed for this property!"); this.set(SHAPE, shape); } @Override - public Set getShapes() { - return this.getValues(SHAPE, org.bukkit.block.data.Rail.Shape.class); + public Set getShapes() { + return this.getValues(SHAPE, Rail.Shape.class); } @Override diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftSmallDripleaf.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftSmallDripleaf.java index 12fa017488..153fd36fce 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftSmallDripleaf.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftSmallDripleaf.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.level.block.state.properties.EnumProperty; import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Bisected; import org.bukkit.block.data.type.SmallDripleaf; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -44,12 +45,12 @@ public class CraftSmallDripleaf extends CraftBlockData implements SmallDripleaf } @Override - public org.bukkit.block.data.Bisected.Half getHalf() { - return this.get(HALF, org.bukkit.block.data.Bisected.Half.class); + public Bisected.Half getHalf() { + return this.get(HALF, Bisected.Half.class); } @Override - public void setHalf(final org.bukkit.block.data.Bisected.Half half) { + public void setHalf(final Bisected.Half half) { Preconditions.checkArgument(half != null, "half cannot be null!"); this.set(HALF, half); } diff --git a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftWeatheringCopperDoor.java b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftWeatheringCopperDoor.java index f2b92e1647..0092d881a2 100644 --- a/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftWeatheringCopperDoor.java +++ b/paper-server/src/generated/java/org/bukkit/craftbukkit/block/impl/CraftWeatheringCopperDoor.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.level.block.state.properties.EnumProperty; import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Bisected; import org.bukkit.block.data.type.Door; import org.bukkit.craftbukkit.block.data.CraftBlockData; @@ -48,12 +49,12 @@ public class CraftWeatheringCopperDoor extends CraftBlockData implements Door { } @Override - public org.bukkit.block.data.Bisected.Half getHalf() { - return this.get(HALF, org.bukkit.block.data.Bisected.Half.class); + public Bisected.Half getHalf() { + return this.get(HALF, Bisected.Half.class); } @Override - public void setHalf(final org.bukkit.block.data.Bisected.Half half) { + public void setHalf(final Bisected.Half half) { Preconditions.checkArgument(half != null, "half cannot be null!"); this.set(HALF, half); } diff --git a/paper-server/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/paper-server/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java index e6ad63a56d..c03860492a 100644 --- a/paper-server/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java +++ b/paper-server/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java @@ -28,113 +28,113 @@ public class MobGoalHelper { // // Start generate - MobGoalHelper#BUKKIT_BRIDGE // @GeneratedFrom 1.21.7 - map.put(net.minecraft.world.entity.Mob.class, Mob.class); map.put(net.minecraft.world.entity.AgeableMob.class, Ageable.class); + map.put(net.minecraft.world.entity.GlowSquid.class, GlowSquid.class); + map.put(net.minecraft.world.entity.Mob.class, Mob.class); + map.put(net.minecraft.world.entity.PathfinderMob.class, Creature.class); + map.put(net.minecraft.world.entity.TamableAnimal.class, Tameable.class); map.put(net.minecraft.world.entity.ambient.AmbientCreature.class, Ambient.class); - map.put(net.minecraft.world.entity.animal.Animal.class, Animals.class); map.put(net.minecraft.world.entity.ambient.Bat.class, Bat.class); + map.put(net.minecraft.world.entity.animal.AbstractCow.class, AbstractCow.class); + map.put(net.minecraft.world.entity.animal.AbstractFish.class, Fish.class); + map.put(net.minecraft.world.entity.animal.AbstractGolem.class, Golem.class); + map.put(net.minecraft.world.entity.animal.AbstractSchoolingFish.class, SchoolableFish.class); + map.put(net.minecraft.world.entity.animal.AgeableWaterCreature.class, Squid.class); + map.put(net.minecraft.world.entity.animal.Animal.class, Animals.class); map.put(net.minecraft.world.entity.animal.Bee.class, Bee.class); - map.put(net.minecraft.world.entity.monster.Blaze.class, Blaze.class); map.put(net.minecraft.world.entity.animal.Cat.class, Cat.class); - map.put(net.minecraft.world.entity.monster.CaveSpider.class, CaveSpider.class); map.put(net.minecraft.world.entity.animal.Chicken.class, Chicken.class); map.put(net.minecraft.world.entity.animal.Cod.class, Cod.class); map.put(net.minecraft.world.entity.animal.Cow.class, Cow.class); - map.put(net.minecraft.world.entity.PathfinderMob.class, Creature.class); - map.put(net.minecraft.world.entity.monster.Creeper.class, Creeper.class); map.put(net.minecraft.world.entity.animal.Dolphin.class, Dolphin.class); - map.put(net.minecraft.world.entity.monster.Drowned.class, Drowned.class); - map.put(net.minecraft.world.entity.boss.enderdragon.EnderDragon.class, EnderDragon.class); - map.put(net.minecraft.world.entity.monster.EnderMan.class, Enderman.class); - map.put(net.minecraft.world.entity.monster.Endermite.class, Endermite.class); - map.put(net.minecraft.world.entity.monster.Evoker.class, Evoker.class); - map.put(net.minecraft.world.entity.animal.AbstractFish.class, Fish.class); - map.put(net.minecraft.world.entity.animal.AbstractSchoolingFish.class, SchoolableFish.class); map.put(net.minecraft.world.entity.animal.Fox.class, Fox.class); - map.put(net.minecraft.world.entity.monster.Ghast.class, Ghast.class); - map.put(net.minecraft.world.entity.monster.Giant.class, Giant.class); - map.put(net.minecraft.world.entity.animal.AbstractGolem.class, Golem.class); - map.put(net.minecraft.world.entity.monster.Guardian.class, Guardian.class); - map.put(net.minecraft.world.entity.monster.ElderGuardian.class, ElderGuardian.class); - map.put(net.minecraft.world.entity.animal.horse.Horse.class, Horse.class); - map.put(net.minecraft.world.entity.animal.horse.AbstractHorse.class, AbstractHorse.class); - map.put(net.minecraft.world.entity.animal.horse.AbstractChestedHorse.class, ChestedHorse.class); - map.put(net.minecraft.world.entity.animal.horse.Donkey.class, Donkey.class); - map.put(net.minecraft.world.entity.animal.horse.Mule.class, Mule.class); - map.put(net.minecraft.world.entity.animal.horse.SkeletonHorse.class, SkeletonHorse.class); - map.put(net.minecraft.world.entity.animal.horse.ZombieHorse.class, ZombieHorse.class); - map.put(net.minecraft.world.entity.animal.camel.Camel.class, Camel.class); - map.put(net.minecraft.world.entity.monster.AbstractIllager.class, Illager.class); - map.put(net.minecraft.world.entity.monster.Illusioner.class, Illusioner.class); - map.put(net.minecraft.world.entity.monster.SpellcasterIllager.class, Spellcaster.class); + map.put(net.minecraft.world.entity.animal.HappyGhast.class, HappyGhast.class); map.put(net.minecraft.world.entity.animal.IronGolem.class, IronGolem.class); - map.put(net.minecraft.world.entity.animal.horse.Llama.class, Llama.class); - map.put(net.minecraft.world.entity.animal.horse.TraderLlama.class, TraderLlama.class); - map.put(net.minecraft.world.entity.monster.MagmaCube.class, MagmaCube.class); - map.put(net.minecraft.world.entity.monster.Monster.class, Monster.class); - map.put(net.minecraft.world.entity.monster.PatrollingMonster.class, Raider.class); map.put(net.minecraft.world.entity.animal.MushroomCow.class, MushroomCow.class); map.put(net.minecraft.world.entity.animal.Ocelot.class, Ocelot.class); map.put(net.minecraft.world.entity.animal.Panda.class, Panda.class); map.put(net.minecraft.world.entity.animal.Parrot.class, Parrot.class); - map.put(net.minecraft.world.entity.animal.ShoulderRidingEntity.class, Parrot.class); - map.put(net.minecraft.world.entity.monster.Phantom.class, Phantom.class); map.put(net.minecraft.world.entity.animal.Pig.class, Pig.class); - map.put(net.minecraft.world.entity.monster.ZombifiedPiglin.class, PigZombie.class); - map.put(net.minecraft.world.entity.monster.Pillager.class, Pillager.class); map.put(net.minecraft.world.entity.animal.PolarBear.class, PolarBear.class); map.put(net.minecraft.world.entity.animal.Pufferfish.class, PufferFish.class); map.put(net.minecraft.world.entity.animal.Rabbit.class, Rabbit.class); - map.put(net.minecraft.world.entity.raid.Raider.class, Raider.class); - map.put(net.minecraft.world.entity.monster.Ravager.class, Ravager.class); map.put(net.minecraft.world.entity.animal.Salmon.class, Salmon.class); + map.put(net.minecraft.world.entity.animal.ShoulderRidingEntity.class, Parrot.class); + map.put(net.minecraft.world.entity.animal.SnowGolem.class, Snowman.class); + map.put(net.minecraft.world.entity.animal.Squid.class, Squid.class); + map.put(net.minecraft.world.entity.animal.TropicalFish.class, TropicalFish.class); + map.put(net.minecraft.world.entity.animal.Turtle.class, Turtle.class); + map.put(net.minecraft.world.entity.animal.WaterAnimal.class, WaterMob.class); + map.put(net.minecraft.world.entity.animal.allay.Allay.class, Allay.class); + map.put(net.minecraft.world.entity.animal.armadillo.Armadillo.class, Armadillo.class); + map.put(net.minecraft.world.entity.animal.axolotl.Axolotl.class, Axolotl.class); + map.put(net.minecraft.world.entity.animal.camel.Camel.class, Camel.class); + map.put(net.minecraft.world.entity.animal.frog.Frog.class, Frog.class); + map.put(net.minecraft.world.entity.animal.frog.Tadpole.class, Tadpole.class); + map.put(net.minecraft.world.entity.animal.goat.Goat.class, Goat.class); + map.put(net.minecraft.world.entity.animal.horse.AbstractChestedHorse.class, ChestedHorse.class); + map.put(net.minecraft.world.entity.animal.horse.AbstractHorse.class, AbstractHorse.class); + map.put(net.minecraft.world.entity.animal.horse.Donkey.class, Donkey.class); + map.put(net.minecraft.world.entity.animal.horse.Horse.class, Horse.class); + map.put(net.minecraft.world.entity.animal.horse.Llama.class, Llama.class); + map.put(net.minecraft.world.entity.animal.horse.Mule.class, Mule.class); + map.put(net.minecraft.world.entity.animal.horse.SkeletonHorse.class, SkeletonHorse.class); + map.put(net.minecraft.world.entity.animal.horse.TraderLlama.class, TraderLlama.class); + map.put(net.minecraft.world.entity.animal.horse.ZombieHorse.class, ZombieHorse.class); map.put(net.minecraft.world.entity.animal.sheep.Sheep.class, Sheep.class); + map.put(net.minecraft.world.entity.animal.sniffer.Sniffer.class, Sniffer.class); + map.put(net.minecraft.world.entity.animal.wolf.Wolf.class, Wolf.class); + map.put(net.minecraft.world.entity.boss.enderdragon.EnderDragon.class, EnderDragon.class); + map.put(net.minecraft.world.entity.boss.wither.WitherBoss.class, Wither.class); + map.put(net.minecraft.world.entity.monster.AbstractIllager.class, Illager.class); + map.put(net.minecraft.world.entity.monster.AbstractSkeleton.class, AbstractSkeleton.class); + map.put(net.minecraft.world.entity.monster.Blaze.class, Blaze.class); + map.put(net.minecraft.world.entity.monster.Bogged.class, Bogged.class); + map.put(net.minecraft.world.entity.monster.CaveSpider.class, CaveSpider.class); + map.put(net.minecraft.world.entity.monster.Creeper.class, Creeper.class); + map.put(net.minecraft.world.entity.monster.Drowned.class, Drowned.class); + map.put(net.minecraft.world.entity.monster.ElderGuardian.class, ElderGuardian.class); + map.put(net.minecraft.world.entity.monster.EnderMan.class, Enderman.class); + map.put(net.minecraft.world.entity.monster.Endermite.class, Endermite.class); + map.put(net.minecraft.world.entity.monster.Evoker.class, Evoker.class); + map.put(net.minecraft.world.entity.monster.Ghast.class, Ghast.class); + map.put(net.minecraft.world.entity.monster.Giant.class, Giant.class); + map.put(net.minecraft.world.entity.monster.Guardian.class, Guardian.class); + map.put(net.minecraft.world.entity.monster.Husk.class, Husk.class); + map.put(net.minecraft.world.entity.monster.Illusioner.class, Illusioner.class); + map.put(net.minecraft.world.entity.monster.MagmaCube.class, MagmaCube.class); + map.put(net.minecraft.world.entity.monster.Monster.class, Monster.class); + map.put(net.minecraft.world.entity.monster.PatrollingMonster.class, Raider.class); + map.put(net.minecraft.world.entity.monster.Phantom.class, Phantom.class); + map.put(net.minecraft.world.entity.monster.Pillager.class, Pillager.class); + map.put(net.minecraft.world.entity.monster.Ravager.class, Ravager.class); map.put(net.minecraft.world.entity.monster.Shulker.class, Shulker.class); map.put(net.minecraft.world.entity.monster.Silverfish.class, Silverfish.class); map.put(net.minecraft.world.entity.monster.Skeleton.class, Skeleton.class); - map.put(net.minecraft.world.entity.monster.AbstractSkeleton.class, AbstractSkeleton.class); - map.put(net.minecraft.world.entity.monster.Stray.class, Stray.class); - map.put(net.minecraft.world.entity.monster.WitherSkeleton.class, WitherSkeleton.class); map.put(net.minecraft.world.entity.monster.Slime.class, Slime.class); - map.put(net.minecraft.world.entity.animal.SnowGolem.class, Snowman.class); + map.put(net.minecraft.world.entity.monster.SpellcasterIllager.class, Spellcaster.class); map.put(net.minecraft.world.entity.monster.Spider.class, Spider.class); - map.put(net.minecraft.world.entity.animal.Squid.class, Squid.class); - map.put(net.minecraft.world.entity.TamableAnimal.class, Tameable.class); - map.put(net.minecraft.world.entity.animal.TropicalFish.class, TropicalFish.class); - map.put(net.minecraft.world.entity.animal.Turtle.class, Turtle.class); - map.put(net.minecraft.world.entity.monster.Vex.class, Vex.class); - map.put(net.minecraft.world.entity.npc.Villager.class, Villager.class); - map.put(net.minecraft.world.entity.npc.AbstractVillager.class, AbstractVillager.class); - map.put(net.minecraft.world.entity.npc.WanderingTrader.class, WanderingTrader.class); - map.put(net.minecraft.world.entity.monster.Vindicator.class, Vindicator.class); - map.put(net.minecraft.world.entity.animal.WaterAnimal.class, WaterMob.class); - map.put(net.minecraft.world.entity.monster.Witch.class, Witch.class); - map.put(net.minecraft.world.entity.boss.wither.WitherBoss.class, Wither.class); - map.put(net.minecraft.world.entity.animal.wolf.Wolf.class, Wolf.class); - map.put(net.minecraft.world.entity.monster.Zombie.class, Zombie.class); - map.put(net.minecraft.world.entity.monster.Husk.class, Husk.class); - map.put(net.minecraft.world.entity.monster.ZombieVillager.class, ZombieVillager.class); - map.put(net.minecraft.world.entity.monster.hoglin.Hoglin.class, Hoglin.class); - map.put(net.minecraft.world.entity.monster.piglin.Piglin.class, Piglin.class); - map.put(net.minecraft.world.entity.monster.piglin.AbstractPiglin.class, PiglinAbstract.class); - map.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class); + map.put(net.minecraft.world.entity.monster.Stray.class, Stray.class); map.put(net.minecraft.world.entity.monster.Strider.class, Strider.class); + map.put(net.minecraft.world.entity.monster.Vex.class, Vex.class); + map.put(net.minecraft.world.entity.monster.Vindicator.class, Vindicator.class); + map.put(net.minecraft.world.entity.monster.Witch.class, Witch.class); + map.put(net.minecraft.world.entity.monster.WitherSkeleton.class, WitherSkeleton.class); map.put(net.minecraft.world.entity.monster.Zoglin.class, Zoglin.class); - map.put(net.minecraft.world.entity.GlowSquid.class, GlowSquid.class); - map.put(net.minecraft.world.entity.animal.axolotl.Axolotl.class, Axolotl.class); - map.put(net.minecraft.world.entity.animal.goat.Goat.class, Goat.class); - map.put(net.minecraft.world.entity.animal.frog.Frog.class, Frog.class); - map.put(net.minecraft.world.entity.animal.frog.Tadpole.class, Tadpole.class); - map.put(net.minecraft.world.entity.monster.warden.Warden.class, Warden.class); - map.put(net.minecraft.world.entity.animal.allay.Allay.class, Allay.class); - map.put(net.minecraft.world.entity.animal.sniffer.Sniffer.class, Sniffer.class); + map.put(net.minecraft.world.entity.monster.Zombie.class, Zombie.class); + map.put(net.minecraft.world.entity.monster.ZombieVillager.class, ZombieVillager.class); + map.put(net.minecraft.world.entity.monster.ZombifiedPiglin.class, PigZombie.class); map.put(net.minecraft.world.entity.monster.breeze.Breeze.class, Breeze.class); - map.put(net.minecraft.world.entity.animal.armadillo.Armadillo.class, Armadillo.class); - map.put(net.minecraft.world.entity.monster.Bogged.class, Bogged.class); map.put(net.minecraft.world.entity.monster.creaking.Creaking.class, Creaking.class); - map.put(net.minecraft.world.entity.animal.AgeableWaterCreature.class, Squid.class); - map.put(net.minecraft.world.entity.animal.AbstractCow.class, AbstractCow.class); - map.put(net.minecraft.world.entity.animal.HappyGhast.class, HappyGhast.class); + map.put(net.minecraft.world.entity.monster.hoglin.Hoglin.class, Hoglin.class); + map.put(net.minecraft.world.entity.monster.piglin.AbstractPiglin.class, PiglinAbstract.class); + map.put(net.minecraft.world.entity.monster.piglin.Piglin.class, Piglin.class); + map.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class); + map.put(net.minecraft.world.entity.monster.warden.Warden.class, Warden.class); + map.put(net.minecraft.world.entity.npc.AbstractVillager.class, AbstractVillager.class); + map.put(net.minecraft.world.entity.npc.Villager.class, Villager.class); + map.put(net.minecraft.world.entity.npc.WanderingTrader.class, WanderingTrader.class); + map.put(net.minecraft.world.entity.raid.Raider.class, Raider.class); // End generate - MobGoalHelper#BUKKIT_BRIDGE // }); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemMetas.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemMetas.java index 3db36f2ec0..97f9298f71 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemMetas.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemMetas.java @@ -2,16 +2,12 @@ package org.bukkit.craftbukkit.inventory; import com.destroystokyo.paper.inventory.meta.ArmorStandMeta; import java.util.function.BiFunction; -import net.minecraft.world.item.BannerItem; -import net.minecraft.world.item.BedItem; import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.BundleItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.SignItem; import net.minecraft.world.item.SpawnEggItem; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.ShulkerBoxBlock; +import net.minecraft.world.level.block.EntityBlock; import org.bukkit.inventory.ItemType; import org.bukkit.inventory.meta.ArmorMeta; import org.bukkit.inventory.meta.AxolotlBucketMeta; @@ -165,126 +161,161 @@ public final class CraftItemMetas { if (itemType == ItemType.AIR) { return CraftItemMetas.asType(CraftItemMetas.EMPTY_META_DATA); } + // Start generate - CraftItemMetas#getItemMetaData + // @GeneratedFrom 1.21.7 if (itemType == ItemType.WRITTEN_BOOK) { - return CraftItemMetas.asType(CraftItemMetas.SIGNED_BOOK_META_DATA); + return CraftItemMetas.asType(SIGNED_BOOK_META_DATA); } if (itemType == ItemType.WRITABLE_BOOK) { - return CraftItemMetas.asType(CraftItemMetas.WRITABLE_BOOK_META_DATA); + return CraftItemMetas.asType(WRITABLE_BOOK_META_DATA); } - if (itemType == ItemType.CREEPER_HEAD || itemType == ItemType.DRAGON_HEAD - || itemType == ItemType.PIGLIN_HEAD || itemType == ItemType.PLAYER_HEAD - || itemType == ItemType.SKELETON_SKULL || itemType == ItemType.WITHER_SKELETON_SKULL - || itemType == ItemType.ZOMBIE_HEAD) { - return CraftItemMetas.asType(CraftItemMetas.SKULL_META_DATA); + if (itemType == ItemType.LEATHER_BOOTS || + itemType == ItemType.LEATHER_LEGGINGS || + itemType == ItemType.LEATHER_CHESTPLATE || + itemType == ItemType.LEATHER_HELMET || + itemType == ItemType.WOLF_ARMOR) { + return CraftItemMetas.asType(COLORABLE_ARMOR_META_DATA); } - if (itemType == ItemType.CHAINMAIL_HELMET || itemType == ItemType.CHAINMAIL_CHESTPLATE - || itemType == ItemType.CHAINMAIL_LEGGINGS || itemType == ItemType.CHAINMAIL_BOOTS - || itemType == ItemType.DIAMOND_HELMET || itemType == ItemType.DIAMOND_CHESTPLATE - || itemType == ItemType.DIAMOND_LEGGINGS || itemType == ItemType.DIAMOND_BOOTS - || itemType == ItemType.GOLDEN_HELMET || itemType == ItemType.GOLDEN_CHESTPLATE - || itemType == ItemType.GOLDEN_LEGGINGS || itemType == ItemType.GOLDEN_BOOTS - || itemType == ItemType.IRON_HELMET || itemType == ItemType.IRON_CHESTPLATE - || itemType == ItemType.IRON_LEGGINGS || itemType == ItemType.IRON_BOOTS - || itemType == ItemType.NETHERITE_HELMET || itemType == ItemType.NETHERITE_CHESTPLATE - || itemType == ItemType.NETHERITE_LEGGINGS || itemType == ItemType.NETHERITE_BOOTS - || itemType == ItemType.TURTLE_HELMET) { - return CraftItemMetas.asType(CraftItemMetas.ARMOR_META_DATA); - } - if (itemType == ItemType.LEATHER_HELMET || itemType == ItemType.LEATHER_CHESTPLATE - || itemType == ItemType.LEATHER_LEGGINGS || itemType == ItemType.LEATHER_BOOTS - || itemType == ItemType.WOLF_ARMOR) { - return CraftItemMetas.asType(CraftItemMetas.COLORABLE_ARMOR_META_DATA); + if (itemType == ItemType.LEATHER_BOOTS || + itemType == ItemType.CHAINMAIL_BOOTS || + itemType == ItemType.GOLDEN_BOOTS || + itemType == ItemType.IRON_BOOTS || + itemType == ItemType.DIAMOND_BOOTS || + itemType == ItemType.NETHERITE_BOOTS || + itemType == ItemType.LEATHER_LEGGINGS || + itemType == ItemType.CHAINMAIL_LEGGINGS || + itemType == ItemType.GOLDEN_LEGGINGS || + itemType == ItemType.IRON_LEGGINGS || + itemType == ItemType.DIAMOND_LEGGINGS || + itemType == ItemType.NETHERITE_LEGGINGS || + itemType == ItemType.LEATHER_CHESTPLATE || + itemType == ItemType.CHAINMAIL_CHESTPLATE || + itemType == ItemType.GOLDEN_CHESTPLATE || + itemType == ItemType.IRON_CHESTPLATE || + itemType == ItemType.DIAMOND_CHESTPLATE || + itemType == ItemType.NETHERITE_CHESTPLATE || + itemType == ItemType.LEATHER_HELMET || + itemType == ItemType.CHAINMAIL_HELMET || + itemType == ItemType.GOLDEN_HELMET || + itemType == ItemType.IRON_HELMET || + itemType == ItemType.DIAMOND_HELMET || + itemType == ItemType.NETHERITE_HELMET || + itemType == ItemType.TURTLE_HELMET) { + return CraftItemMetas.asType(ARMOR_META_DATA); } if (itemType == ItemType.LEATHER_HORSE_ARMOR) { - return CraftItemMetas.asType(CraftItemMetas.LEATHER_ARMOR_META_DATA); + return CraftItemMetas.asType(LEATHER_ARMOR_META_DATA); } - if (itemType == ItemType.POTION || itemType == ItemType.SPLASH_POTION - || itemType == ItemType.LINGERING_POTION || itemType == ItemType.TIPPED_ARROW) { - return CraftItemMetas.asType(CraftItemMetas.POTION_META_DATA); + if (itemType == ItemType.POTION || + itemType == ItemType.SPLASH_POTION || + itemType == ItemType.LINGERING_POTION || + itemType == ItemType.TIPPED_ARROW) { + return CraftItemMetas.asType(POTION_META_DATA); } if (itemType == ItemType.FILLED_MAP) { - return CraftItemMetas.asType(CraftItemMetas.MAP_META_DATA); + return CraftItemMetas.asType(MAP_META_DATA); } if (itemType == ItemType.FIREWORK_ROCKET) { - return CraftItemMetas.asType(CraftItemMetas.FIREWORK_META_DATA); + return CraftItemMetas.asType(FIREWORK_META_DATA); } if (itemType == ItemType.FIREWORK_STAR) { - return CraftItemMetas.asType(CraftItemMetas.CHARGE_META_DATA); + return CraftItemMetas.asType(CHARGE_META_DATA); } if (itemType == ItemType.ENCHANTED_BOOK) { - return CraftItemMetas.asType(CraftItemMetas.ENCHANTED_BOOK_META_DATA); - } - if (itemHandle instanceof BannerItem) { - return CraftItemMetas.asType(CraftItemMetas.BANNER_META_DATA); + return CraftItemMetas.asType(ENCHANTED_BOOK_META_DATA); } if (itemHandle instanceof SpawnEggItem) { - return CraftItemMetas.asType(CraftItemMetas.SPAWN_EGG_META_DATA); + return CraftItemMetas.asType(SPAWN_EGG_META_DATA); } if (itemType == ItemType.ARMOR_STAND) { - return CraftItemMetas.asType(CraftItemMetas.ARMOR_STAND_META_DATA); + return CraftItemMetas.asType(ARMOR_STAND_META_DATA); } if (itemType == ItemType.KNOWLEDGE_BOOK) { - return CraftItemMetas.asType(CraftItemMetas.KNOWLEDGE_BOOK_META_DATA); + return CraftItemMetas.asType(KNOWLEDGE_BOOK_META_DATA); } - if (itemType == ItemType.FURNACE || itemType == ItemType.CHEST - || itemType == ItemType.TRAPPED_CHEST || itemType == ItemType.JUKEBOX - || itemType == ItemType.DISPENSER || itemType == ItemType.DROPPER - || itemHandle instanceof SignItem || itemType == ItemType.SPAWNER - || itemType == ItemType.BREWING_STAND || itemType == ItemType.ENCHANTING_TABLE - || itemType == ItemType.COMMAND_BLOCK || itemType == ItemType.REPEATING_COMMAND_BLOCK - || itemType == ItemType.CHAIN_COMMAND_BLOCK || itemType == ItemType.BEACON - || itemType == ItemType.DAYLIGHT_DETECTOR || itemType == ItemType.HOPPER - || itemType == ItemType.COMPARATOR || itemType == ItemType.STRUCTURE_BLOCK - || blockHandle instanceof ShulkerBoxBlock - || itemType == ItemType.ENDER_CHEST || itemType == ItemType.BARREL - || itemType == ItemType.BELL || itemType == ItemType.BLAST_FURNACE - || itemType == ItemType.CAMPFIRE || itemType == ItemType.SOUL_CAMPFIRE - || itemType == ItemType.JIGSAW || itemType == ItemType.LECTERN - || itemType == ItemType.SMOKER || itemType == ItemType.BEEHIVE - || itemType == ItemType.BEE_NEST || itemType == ItemType.SCULK_CATALYST - || itemType == ItemType.SCULK_SHRIEKER || itemType == ItemType.SCULK_SENSOR - || itemType == ItemType.CALIBRATED_SCULK_SENSOR || itemType == ItemType.CHISELED_BOOKSHELF - || itemType == ItemType.DECORATED_POT || itemType == ItemType.SUSPICIOUS_SAND - || itemType == ItemType.SUSPICIOUS_GRAVEL || itemType == ItemType.CRAFTER - || itemType == ItemType.TRIAL_SPAWNER || itemType == ItemType.VAULT - || itemType == ItemType.CREAKING_HEART || itemType == ItemType.TEST_BLOCK - || itemType == ItemType.TEST_INSTANCE_BLOCK || itemHandle instanceof BedItem - || itemType == ItemType.CONDUIT) { - return CraftItemMetas.asType(CraftItemMetas.BLOCK_STATE_META_DATA); + if (itemType == ItemType.PLAYER_HEAD || + itemType == ItemType.CREEPER_HEAD || + itemType == ItemType.ZOMBIE_HEAD || + itemType == ItemType.SKELETON_SKULL || + itemType == ItemType.WITHER_SKELETON_SKULL || + itemType == ItemType.DRAGON_HEAD || + itemType == ItemType.PIGLIN_HEAD) { + return CraftItemMetas.asType(SKULL_META_DATA); + } + if (itemType == ItemType.WHITE_BANNER || + itemType == ItemType.ORANGE_BANNER || + itemType == ItemType.MAGENTA_BANNER || + itemType == ItemType.LIGHT_BLUE_BANNER || + itemType == ItemType.YELLOW_BANNER || + itemType == ItemType.LIME_BANNER || + itemType == ItemType.PINK_BANNER || + itemType == ItemType.GRAY_BANNER || + itemType == ItemType.LIGHT_GRAY_BANNER || + itemType == ItemType.CYAN_BANNER || + itemType == ItemType.PURPLE_BANNER || + itemType == ItemType.BLUE_BANNER || + itemType == ItemType.BROWN_BANNER || + itemType == ItemType.GREEN_BANNER || + itemType == ItemType.RED_BANNER || + itemType == ItemType.BLACK_BANNER) { + return CraftItemMetas.asType(BANNER_META_DATA); + } + if (blockHandle instanceof EntityBlock) { + return CraftItemMetas.asType(BLOCK_STATE_META_DATA); } if (itemType == ItemType.SHIELD) { - return CraftItemMetas.asType(CraftItemMetas.SHIELD_META_DATA); + return CraftItemMetas.asType(SHIELD_META_DATA); } if (itemType == ItemType.TROPICAL_FISH_BUCKET) { - return CraftItemMetas.asType(CraftItemMetas.TROPICAL_FISH_BUCKET_META_DATA); + return CraftItemMetas.asType(TROPICAL_FISH_BUCKET_META_DATA); } if (itemType == ItemType.AXOLOTL_BUCKET) { - return CraftItemMetas.asType(CraftItemMetas.AXOLOTL_BUCKET_META_DATA); + return CraftItemMetas.asType(AXOLOTL_BUCKET_META_DATA); } if (itemType == ItemType.CROSSBOW) { - return CraftItemMetas.asType(CraftItemMetas.CROSSBOW_META_DATA); + return CraftItemMetas.asType(CROSSBOW_META_DATA); } if (itemType == ItemType.SUSPICIOUS_STEW) { - return CraftItemMetas.asType(CraftItemMetas.SUSPICIOUS_STEW_META_DATA); + return CraftItemMetas.asType(SUSPICIOUS_STEW_META_DATA); } - if (itemType == ItemType.COD_BUCKET || itemType == ItemType.PUFFERFISH_BUCKET || itemType == ItemType.TADPOLE_BUCKET - || itemType == ItemType.SALMON_BUCKET || itemType == ItemType.ITEM_FRAME - || itemType == ItemType.GLOW_ITEM_FRAME || itemType == ItemType.PAINTING) { - return CraftItemMetas.asType(CraftItemMetas.ENTITY_TAG_META_DATA); + if (itemType == ItemType.COD_BUCKET || + itemType == ItemType.PUFFERFISH_BUCKET || + itemType == ItemType.TADPOLE_BUCKET || + itemType == ItemType.SALMON_BUCKET || + itemType == ItemType.ITEM_FRAME || + itemType == ItemType.GLOW_ITEM_FRAME || + itemType == ItemType.PAINTING) { + return CraftItemMetas.asType(ENTITY_TAG_META_DATA); } if (itemType == ItemType.COMPASS) { - return CraftItemMetas.asType(CraftItemMetas.COMPASS_META_DATA); + return CraftItemMetas.asType(COMPASS_META_DATA); } - if (itemHandle instanceof BundleItem) { - return CraftItemMetas.asType(CraftItemMetas.BUNDLE_META_DATA); + if (itemType == ItemType.BUNDLE || + itemType == ItemType.BLACK_BUNDLE || + itemType == ItemType.BLUE_BUNDLE || + itemType == ItemType.BROWN_BUNDLE || + itemType == ItemType.CYAN_BUNDLE || + itemType == ItemType.GRAY_BUNDLE || + itemType == ItemType.GREEN_BUNDLE || + itemType == ItemType.LIGHT_BLUE_BUNDLE || + itemType == ItemType.LIGHT_GRAY_BUNDLE || + itemType == ItemType.LIME_BUNDLE || + itemType == ItemType.MAGENTA_BUNDLE || + itemType == ItemType.ORANGE_BUNDLE || + itemType == ItemType.PINK_BUNDLE || + itemType == ItemType.PURPLE_BUNDLE || + itemType == ItemType.RED_BUNDLE || + itemType == ItemType.YELLOW_BUNDLE || + itemType == ItemType.WHITE_BUNDLE) { + return CraftItemMetas.asType(BUNDLE_META_DATA); } if (itemType == ItemType.GOAT_HORN) { - return CraftItemMetas.asType(CraftItemMetas.MUSIC_INSTRUMENT_META_DATA); + return CraftItemMetas.asType(MUSIC_INSTRUMENT_META_DATA); } - if (itemType == ItemType.OMINOUS_BOTTLE) { - return CraftItemMetas.asType(CraftItemMetas.OMINOUS_BOTTLE_META_DATA); + return CraftItemMetas.asType(OMINOUS_BOTTLE_META_DATA); } + // End generate - CraftItemMetas#getItemMetaData return CraftItemMetas.asType(CraftItemMetas.ITEM_META_DATA); } diff --git a/paper-server/src/test/java/org/bukkit/SoundTest.java b/paper-server/src/test/java/org/bukkit/SoundTest.java deleted file mode 100644 index ef268c0436..0000000000 --- a/paper-server/src/test/java/org/bukkit/SoundTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.bukkit; - -import static org.junit.jupiter.api.Assertions.*; - -import org.bukkit.support.environment.AllFeatures; -import org.junit.jupiter.api.Test; - -@AllFeatures -public class SoundTest { - - @Test - public void testCategory() { - for (SoundCategory category : SoundCategory.values()) { - assertNotNull(net.minecraft.sounds.SoundSource.valueOf(category.name()), category + ""); - } - } - - @Test - public void testCategoryReverse() { - for (net.minecraft.sounds.SoundSource category : net.minecraft.sounds.SoundSource.values()) { - assertNotNull(SoundCategory.valueOf(category.name()), category + ""); - } - } -} diff --git a/paper-server/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/paper-server/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java index 6174b21c87..66951b176b 100644 --- a/paper-server/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +++ b/paper-server/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java @@ -3,19 +3,13 @@ package org.bukkit.craftbukkit.inventory; import static org.bukkit.support.MatcherAssert.*; import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.*; -import java.util.ArrayList; + import java.util.Arrays; import java.util.List; import java.util.UUID; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; -import net.minecraft.world.item.StandingAndWallBlockItem; -import net.minecraft.world.level.block.AbstractBannerBlock; -import net.minecraft.world.level.block.AbstractSkullBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.EntityBlock; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.DyeColor; @@ -43,7 +37,6 @@ import org.bukkit.inventory.meta.ArmorMeta; import org.bukkit.inventory.meta.AxolotlBucketMeta; import org.bukkit.inventory.meta.BannerMeta; import org.bukkit.inventory.meta.BlockDataMeta; -import org.bukkit.inventory.meta.BlockStateMeta; import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.BundleMeta; import org.bukkit.inventory.meta.ColorableArmorMeta; @@ -56,7 +49,6 @@ import org.bukkit.inventory.meta.KnowledgeBookMeta; import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.MapMeta; import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.inventory.meta.SpawnEggMeta; import org.bukkit.inventory.meta.TropicalFishBucketMeta; import org.bukkit.inventory.meta.trim.ArmorTrim; import org.bukkit.inventory.meta.trim.TrimMaterial; @@ -159,63 +151,12 @@ public class ItemMetaTest { assertThat(bukkit, is(craft)); } - @Test - public void testBlockStateMeta() { - List queue = new ArrayList<>(); - - for (Item item : BuiltInRegistries.ITEM) { - if (item instanceof BlockItem) { - queue.add(((BlockItem) item).getBlock()); - } - if (item instanceof StandingAndWallBlockItem) { - queue.add(((StandingAndWallBlockItem) item).wallBlock); - } - } - - for (Block block : queue) { - if (block != null) { - ItemStack stack = CraftItemStack.asNewCraftStack(Item.byBlock(block)); - - if (block instanceof AbstractSkullBlock || block instanceof AbstractBannerBlock) { - continue; // those blocks have a special meta - } - - ItemMeta meta = stack.getItemMeta(); - if (block instanceof EntityBlock) { - assertTrue(meta instanceof BlockStateMeta, stack + " has meta of type " + meta + " expected BlockStateMeta"); - - BlockStateMeta blockState = (BlockStateMeta) meta; - assertNotNull(blockState.getBlockState(), stack + " has null block state"); - - blockState.setBlockState(blockState.getBlockState()); - } else { - assertFalse(meta instanceof BlockStateMeta, stack + " has unexpected meta of type BlockStateMeta (but is not a tile)"); - } - } - } - } - - @Test - public void testSpawnEggsHasMeta() { - for (Item item : BuiltInRegistries.ITEM) { - if (item instanceof net.minecraft.world.item.SpawnEggItem) { - Material material = CraftItemType.minecraftToBukkit(item); - CraftMetaItem baseMeta = (CraftMetaItem) Bukkit.getItemFactory().getItemMeta(material); - ItemMeta baseMetaItem = CraftItemStack.getItemMeta(item.getDefaultInstance()); - - assertTrue(baseMeta instanceof CraftMetaSpawnEgg, material + " is not handled in CraftItemFactory"); - assertTrue(baseMeta.applicableTo(material), material + " is not applicable to CraftMetaSpawnEgg"); - assertTrue(baseMetaItem instanceof SpawnEggMeta, material + " is not handled in CraftItemStack"); - } - } - } - - // Paper start - check entity tag metas private static final java.util.Set> ENTITY_TAG_METAS = java.util.Set.of( CraftMetaEntityTag.class, CraftMetaTropicalFishBucket.class, CraftMetaAxolotlBucket.class ); + @Test public void testEntityTagMeta() { for (final Item item : BuiltInRegistries.ITEM) { @@ -229,7 +170,6 @@ public class ItemMetaTest { } } } - // Paper end @Test public void testEachExtraData() { diff --git a/paper-server/src/test/java/org/bukkit/registry/RegistryConversionTest.java b/paper-server/src/test/java/org/bukkit/registry/RegistryConversionTest.java index 87396938f8..852f1ec596 100644 --- a/paper-server/src/test/java/org/bukkit/registry/RegistryConversionTest.java +++ b/paper-server/src/test/java/org/bukkit/registry/RegistryConversionTest.java @@ -52,7 +52,7 @@ public class RegistryConversionTest { @Order(1) @RegistriesTest - public void testHandleableImplementation(io.papermc.paper.registry.RegistryKey type, Class clazz) { // Paper + public void testHandleableImplementation(RegistryKey type, Class clazz) { // Paper Set> notImplemented = new HashSet<>(); Registry registry = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(type); // Paper @@ -74,7 +74,7 @@ public class RegistryConversionTest { @Order(2) @RegistriesTest - public void testMinecraftToBukkitPresent(io.papermc.paper.registry.RegistryKey type, Class clazz, ResourceKey> registryKey, + public void testMinecraftToBukkitPresent(RegistryKey type, Class clazz, ResourceKey> registryKey, Class craftClazz, Class minecraftClazz, boolean newMethod) { String methodName = (newMethod) ? RegistryConversionTest.MINECRAFT_TO_BUKKIT_NEW : RegistryConversionTest.MINECRAFT_TO_BUKKIT; Method method = null; @@ -123,7 +123,7 @@ public class RegistryConversionTest { @Order(2) @RegistriesTest - public void testBukkitToMinecraftPresent(io.papermc.paper.registry.RegistryKey type, Class clazz, ResourceKey> registryKey, + public void testBukkitToMinecraftPresent(RegistryKey type, Class clazz, ResourceKey> registryKey, Class craftClazz, Class minecraftClazz, boolean newMethod) { String methodName = (newMethod) ? RegistryConversionTest.BUKKIT_TO_MINECRAFT_NEW : RegistryConversionTest.BUKKIT_TO_MINECRAFT; Method method = null; @@ -172,7 +172,7 @@ public class RegistryConversionTest { @Order(3) @RegistriesTest - public void testMinecraftToBukkitNullValue(io.papermc.paper.registry.RegistryKey type, Class clazz) throws IllegalAccessException { // Paper + public void testMinecraftToBukkitNullValue(RegistryKey type, Class clazz) throws IllegalAccessException { // Paper this.checkValidMinecraftToBukkit(clazz); try { @@ -191,7 +191,7 @@ public class RegistryConversionTest { @Order(3) @RegistriesTest - public void testBukkitToMinecraftNullValue(io.papermc.paper.registry.RegistryKey type, Class clazz) throws IllegalAccessException { // Paper + public void testBukkitToMinecraftNullValue(RegistryKey type, Class clazz) throws IllegalAccessException { // Paper this.checkValidBukkitToMinecraft(clazz); try { @@ -210,7 +210,7 @@ public class RegistryConversionTest { @Order(3) @RegistriesTest - public void testMinecraftToBukkit(io.papermc.paper.registry.RegistryKey type, Class clazz) { // Paper + public void testMinecraftToBukkit(RegistryKey type, Class clazz) { // Paper this.checkValidMinecraftToBukkit(clazz); this.checkValidHandle(clazz); @@ -241,7 +241,7 @@ public class RegistryConversionTest { @Order(3) @RegistriesTest - public void testBukkitToMinecraft(io.papermc.paper.registry.RegistryKey type, Class clazz) { // Paper + public void testBukkitToMinecraft(RegistryKey type, Class clazz) { // Paper this.checkValidBukkitToMinecraft(clazz); this.checkValidHandle(clazz); @@ -270,7 +270,17 @@ public class RegistryConversionTest { Joiner.on('\n').withKeyValueSeparator(" got: ").join(notMatching))); } - static final Set> IGNORE_FOR_DIRECT_HOLDER = Set.of(RegistryKey.TRIM_MATERIAL, RegistryKey.TRIM_PATTERN, RegistryKey.INSTRUMENT, RegistryKey.BANNER_PATTERN, RegistryKey.SOUND_EVENT, RegistryKey.DIALOG); // Paper + static final Set> IGNORE_FOR_DIRECT_HOLDER = Set.of( + // Start generate - RegistryConversionTest#IGNORE_FOR_DIRECT_HOLDER + // @GeneratedFrom 1.21.7 + RegistryKey.SOUND_EVENT, + RegistryKey.TRIM_MATERIAL, + RegistryKey.TRIM_PATTERN, + RegistryKey.BANNER_PATTERN, + RegistryKey.INSTRUMENT, + RegistryKey.DIALOG + // End generate - RegistryConversionTest#IGNORE_FOR_DIRECT_HOLDER + ); /** * Minecraft registry can return a default key / value @@ -278,7 +288,7 @@ public class RegistryConversionTest { */ @Order(3) @RegistriesTest - public void testMinecraftToBukkitNoValidMinecraft(io.papermc.paper.registry.RegistryKey type, Class clazz, ResourceKey> registryKey, // Paper + public void testMinecraftToBukkitNoValidMinecraft(RegistryKey type, Class clazz, ResourceKey> registryKey, // Paper Class craftClazz, Class minecraftClazz) throws IllegalAccessException { this.checkValidMinecraftToBukkit(clazz); diff --git a/paper-server/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java b/paper-server/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java index 919f13143d..e8587a4cd2 100644 --- a/paper-server/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java +++ b/paper-server/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java @@ -1,6 +1,8 @@ package org.bukkit.support.provider; import com.google.common.collect.Lists; +import io.papermc.paper.datacomponent.DataComponentType; +import io.papermc.paper.datacomponent.PaperDataComponentType; import io.papermc.paper.dialog.Dialog; import io.papermc.paper.dialog.PaperDialog; import io.papermc.paper.registry.RegistryKey; @@ -21,6 +23,8 @@ import net.minecraft.world.entity.decoration.PaintingVariant; import net.minecraft.world.entity.npc.VillagerProfession; import net.minecraft.world.entity.npc.VillagerType; import net.minecraft.world.item.Instrument; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BannerPattern; import net.minecraft.world.level.saveddata.maps.MapDecorationType; import org.bukkit.Art; @@ -87,41 +91,40 @@ public class RegistriesArgumentProvider implements ArgumentsProvider { static { // Order: RegistryKey, Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class - register(RegistryKey.PAINTING_VARIANT, Art.class, Registries.PAINTING_VARIANT, CraftArt.class, PaintingVariant.class); - register(RegistryKey.ATTRIBUTE, Attribute.class, Registries.ATTRIBUTE, CraftAttribute.class, net.minecraft.world.entity.ai.attributes.Attribute.class); - register(RegistryKey.BIOME, Biome.class, Registries.BIOME, CraftBiome.class, net.minecraft.world.level.biome.Biome.class); - register(RegistryKey.ENCHANTMENT, Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class); - register(RegistryKey.FLUID, Fluid.class, Registries.FLUID, CraftFluid.class, net.minecraft.world.level.material.Fluid.class); - register(RegistryKey.GAME_EVENT, GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class); - register(RegistryKey.INSTRUMENT, MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class); - register(RegistryKey.MOB_EFFECT, PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class); - register(RegistryKey.SOUND_EVENT, Sound.class, Registries.SOUND_EVENT, CraftSound.class, SoundEvent.class); - register(RegistryKey.STRUCTURE, Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class); - register(RegistryKey.STRUCTURE_TYPE, StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class); - register(RegistryKey.VILLAGER_TYPE, Villager.Type.class, Registries.VILLAGER_TYPE, CraftVillager.CraftType.class, VillagerType.class); - register(RegistryKey.VILLAGER_PROFESSION, Villager.Profession.class, Registries.VILLAGER_PROFESSION, CraftVillager.CraftProfession.class, VillagerProfession.class); - register(RegistryKey.TRIM_MATERIAL, TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.equipment.trim.TrimMaterial.class); - register(RegistryKey.TRIM_PATTERN, TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.equipment.trim.TrimPattern.class); - register(RegistryKey.DAMAGE_TYPE, DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class); - register(RegistryKey.JUKEBOX_SONG, JukeboxSong.class, Registries.JUKEBOX_SONG, CraftJukeboxSong.class, net.minecraft.world.item.JukeboxSong.class); - register(RegistryKey.WOLF_VARIANT, Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, WolfVariant.class); - register(RegistryKey.WOLF_SOUND_VARIANT, Wolf.SoundVariant.class, Registries.WOLF_SOUND_VARIANT, CraftWolf.CraftSoundVariant.class, WolfSoundVariant.class); - register(RegistryKey.ITEM, ItemType.class, Registries.ITEM, CraftItemType.class, net.minecraft.world.item.Item.class, true); - register(RegistryKey.BLOCK, BlockType.class, Registries.BLOCK, CraftBlockType.class, net.minecraft.world.level.block.Block.class, true); - register(RegistryKey.FROG_VARIANT, Frog.Variant.class, Registries.FROG_VARIANT, CraftFrog.CraftVariant.class, FrogVariant.class); - register(RegistryKey.CAT_VARIANT, Cat.Type.class, Registries.CAT_VARIANT, CraftCat.CraftType.class, CatVariant.class); - register(RegistryKey.MAP_DECORATION_TYPE, MapCursor.Type.class, Registries.MAP_DECORATION_TYPE, CraftMapCursor.CraftType.class, MapDecorationType.class); - register(RegistryKey.BANNER_PATTERN, PatternType.class, Registries.BANNER_PATTERN, CraftPatternType.class, BannerPattern.class); - register(RegistryKey.MENU, MenuType.class, Registries.MENU, CraftMenuType.class, net.minecraft.world.inventory.MenuType.class); - register(RegistryKey.DATA_COMPONENT_TYPE, io.papermc.paper.datacomponent.DataComponentType.class, Registries.DATA_COMPONENT_TYPE, io.papermc.paper.datacomponent.PaperDataComponentType.class, net.minecraft.core.component.DataComponentType.class); - register(RegistryKey.CHICKEN_VARIANT, Chicken.Variant.class, Registries.CHICKEN_VARIANT, CraftChicken.CraftVariant.class, ChickenVariant.class); - register(RegistryKey.COW_VARIANT, Cow.Variant.class, Registries.COW_VARIANT, CraftCow.CraftVariant.class, CowVariant.class); - register(RegistryKey.PIG_VARIANT, Pig.Variant.class, Registries.PIG_VARIANT, CraftPig.CraftVariant.class, PigVariant.class); - register(RegistryKey.DIALOG, Dialog.class, Registries.DIALOG, PaperDialog.class, net.minecraft.server.dialog.Dialog.class); - } - - private static void register(RegistryKey registryKey, Class bukkit, ResourceKey registry, Class craft, Class minecraft) { // Paper - RegistriesArgumentProvider.register(registryKey, bukkit, registry, craft, minecraft, false); + // Start generate - RegistriesArgumentProvider#DATA + // @GeneratedFrom 1.21.7 + register(RegistryKey.GAME_EVENT, GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class, false); + register(RegistryKey.STRUCTURE_TYPE, StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class, false); + register(RegistryKey.MOB_EFFECT, PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class, false); + register(RegistryKey.BLOCK, BlockType.class, Registries.BLOCK, CraftBlockType.class, Block.class, true); + register(RegistryKey.ITEM, ItemType.class, Registries.ITEM, CraftItemType.class, Item.class, true); + register(RegistryKey.VILLAGER_PROFESSION, Villager.Profession.class, Registries.VILLAGER_PROFESSION, CraftVillager.CraftProfession.class, VillagerProfession.class, false); + register(RegistryKey.VILLAGER_TYPE, Villager.Type.class, Registries.VILLAGER_TYPE, CraftVillager.CraftType.class, VillagerType.class, false); + register(RegistryKey.MAP_DECORATION_TYPE, MapCursor.Type.class, Registries.MAP_DECORATION_TYPE, CraftMapCursor.CraftType.class, MapDecorationType.class, false); + register(RegistryKey.MENU, MenuType.class, Registries.MENU, CraftMenuType.class, net.minecraft.world.inventory.MenuType.class, false); + register(RegistryKey.ATTRIBUTE, Attribute.class, Registries.ATTRIBUTE, CraftAttribute.class, net.minecraft.world.entity.ai.attributes.Attribute.class, false); + register(RegistryKey.FLUID, Fluid.class, Registries.FLUID, CraftFluid.class, net.minecraft.world.level.material.Fluid.class, false); + register(RegistryKey.SOUND_EVENT, Sound.class, Registries.SOUND_EVENT, CraftSound.class, SoundEvent.class, false); + register(RegistryKey.DATA_COMPONENT_TYPE, DataComponentType.class, Registries.DATA_COMPONENT_TYPE, PaperDataComponentType.class, net.minecraft.core.component.DataComponentType.class, false); + register(RegistryKey.BIOME, Biome.class, Registries.BIOME, CraftBiome.class, net.minecraft.world.level.biome.Biome.class, false); + register(RegistryKey.STRUCTURE, Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class, false); + register(RegistryKey.TRIM_MATERIAL, TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.equipment.trim.TrimMaterial.class, false); + register(RegistryKey.TRIM_PATTERN, TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.equipment.trim.TrimPattern.class, false); + register(RegistryKey.DAMAGE_TYPE, DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class, false); + register(RegistryKey.WOLF_VARIANT, Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, WolfVariant.class, false); + register(RegistryKey.WOLF_SOUND_VARIANT, Wolf.SoundVariant.class, Registries.WOLF_SOUND_VARIANT, CraftWolf.CraftSoundVariant.class, WolfSoundVariant.class, false); + register(RegistryKey.ENCHANTMENT, Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class, false); + register(RegistryKey.JUKEBOX_SONG, JukeboxSong.class, Registries.JUKEBOX_SONG, CraftJukeboxSong.class, net.minecraft.world.item.JukeboxSong.class, false); + register(RegistryKey.BANNER_PATTERN, PatternType.class, Registries.BANNER_PATTERN, CraftPatternType.class, BannerPattern.class, false); + register(RegistryKey.PAINTING_VARIANT, Art.class, Registries.PAINTING_VARIANT, CraftArt.class, PaintingVariant.class, false); + register(RegistryKey.INSTRUMENT, MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class, false); + register(RegistryKey.CAT_VARIANT, Cat.Type.class, Registries.CAT_VARIANT, CraftCat.CraftType.class, CatVariant.class, false); + register(RegistryKey.FROG_VARIANT, Frog.Variant.class, Registries.FROG_VARIANT, CraftFrog.CraftVariant.class, FrogVariant.class, false); + register(RegistryKey.CHICKEN_VARIANT, Chicken.Variant.class, Registries.CHICKEN_VARIANT, CraftChicken.CraftVariant.class, ChickenVariant.class, false); + register(RegistryKey.COW_VARIANT, Cow.Variant.class, Registries.COW_VARIANT, CraftCow.CraftVariant.class, CowVariant.class, false); + register(RegistryKey.PIG_VARIANT, Pig.Variant.class, Registries.PIG_VARIANT, CraftPig.CraftVariant.class, PigVariant.class, false); + register(RegistryKey.DIALOG, Dialog.class, Registries.DIALOG, PaperDialog.class, net.minecraft.server.dialog.Dialog.class, false); + // End generate - RegistriesArgumentProvider#DATA } private static void register(RegistryKey registryKey, Class bukkit, ResourceKey registry, Class craft, Class minecraft, boolean newClass) { // Paper