mirror of
https://github.com/PaperMC/Paper.git
synced 2025-07-26 01:32:02 -07:00
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
This commit is contained in:
@@ -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}
|
||||
|
@@ -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<Dialog> create(final Key key) {
|
||||
return TagKey.create(RegistryKey.DIALOG, key);
|
||||
}
|
||||
|
@@ -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<org.bukkit.block.data.FaceAttachable.AttachedFace> ATTACH_FACE = enumeration("face", FaceAttachable.AttachedFace.class);
|
||||
public static final EnumBlockProperty<org.bukkit.Axis> AXIS = enumeration("axis", Axis.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Bamboo.Leaves> BAMBOO_LEAVES = enumeration("leaves", Bamboo.Leaves.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Bed.Part> BED_PART = enumeration("part", Bed.Part.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Bell.Attachment> BELL_ATTACHMENT = enumeration("attachment", Bell.Attachment.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Chest.Type> CHEST_TYPE = enumeration("type", Chest.Type.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.CreakingHeart.State> CREAKING_HEART_STATE = enumeration("creaking_heart_state", CreakingHeart.State.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Door.Hinge> DOOR_HINGE = enumeration("hinge", Door.Hinge.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.Bisected.Half> DOUBLE_BLOCK_HALF = enumeration("half", Bisected.Half.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.PointedDripstone.Thickness> DRIPSTONE_THICKNESS = enumeration("thickness", PointedDripstone.Thickness.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.RedstoneWire.Connection> EAST_REDSTONE = enumeration("east", RedstoneWire.Connection.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Wall.Height> EAST_WALL = enumeration("east", Wall.Height.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.BlockFace> FACING = enumeration("facing", BlockFace.class, org.bukkit.block.BlockFace::isCartesian);
|
||||
public static final EnumBlockProperty<org.bukkit.block.BlockFace> FACING_HOPPER = enumeration("facing", BlockFace.class, ((Predicate<org.bukkit.block.BlockFace>) org.bukkit.block.BlockFace::isCartesian).and(face -> face != org.bukkit.block.BlockFace.UP));
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.Bisected.Half> HALF = enumeration("half", Bisected.Half.class);
|
||||
public static final EnumBlockProperty<org.bukkit.Axis> HORIZONTAL_AXIS = enumeration("axis", Axis.class, org.bukkit.Axis::isHorizontal);
|
||||
public static final EnumBlockProperty<org.bukkit.block.BlockFace> HORIZONTAL_FACING = enumeration("facing", BlockFace.class, org.bukkit.block.BlockFace::isCardinal);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Comparator.Mode> MODE_COMPARATOR = enumeration("mode", Comparator.Mode.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.RedstoneWire.Connection> NORTH_REDSTONE = enumeration("north", RedstoneWire.Connection.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Wall.Height> NORTH_WALL = enumeration("north", Wall.Height.class);
|
||||
public static final EnumBlockProperty<org.bukkit.Instrument> NOTEBLOCK_INSTRUMENT = enumeration("instrument", Instrument.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.Orientation> ORIENTATION = enumeration("orientation", Orientation.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.TechnicalPiston.Type> PISTON_TYPE = enumeration("type", TechnicalPiston.Type.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.Rail.Shape> RAIL_SHAPE = enumeration("shape", Rail.Shape.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.Rail.Shape> RAIL_SHAPE_STRAIGHT = enumeration("shape", Rail.Shape.class, org.bukkit.block.data.Rail.Shape::isStraight);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.SculkSensor.Phase> SCULK_SENSOR_PHASE = enumeration("sculk_sensor_phase", SculkSensor.Phase.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Slab.Type> SLAB_TYPE = enumeration("type", Slab.Type.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.RedstoneWire.Connection> SOUTH_REDSTONE = enumeration("south", RedstoneWire.Connection.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Wall.Height> SOUTH_WALL = enumeration("south", Wall.Height.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Stairs.Shape> STAIRS_SHAPE = enumeration("shape", Stairs.Shape.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.StructureBlock.Mode> STRUCTUREBLOCK_MODE = enumeration("mode", StructureBlock.Mode.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.TestBlock.Mode> TEST_BLOCK_MODE = enumeration("mode", TestBlock.Mode.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.BigDripleaf.Tilt> TILT = enumeration("tilt", BigDripleaf.Tilt.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.TrialSpawner.State> TRIAL_SPAWNER_STATE = enumeration("trial_spawner_state", TrialSpawner.State.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Vault.State> VAULT_STATE = enumeration("vault_state", Vault.State.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.BlockFace> VERTICAL_DIRECTION = enumeration("vertical_direction", BlockFace.class, face -> face.getModY() != 0);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.RedstoneWire.Connection> WEST_REDSTONE = enumeration("west", RedstoneWire.Connection.class);
|
||||
public static final EnumBlockProperty<org.bukkit.block.data.type.Wall.Height> 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<org.bukkit.Note> 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<org.bukkit.block.BlockFace> 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);
|
||||
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
@@ -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");
|
||||
|
@@ -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;
|
||||
|
@@ -19,10 +19,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public interface Tag<T extends Keyed> 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<Material> ACACIA_LOGS = Bukkit.getTag(REGISTRY_BLOCKS, NamespacedKey.minecraft("acacia_logs"), Material.class);
|
||||
|
||||
Tag<Material> AIR = Bukkit.getTag(REGISTRY_BLOCKS, NamespacedKey.minecraft("air"), Material.class);
|
||||
@@ -411,8 +415,6 @@ public interface Tag<T extends Keyed> extends Keyed {
|
||||
|
||||
Tag<Material> WOOL_CARPETS = Bukkit.getTag(REGISTRY_BLOCKS, NamespacedKey.minecraft("wool_carpets"), Material.class);
|
||||
|
||||
String REGISTRY_ITEMS = "items";
|
||||
|
||||
Tag<Material> ITEMS_ACACIA_LOGS = Bukkit.getTag(REGISTRY_ITEMS, NamespacedKey.minecraft("acacia_logs"), Material.class);
|
||||
|
||||
Tag<Material> ITEMS_ANVIL = Bukkit.getTag(REGISTRY_ITEMS, NamespacedKey.minecraft("anvil"), Material.class);
|
||||
@@ -771,14 +773,10 @@ public interface Tag<T extends Keyed> extends Keyed {
|
||||
|
||||
Tag<Material> ITEMS_WOOL_CARPETS = Bukkit.getTag(REGISTRY_ITEMS, NamespacedKey.minecraft("wool_carpets"), Material.class);
|
||||
|
||||
String REGISTRY_FLUIDS = "fluids";
|
||||
|
||||
Tag<Fluid> FLUIDS_LAVA = Bukkit.getTag(REGISTRY_FLUIDS, NamespacedKey.minecraft("lava"), Fluid.class);
|
||||
|
||||
Tag<Fluid> FLUIDS_WATER = Bukkit.getTag(REGISTRY_FLUIDS, NamespacedKey.minecraft("water"), Fluid.class);
|
||||
|
||||
String REGISTRY_ENTITY_TYPES = "entity_types";
|
||||
|
||||
Tag<EntityType> ENTITY_TYPES_AQUATIC = Bukkit.getTag(REGISTRY_ENTITY_TYPES, NamespacedKey.minecraft("aquatic"), EntityType.class);
|
||||
|
||||
Tag<EntityType> ENTITY_TYPES_ARROWS = Bukkit.getTag(REGISTRY_ENTITY_TYPES, NamespacedKey.minecraft("arrows"), EntityType.class);
|
||||
@@ -857,8 +855,6 @@ public interface Tag<T extends Keyed> extends Keyed {
|
||||
|
||||
Tag<EntityType> ENTITY_TYPES_ZOMBIES = Bukkit.getTag(REGISTRY_ENTITY_TYPES, NamespacedKey.minecraft("zombies"), EntityType.class);
|
||||
|
||||
String REGISTRY_GAME_EVENTS = "game_events";
|
||||
|
||||
Tag<GameEvent> GAME_EVENT_ALLAY_CAN_LISTEN = Bukkit.getTag(REGISTRY_GAME_EVENTS, NamespacedKey.minecraft("allay_can_listen"), GameEvent.class);
|
||||
|
||||
Tag<GameEvent> GAME_EVENT_IGNORE_VIBRATIONS_SNEAKING = Bukkit.getTag(REGISTRY_GAME_EVENTS, NamespacedKey.minecraft("ignore_vibrations_sneaking"), GameEvent.class);
|
||||
|
@@ -17,147 +17,184 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public interface Attribute extends OldEnum<Attribute>, 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));
|
||||
|
@@ -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;
|
||||
|
@@ -6,6 +6,7 @@ package org.bukkit.entity;
|
||||
public enum Pose {
|
||||
|
||||
// Start generate - Pose
|
||||
// @GeneratedFrom 1.21.7
|
||||
/**
|
||||
* Entity is standing normally.
|
||||
*/
|
||||
|
@@ -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
|
||||
|
||||
//<editor-fold desc="ItemTypes" defaultstate="collapsed">
|
||||
// Start generate - ItemType
|
||||
// @GeneratedFrom 1.21.7-rc1
|
||||
// @GeneratedFrom 1.21.7
|
||||
ItemType.Typed<ItemMeta> ACACIA_BOAT = getItemType("acacia_boat");
|
||||
|
||||
ItemType.Typed<ItemMeta> ACACIA_BUTTON = getItemType("acacia_button");
|
||||
@@ -165,7 +166,7 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
||||
|
||||
ItemType.Typed<SpawnEggMeta> ARMADILLO_SPAWN_EGG = getItemType("armadillo_spawn_egg");
|
||||
|
||||
ItemType.Typed<com.destroystokyo.paper.inventory.meta.ArmorStandMeta> ARMOR_STAND = getItemType("armor_stand");
|
||||
ItemType.Typed<ArmorStandMeta> ARMOR_STAND = getItemType("armor_stand");
|
||||
|
||||
ItemType.Typed<ItemMeta> ARMS_UP_POTTERY_SHERD = getItemType("arms_up_pottery_sherd");
|
||||
|
||||
|
@@ -1,3 +1,6 @@
|
||||
[*.java]
|
||||
ij_java_generate_final_locals = false
|
||||
ij_java_generate_final_parameters = false
|
||||
|
||||
[*.json]
|
||||
indent_size = 2
|
||||
|
@@ -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<JavaExec>("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<GenerationArgumentProvider>()
|
||||
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<String>
|
||||
|
||||
@get:Input
|
||||
abstract val rewrite: Property<Boolean>
|
||||
@@ -141,9 +155,6 @@ abstract class GenerationArgumentProvider : CommandLineArgumentProvider {
|
||||
@get:Input
|
||||
abstract val side: Property<String>
|
||||
|
||||
@get:CompileClasspath
|
||||
abstract val serverClassPath: ConfigurableFileCollection
|
||||
|
||||
@get:Input
|
||||
@get:Optional
|
||||
abstract val bootstrapTags: Property<Boolean>
|
||||
@@ -155,17 +166,18 @@ abstract class GenerationArgumentProvider : CommandLineArgumentProvider {
|
||||
override fun asArguments(): Iterable<String> {
|
||||
val args = mutableListOf<String>()
|
||||
|
||||
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"
|
||||
|
@@ -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<SourceGenerator> 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
|
||||
}));
|
||||
|
||||
|
@@ -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<Integer> {
|
||||
|
||||
@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<Path> classpath;
|
||||
|
||||
@CommandLine.Option(names = {"--rewrite"})
|
||||
boolean isRewrite;
|
||||
|
||||
@@ -61,17 +60,19 @@ public class Main implements Callable<Integer> {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public static @MonotonicNonNull Path ROOT_DIR;
|
||||
public static RegistryAccess.@MonotonicNonNull Frozen REGISTRY_ACCESS;
|
||||
public static @MonotonicNonNull Map<TagKey<?>, String> EXPERIMENTAL_TAGS;
|
||||
public static final boolean IS_UPDATING = Boolean.getBoolean("paper.updatingMinecraft");
|
||||
|
||||
public static CompletableFuture<Void> 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<RegistryLayer> layers = RegistryLayer.createRegistryAccess();
|
||||
List<Registry.PendingTags<?>> pendingTags = TagLoader.loadTagsForExistingRegistries(resourceManager, layers.getLayer(RegistryLayer.STATIC));
|
||||
List<HolderLookup.RegistryLookup<?>> worldGenLayer = TagLoader.buildUpdatedLookups(layers.getAccessForLoading(RegistryLayer.WORLDGEN), pendingTags);
|
||||
@@ -106,9 +107,10 @@ public class Main implements Callable<Integer> {
|
||||
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<Integer> {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void rewrite(Path sourceSet, Set<Path> classpath, Consumer<PatternSourceSetRewriter> rewriters) throws IOException {
|
||||
PatternSourceSetRewriter sourceSetRewriter = new PaperPatternSourceSetRewriter(classpath);
|
||||
private static void rewrite(Path sourceSet, Consumer<PatternSourceSetRewriter> 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<SourceGenerator> 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) {
|
||||
|
@@ -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<Consumer<PatternSourceSetRewriter>> values = VALUES.values().iterator();
|
||||
for (PatternSourceSetRewriter sourceSetRewriter : sourceSets) {
|
||||
values.next().accept(sourceSetRewriter);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Consumer<PatternSourceSetRewriter> API = Rewriters::bootstrapApi;
|
||||
public static final Consumer<PatternSourceSetRewriter> SERVER = Rewriters::bootstrapServer;
|
||||
public static final Map<String, Consumer<PatternSourceSetRewriter>> 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<net.minecraft.world.item.JukeboxSong> reference) {
|
||||
protected String rewriteFieldName(Holder.Reference<JukeboxSong> 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<? extends Mob>, Class<? extends org.bukkit.entity.Mob>> entry : MobGoalNames.BUKKIT_BRIDGE.entrySet()) {
|
||||
for (Map.Entry<Class<? extends Mob>, 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());
|
||||
}
|
||||
}
|
||||
|
@@ -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<SourceGenerator> 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) {
|
||||
|
@@ -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 <T> RegistryEntry<T> entry(ResourceKey<? extends Registry<T>> registryKey, Class<?> holderElementsClass, Class<? extends Keyed> apiClass) {
|
||||
return entry(registryKey, holderElementsClass, apiClass, "Craft");
|
||||
private static <T> RegistryIntern<T> entry(ResourceKey<? extends Registry<T>> registryKey, Class<?> holderElementsClass) {
|
||||
return new RegistryIntern<>(registryKey, holderElementsClass);
|
||||
}
|
||||
|
||||
private static <T> RegistryEntry<T> entry(ResourceKey<? extends Registry<T>> registryKey, Class<?> holderElementsClass, Class<? extends Keyed> apiClass, String implPrefix) {
|
||||
String name = io.papermc.typewriter.util.ClassHelper.retrieveFullNestedName(apiClass);
|
||||
RegistryKeyField<T> registryKeyField = (RegistryKeyField<T>) 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 <T> RegistryEntry<T> inconsistentEntry(ResourceKey<? extends Registry<T>> registryKey, Class<?> holderElementsClass, Class<? extends Keyed> apiClass, String implClass) {
|
||||
return new RegistryEntry<>(registryKey, (RegistryKeyField<T>) REGISTRY_KEY_FIELDS.get(registryKey), holderElementsClass, apiClass, implClass);
|
||||
}
|
||||
|
||||
private static final Map<ResourceKey<? extends Registry<?>>, RegistryKeyField<?>> REGISTRY_KEY_FIELDS;
|
||||
public static final Map<ResourceKey<? extends Registry<?>>, RegistryKeyField<?>> REGISTRY_KEY_FIELDS;
|
||||
static {
|
||||
Map<ResourceKey<? extends Registry<?>>, RegistryKeyField<?>> registryKeyFields = new IdentityHashMap<>();
|
||||
try {
|
||||
@@ -146,77 +88,104 @@ public final class RegistryEntries {
|
||||
REGISTRY_KEY_FIELDS = Collections.unmodifiableMap(registryKeyFields);
|
||||
}
|
||||
|
||||
public static final Set<Class<?>> REGISTRY_CLASS_NAME_BASED_ON_API = Set.of(
|
||||
BlockType.class,
|
||||
ItemType.class
|
||||
private static final Map<ResourceKey<? extends Registry<?>>, 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<RegistryEntry<?>> API_ONLY = new ArrayList<>();
|
||||
|
||||
@Deprecated
|
||||
public static final List<ResourceKey<? extends Registry<?>>> API_ONLY_KEYS = List.of(
|
||||
Registries.ENTITY_TYPE, Registries.PARTICLE_TYPE, Registries.POTION, Registries.MEMORY_MODULE_TYPE
|
||||
);
|
||||
|
||||
public static final List<RegistryEntry<?>> 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<RegistryEntry.Type, RegistryEntry<?>> REGISTRIES = Util.make(MultimapBuilder.enumKeys(RegistryEntry.Type.class).arrayListValues().build(), map -> {
|
||||
List<ResourceKey<? extends Registry<?>>> remainingRegistries = new ArrayList<>(EXPOSED_REGISTRIES.keySet());
|
||||
DataFileLoader.REGISTRIES.forEach((type, file) -> {
|
||||
Map<ResourceKey<? extends Registry<?>>, RegistryData> registries = file.get();
|
||||
for (Map.Entry<ResourceKey<? extends Registry<?>>, RegistryData> registry : registries.entrySet()) {
|
||||
ResourceKey<? extends Registry<?>> 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<RegistryEntry<?>> 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<RegistryEntry<?>> 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<RegistryEntry<?>> byType(RegistryEntry.Type type) {
|
||||
return REGISTRIES.get(type);
|
||||
}
|
||||
|
||||
public static final Map<ResourceKey<? extends Registry<?>>, RegistryEntry<?>> BY_REGISTRY_KEY;
|
||||
static {
|
||||
Map<ResourceKey<? extends Registry<?>>, RegistryEntry<?>> byRegistryKey = new IdentityHashMap<>(BUILT_IN.size() + DATA_DRIVEN.size() + API_ONLY.size());
|
||||
Map<ResourceKey<? extends Registry<?>>, 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 <T> RegistryEntry<T> byRegistryKey(ResourceKey<? extends Registry<T>> registryKey) {
|
||||
return (RegistryEntry<T>) Objects.requireNonNull(BY_REGISTRY_KEY.get(registryKey));
|
||||
return (RegistryEntry<T>) Objects.requireNonNull(BY_REGISTRY_KEY.get(registryKey), "registry not found: " + registryKey);
|
||||
}
|
||||
|
||||
// real registries
|
||||
public static void forEach(Consumer<RegistryEntry<?>> callback) {
|
||||
forEach(callback, RegistryEntries.BUILT_IN, RegistryEntries.DATA_DRIVEN);
|
||||
forEach(callback, REGISTRIES.values());
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static void forEach(Consumer<RegistryEntry<?>> callback, List<RegistryEntry<?>>... datas) {
|
||||
for (List<RegistryEntry<?>> data : datas) {
|
||||
public static void forEach(Consumer<RegistryEntry<?>> callback, Collection<RegistryEntry<?>>... datas) {
|
||||
for (Collection<RegistryEntry<?>> data : datas) {
|
||||
for (RegistryEntry<?> entry : data) {
|
||||
callback.accept(entry);
|
||||
}
|
||||
|
@@ -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<T> {
|
||||
public class RegistryEntry<T> implements RegistryIdentifiable<T> {
|
||||
|
||||
private final ResourceKey<? extends Registry<T>> registryKey;
|
||||
private final RegistryKeyField<T> registryKeyField;
|
||||
private final Class<T> elementClass;
|
||||
private final Class<?> holderElementsClass;
|
||||
private boolean allowDirect;
|
||||
|
||||
private final Class<? extends Keyed> 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<String> apiRegistryField = Optional.empty();
|
||||
private final RegistryData data;
|
||||
|
||||
private @Nullable Map<ResourceKey<T>, String> fieldNames;
|
||||
|
||||
public RegistryEntry(ResourceKey<? extends Registry<T>> registryKey, RegistryKeyField<T> registryKeyField, Class<?> holderElementsClass, Class<? extends Keyed> apiClass, String implClass) {
|
||||
protected RegistryEntry(ResourceKey<? extends Registry<T>> registryKey, RegistryKeyField<T> 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<? extends Registry<T>> registryKey() {
|
||||
@Override
|
||||
public ResourceKey<? extends Registry<T>> getRegistryKey() {
|
||||
return this.registryKey;
|
||||
}
|
||||
|
||||
@@ -62,123 +45,55 @@ public final class RegistryEntry<T> {
|
||||
return Main.REGISTRY_ACCESS.lookupOrThrow(this.registryKey);
|
||||
}
|
||||
|
||||
public Class<T> elementClass() {
|
||||
return this.registryKeyField.elementClass();
|
||||
}
|
||||
|
||||
public String registryKeyField() {
|
||||
return this.registryKeyField.name();
|
||||
}
|
||||
|
||||
public Class<? extends Keyed> apiClass() {
|
||||
return this.apiClass;
|
||||
public RegistryData data() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public String implClass() {
|
||||
return this.implClass;
|
||||
}
|
||||
|
||||
public RegistryEntry<T> allowDirect() {
|
||||
this.allowDirect = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegistryEntry<T> delayed() {
|
||||
this.delayed = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegistryEntry<T> preload(Class<?> klass) {
|
||||
this.preloadClass = klass;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegistryEntry<T> apiAccessName(String name) {
|
||||
Preconditions.checkArgument(SourceVersion.isIdentifier(name) && !SourceVersion.isKeyword(name), "Invalid accessor name");
|
||||
this.apiAccessName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegistryEntry<T> 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<T> writableApiRegistryBuilder(Class<?> builderClass, String builderImplClass) {
|
||||
return this.apiRegistryBuilder(builderClass, builderImplClass, RegistryModificationApiSupport.WRITABLE);
|
||||
}
|
||||
|
||||
public RegistryEntry<T> apiRegistryBuilder(Class<?> builderClass, String builderImplClass, RegistryModificationApiSupport modificationApiSupport) {
|
||||
this.apiRegistryBuilder = builderClass;
|
||||
this.apiRegistryBuilderImpl = builderImplClass;
|
||||
this.modificationApiSupport = modificationApiSupport;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Optional<String> apiRegistryField() {
|
||||
return this.apiRegistryField;
|
||||
}
|
||||
|
||||
public RegistryEntry<T> 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 <TO> Map<ResourceKey<T>, TO> getFields(Map<ResourceKey<T>, TO> map, Function<Field, @Nullable TO> transform) {
|
||||
Registry<T> registry = this.registry();
|
||||
Class<T> 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<T> 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<T>) field.get(null)).key();
|
||||
@@ -217,19 +132,23 @@ public final class RegistryEntry<T> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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<T> {
|
||||
|
||||
ResourceKey<? extends Registry<T>> getRegistryKey();
|
||||
}
|
@@ -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<T>(ResourceKey<? extends Registry<T>> registryKey, RegistryKeyField<T> registryKeyField, Class<?> holderElementsClass) implements RegistryIdentifiable<T> {
|
||||
public RegistryIntern(ResourceKey<? extends Registry<T>> registryKey, Class<?> holderElementsClass) {
|
||||
this(registryKey, (RegistryKeyField<T>) RegistryEntries.REGISTRY_KEY_FIELDS.get(registryKey), holderElementsClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceKey<? extends Registry<T>> getRegistryKey() {
|
||||
return this.registryKey;
|
||||
}
|
||||
|
||||
public RegistryEntry<?> bind(RegistryData data) {
|
||||
return new RegistryEntry<>(this.registryKey, this.registryKeyField, this.holderElementsClass, data);
|
||||
}
|
||||
}
|
@@ -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<V, A, R> {
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().setFormattingStyle(FormattingStyle.PRETTY).create();
|
||||
|
||||
private final String path;
|
||||
protected final Codec<V> codec;
|
||||
protected final DynamicOps<JsonElement> requiredOps;
|
||||
private final Transmuter<V, A, R> transmuter;
|
||||
private final boolean requireRegistry;
|
||||
private @MonotonicNonNull V value;
|
||||
|
||||
protected DataFile(String path, Codec<V> codec, Transmuter<V, A, R> 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<V> codec, Transmuter<V, A, R> 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<A, R> slice(){
|
||||
return this.transmuter.examine(this.get());
|
||||
}
|
||||
|
||||
public SliceResult<A, R> upgrade(Path destination) throws IOException {
|
||||
if (!(this.transmuter instanceof Transmuter.Mutable<V, A, R> mutableTransmuter)) {
|
||||
return SliceResult.empty();
|
||||
}
|
||||
|
||||
SliceResult<A, R> 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<String, String> print(SliceResult<A, R> result);
|
||||
|
||||
public String path() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public Codec<V> codec() {
|
||||
return this.codec;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public <T> DynamicOps<T> getRequiredOps(DynamicOps<T> 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<K, V> extends DataFile<java.util.Map<K, V>, java.util.Map.Entry<K, V>, K> {
|
||||
public Map(String path, Codec<java.util.Map<K, V>> codec, Transmuter<java.util.Map<K, V>, java.util.Map.Entry<K, V>, K> transmuter, boolean requireRegistry) {
|
||||
super(path, codec, transmuter, requireRegistry);
|
||||
}
|
||||
|
||||
public Map(String path, Codec<java.util.Map<K, V>> codec, Transmuter<java.util.Map<K, V>, java.util.Map.Entry<K, V>, K> transmuter) {
|
||||
super(path, codec, transmuter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlattenSliceResult<String, String> print(SliceResult<java.util.Map.Entry<K, V>, K> result) {
|
||||
String newEntries = null;
|
||||
String dropEntries = null;
|
||||
if (!result.added().isEmpty()) {
|
||||
java.util.Map<K, V> 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<K, V> 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<E> extends DataFile<java.util.List<E>, E, E> {
|
||||
public List(String path, Codec<java.util.List<E>> codec, Transmuter<java.util.List<E>, E, E> transmuter, boolean requireRegistry) {
|
||||
super(path, codec, transmuter, requireRegistry);
|
||||
}
|
||||
|
||||
public List(String path, Codec<java.util.List<E>> codec, Transmuter<java.util.List<E>, E, E> transmuter) {
|
||||
super(path, codec, transmuter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlattenSliceResult<String, String> print(SliceResult<E, E> 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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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 <K, V> Transmuter<Map<K, V>, Map.Entry<K, V>, K> sortedMap(Comparator<K> comparator) {
|
||||
return transmuteMap(SliceResult::empty, comparator);
|
||||
}
|
||||
|
||||
private static <K, V> Transmuter<Map<K, V>, Map.Entry<K, V>, K> transmuteMap(Supplier<Set<K>> typesProvider, Function<K, V> onMissing, Comparator<K> comparator) {
|
||||
return transmuteMap(map -> {
|
||||
Set<K> types = typesProvider.get();
|
||||
Set<K> registeredTypes = map.keySet();
|
||||
|
||||
Set<Map.Entry<K, V>> added = new HashSet<>();
|
||||
Sets.difference(types, registeredTypes).forEach(missingType -> added.add(Map.entry(missingType, onMissing.apply(missingType))));
|
||||
Set<K> removed = new HashSet<>(Sets.difference(registeredTypes, types));
|
||||
return new SliceResult<>(added, removed);
|
||||
}, comparator);
|
||||
}
|
||||
|
||||
private static <K, V> Transmuter<Map<K, V>, Map.Entry<K, V>, K> transmuteMap(Function<Map<K, V>, SliceResult<Map.Entry<K, V>, K>> slicer, Comparator<K> comparator) {
|
||||
return new Transmuter.Mutable<>() {
|
||||
|
||||
@Override
|
||||
public SliceResult<Map.Entry<K, V>, K> examine(Map<K, V> original) {
|
||||
return slicer.apply(original);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, V> apply(Map<K, V> original, SliceResult<Map.Entry<K, V>, K> result) {
|
||||
Map<K, V> 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<ResourceKey<? extends DataFile<?, ?, ?>>, DataFile<?, ?, ?>> DATA_FILES = new HashMap<>();
|
||||
public static final @MonotonicNonNull Map<ResourceKey<? extends DataFile<?, ?, ?>>, DataFile<?, ?, ?>> DATA_FILES_VIEW = Collections.unmodifiableMap(DATA_FILES);
|
||||
|
||||
private static final Supplier<Map<ResourceKey<EntityType<?>>, 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<RegistryEntry.Type, DataFile.Map<ResourceKey<? extends Registry<?>>, RegistryData>> REGISTRIES = Collections.unmodifiableMap(Util.make(new EnumMap<>(RegistryEntry.Type.class), map -> {
|
||||
Codec<Map<ResourceKey<? extends Registry<?>>, RegistryData>> codec = Codec.lazyInitialized(() -> Codec.unboundedMap(SourceCodecs.REGISTRY_KEY, RegistryData.CODEC));
|
||||
for (RegistryEntry.Type type : RegistryEntry.Type.values()) {
|
||||
ResourceKey<DataFile.Map<ResourceKey<? extends Registry<?>>, 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<Enum<? extends StringRepresentable>>() {}), SourceCodecs.CLASS_NAME
|
||||
),
|
||||
(path, codec) -> new DataFile.Map<>(
|
||||
path, codec,
|
||||
transmuteMap(() -> {
|
||||
try {
|
||||
Set<Class<? extends Enum<? extends StringRepresentable>>> 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<Class<? extends Mob>> 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, A, R> V get(ResourceKey<? extends DataFile<V, A, R>> key) {
|
||||
return ((DataFile<V, A, R>) DATA_FILES.get(key)).get();
|
||||
}
|
||||
|
||||
private static <V, A, R> void register(ResourceKey<? extends DataFile<V, A, R>> key, Supplier<Codec<V>> codec, BiFunction<String, Codec<V>, DataFile<V, A, R>> maker) {
|
||||
register(key, path -> maker.apply(path, Codec.lazyInitialized(codec)));
|
||||
}
|
||||
|
||||
private static <F extends DataFile<?, ?, ?>> F register(ResourceKey<? extends F> key, Function<String, F> maker) {
|
||||
F file = maker.apply("data/%s.json".formatted(key.location().getPath()));
|
||||
DATA_FILES.put(key, file);
|
||||
return file;
|
||||
}
|
||||
}
|
@@ -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<DataFile<?, ?, ?>>> REGISTRY_KEY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath("paper", "data_file"));
|
||||
|
||||
public static final ResourceKey<DataFile.Map<String, List<String>>> BLOCK_STATE_AMBIGUOUS_NAMES = store("block_state/ambiguous_names");
|
||||
public static final ResourceKey<DataFile.Map<Class<? extends Enum<? extends StringRepresentable>>, ClassName>> BLOCK_STATE_ENUM_PROPERTY_TYPES = store("block_state/enum_property_types");
|
||||
public static final ResourceKey<DataFile.Map<ClassNamed, List<BlockPredicate>>> BLOCK_STATE_PREDICATES = store("block_state/predicates");
|
||||
|
||||
public static final ResourceKey<DataFile.Map<ClassNamed, ItemMetaData>> ITEM_META_BRIDGE = store("item_meta/bridge");
|
||||
public static final ResourceKey<DataFile.Map<ClassNamed, List<ItemPredicate>>> ITEM_META_PREDICATES = store("item_meta/predicates");
|
||||
|
||||
public static ResourceKey<DataFile.Map<ResourceKey<? extends Registry<?>>, RegistryData>> registry(RegistryEntry.Type type) {
|
||||
return store("registry/%s".formatted(type.getSerializedName()));
|
||||
}
|
||||
|
||||
public static final ResourceKey<DataFile.Map<ResourceKey<EntityType<?>>, EntityTypeData>> ENTITY_TYPES = store("entity_types");
|
||||
public static final ResourceKey<DataFile.Map<Class<? extends Mob>, EntityClassData>> ENTITY_CLASS_NAMES = store("entity_class_names");
|
||||
|
||||
private static <T extends DataFile<?, ?, ?>> ResourceKey<T> store(String name) {
|
||||
return (ResourceKey<T>) ResourceKey.create(REGISTRY_KEY, ResourceLocation.fromNamespaceAndPath("paper", name));
|
||||
}
|
||||
|
||||
private DataFiles() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
package io.papermc.generator.resources;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public record FlattenSliceResult<A, R>(@Nullable A added, @Nullable R removed) {
|
||||
}
|
@@ -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<ParameterizedClass> arguments) {
|
||||
public ParameterizedClass(ClassNamed value) {
|
||||
this(value, List.of());
|
||||
}
|
||||
|
||||
private static Codec<ParameterizedClass> directCodec(Codec<ParameterizedClass> 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<ParameterizedClass> CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAMED.xmap(ParameterizedClass::new, ParameterizedClass::klass);
|
||||
|
||||
public static final Codec<ParameterizedClass> 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<TypeName> 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<ClassNamed, String> 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<ParameterizedClass> 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<ParameterizedClass> wildcardClasses, Function<ClassNamed, String> imported) {
|
||||
builder.append(imported.apply(rawType));
|
||||
int size = wildcardClasses.size();
|
||||
if (size != 0) {
|
||||
builder.append('<');
|
||||
Iterator<ParameterizedClass> 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('>');
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package io.papermc.generator.resources;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public record SliceResult<A, R>(Set<A> added, Set<R> removed) {
|
||||
|
||||
static <A, R> SliceResult<A, R> empty() {
|
||||
return new SliceResult<>(Collections.emptySet(), Collections.emptySet());
|
||||
}
|
||||
|
||||
static <V, A, R> SliceResult<A, R> empty(V value) {
|
||||
return empty();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.added.isEmpty() && this.removed.isEmpty();
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package io.papermc.generator.resources;
|
||||
|
||||
public interface Transmuter<V, A, R> {
|
||||
|
||||
SliceResult<A, R> examine(V original);
|
||||
|
||||
interface Mutable<V, A, R> extends Transmuter<V, A, R> {
|
||||
|
||||
V apply(V original, SliceResult<A, R> result);
|
||||
}
|
||||
}
|
@@ -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<EntityClassData> 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<EntityClassData> CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAME.xmap(EntityClassData::new, EntityClassData::name);
|
||||
|
||||
public static final Codec<EntityClassData> CODEC = Codec.either(CLASS_ONLY_CODEC, DIRECT_CODEC).xmap(Either::unwrap, data -> {
|
||||
if (!data.hasSpecifier()) {
|
||||
return Either.right(data);
|
||||
}
|
||||
return Either.left(data);
|
||||
});
|
||||
}
|
@@ -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<EntityTypeData> 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<EntityTypeData> CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAMED.xmap(EntityTypeData::new, EntityTypeData::api);
|
||||
|
||||
public static final Codec<EntityTypeData> 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);
|
||||
});
|
||||
}
|
@@ -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<ItemMetaData> 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));
|
||||
}
|
@@ -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> builder,
|
||||
Optional<String> serializationUpdaterField,
|
||||
boolean allowInline
|
||||
) {
|
||||
|
||||
public static final Codec<RegistryData> 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> holderClass, boolean keyClassNameRelate, Optional<String> registryField) {
|
||||
public Api(ClassNamed klass) {
|
||||
this(new Class(klass), Optional.of(new HolderClass(klass)), false, Optional.empty());
|
||||
}
|
||||
|
||||
public static final Codec<Api> 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<Api> CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAMED.xmap(Api::new, api -> api.klass().name());
|
||||
|
||||
public static final Codec<Api> 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<ParameterizedClass> wildcards, boolean legacyEnum) {
|
||||
public Class(ClassNamed name) {
|
||||
this(name, List.of(), false);
|
||||
}
|
||||
|
||||
public static final Codec<Class> 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> CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAMED.xmap(Class::new, Class::name);
|
||||
|
||||
public static final Codec<Class> 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<ClassNamed, String> imported) {
|
||||
ParameterizedClass.appendAsWildcardType(builder, this.name, this.wildcards, imported);
|
||||
}
|
||||
}
|
||||
|
||||
public record HolderClass(Optional<ClassNamed> name, boolean isInterface) {
|
||||
public HolderClass(ClassNamed name) {
|
||||
this(Optional.of(name), true);
|
||||
}
|
||||
|
||||
public static final Codec<HolderClass> 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<Impl> 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<Impl> CLASS_ONLY_CODEC = SourceCodecs.CLASS_NAMED.xmap(Impl::new, Impl::klass);
|
||||
|
||||
public static final Codec<Impl> 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<ParameterizedClass> wildcards, RegisterCapability capability) {
|
||||
|
||||
public static final Codec<Builder> 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<ClassNamed, String> 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<RegisterCapability> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
@NullMarked
|
||||
package io.papermc.generator.resources;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
@@ -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<BlockPredicate> 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<Type> CODEC = StringRepresentable.fromValues(Type::values);
|
||||
private final String name;
|
||||
final MapCodec<? extends BlockPredicate> codec;
|
||||
|
||||
Type(final String name, final MapCodec<? extends BlockPredicate> codec) {
|
||||
this.name = name;
|
||||
this.codec = codec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSerializedName() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
boolean matches(Class<? extends Block> block, Set<Property<?>> properties);
|
||||
|
||||
record IsClassPredicate(Class<? extends Block> value) implements BlockPredicate {
|
||||
|
||||
public static final MapCodec<IsClassPredicate> 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<? extends Block> block, Set<Property<?>> properties) {
|
||||
return this.value.equals(block);
|
||||
}
|
||||
}
|
||||
|
||||
record InstanceOfPredicate(Class<? extends Block> value, List<BlockPropertyPredicate> propertyPredicates) implements BlockPredicate {
|
||||
|
||||
public static final MapCodec<InstanceOfPredicate> 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<? extends Block> block, Set<Property<?>> 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<BlockPropertyPredicate> value, int count, Strategy strategy) implements BlockPredicate {
|
||||
|
||||
public static final MapCodec<ContainsPropertyPredicate> 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<ContainsPropertyPredicate> 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<? extends Block> block, Set<Property<?>> 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<Strategy> CODEC = StringRepresentable.fromEnum(Strategy::values);
|
||||
|
||||
Strategy(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSerializedName() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<BlockPropertyPredicate> DIRECT_CODEC = Type.CODEC.dispatch("type", BlockPropertyPredicate::type, type -> type.codec);
|
||||
Codec<BlockPropertyPredicate> COMPACT_CODEC = Codec.withAlternative(IsFieldPredicate.COMPACT_CODEC, IsNamePredicate.COMPACT_CODEC);
|
||||
Codec<BlockPropertyPredicate> 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<Type> CODEC = StringRepresentable.fromValues(Type::values);
|
||||
private final String name;
|
||||
final MapCodec<? extends BlockPropertyPredicate> codec;
|
||||
|
||||
Type(final String name, final MapCodec<? extends BlockPropertyPredicate> codec) {
|
||||
this.name = name;
|
||||
this.codec = codec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSerializedName() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
boolean matches(Property<?> property);
|
||||
|
||||
static boolean testProperty(Predicate<String> 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<String> 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<IsNamePredicate> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
||||
PROPERTY_NAME.fieldOf("value").forGetter(IsNamePredicate::value)
|
||||
).apply(instance, IsNamePredicate::new));
|
||||
|
||||
public static final Codec<BlockPropertyPredicate> 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<IsFieldPredicate> 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<BlockPropertyPredicate> 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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<ItemPredicate> DIRECT_CODEC = Type.CODEC.dispatch("type", ItemPredicate::type, type -> type.codec);
|
||||
Codec<ItemPredicate> 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<Type> CODEC = StringRepresentable.fromValues(Type::values);
|
||||
private final String name;
|
||||
final MapCodec<? extends ItemPredicate> codec;
|
||||
|
||||
Type(final String name, final MapCodec<? extends ItemPredicate> codec) {
|
||||
this.name = name;
|
||||
this.codec = codec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSerializedName() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
boolean matches(Holder.Reference<Item> item);
|
||||
|
||||
record IsClassPredicate(Class<?> value, boolean againstBlock) implements ItemPredicate {
|
||||
|
||||
public static final MapCodec<IsClassPredicate> 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> 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<InstanceOfPredicate> 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> 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<TagKey<Item>, Holder<Item>> value) implements ItemPredicate {
|
||||
|
||||
public static final MapCodec<IsElementPredicate> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
||||
SourceCodecs.elementOrTagCodec(Registries.ITEM).fieldOf("value").forGetter(IsElementPredicate::value)
|
||||
).apply(instance, IsElementPredicate::new));
|
||||
|
||||
public static final Codec<IsElementPredicate> 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> item) {
|
||||
return this.value.map(item::is, item::is);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<Pattern
|
||||
COMMENT_MARKER_FORMAT.formatted("Start", pattern),
|
||||
COMMENT_MARKER_FORMAT.formatted("End", pattern)
|
||||
)
|
||||
.generatedComment(Annotations.annotationStyle(GeneratedFrom.class) + " " + SharedConstants.getCurrentVersion().id())
|
||||
.generatedComment(Annotations.annotationStyle(Types.GENERATED_FROM) + " " + SharedConstants.getCurrentVersion().id())
|
||||
.targetClass(targetClass);
|
||||
}
|
||||
|
||||
|
@@ -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.registration.SourceSetRewriter;
|
||||
import io.papermc.typewriter.replace.CompositeRewriter;
|
||||
@@ -9,15 +11,11 @@ import org.jspecify.annotations.NullMarked;
|
||||
@NullMarked
|
||||
public interface PatternSourceSetRewriter extends SourceSetRewriter<PatternSourceSetRewriter> {
|
||||
|
||||
default PatternSourceSetRewriter register(String pattern, Class<?> targetClass, SearchReplaceRewriter rewriter) {
|
||||
return register(pattern, new ClassNamed(targetClass), rewriter);
|
||||
default <E, T extends SearchReplaceRewriter & RegistryIdentifiable<E>> 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);
|
||||
}
|
||||
|
@@ -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 <E, T extends SearchReplaceRewriter & RegistryIdentifiable<E>> 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);
|
||||
}
|
||||
|
||||
|
@@ -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<String> names = new ArrayList<>(name.simpleNames());
|
||||
String topName = names.removeFirst();
|
||||
return ClassNamed.of(name.packageName(), topName, names.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
@@ -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<T> extends EnumRewriter<Holder.Reference<T>> {
|
||||
public class EnumRegistryRewriter<T> extends EnumRewriter<Holder.Reference<T>> implements RegistryIdentifiable<T> {
|
||||
|
||||
private final ResourceKey<? extends Registry<T>> registryKey;
|
||||
private final Supplier<Registry<T>> registry;
|
||||
private final Supplier<Map<ResourceKey<T>, SingleFlagHolder>> experimentalKeys;
|
||||
private final boolean isFilteredRegistry;
|
||||
private final boolean hasKeyArgument;
|
||||
|
||||
public EnumRegistryRewriter(ResourceKey<? extends Registry<T>> registryKey) {
|
||||
this(registryKey, true);
|
||||
}
|
||||
|
||||
protected EnumRegistryRewriter(ResourceKey<? extends Registry<T>> 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<? extends Registry<T>> getRegistryKey() {
|
||||
return this.registryKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,23 +47,24 @@ public class EnumRegistryRewriter<T> extends EnumRewriter<Holder.Reference<T>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EnumValue.Builder rewriteEnumValue(Holder.Reference<T> 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<T> reference) {
|
||||
return EnumConstant.builder(Formatting.formatKeyAsField(reference.key().location().getPath()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendEnumValue(Holder.Reference<T> reference, StringBuilder builder, String indent, boolean reachEnd) {
|
||||
protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference<T> reference) {
|
||||
builder.argument(quoted(reference.key().location().getPath()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendConstant(Holder.Reference<T> 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<T> reference) {
|
||||
|
@@ -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<Map.Entry<ResourceLocation, FeatureFlag>> 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(';');
|
||||
|
@@ -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(',');
|
||||
}
|
||||
|
@@ -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<ClassNamed> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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<ResourceKey<? extends Registry<?>>> 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");
|
||||
});
|
||||
}
|
||||
}
|
@@ -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...
|
||||
}
|
||||
}
|
@@ -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');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -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<T> extends SearchReplaceRewriter {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public class RegistryFieldRewriter<T> extends SearchReplaceRewriter implements RegistryIdentifiable<T> {
|
||||
|
||||
private final ResourceKey<? extends Registry<T>> registryKey;
|
||||
private final boolean isFilteredRegistry;
|
||||
private final @Nullable String fetchMethod;
|
||||
|
||||
protected @MonotonicNonNull ClassNamed fieldClass;
|
||||
protected @MonotonicNonNull RegistryEntry<T> entry;
|
||||
private @MonotonicNonNull Supplier<Map<ResourceKey<T>, SingleFlagHolder>> experimentalKeys;
|
||||
|
||||
public RegistryFieldRewriter(ResourceKey<? extends Registry<T>> registryKey, @Nullable String fetchMethod) {
|
||||
@@ -49,27 +42,21 @@ public class RegistryFieldRewriter<T> extends SearchReplaceRewriter {
|
||||
this.fetchMethod = fetchMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceKey<? extends Registry<T>> 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<T> registry = Main.REGISTRY_ACCESS.lookupOrThrow(this.registryKey);
|
||||
boolean isInterface = this.entry.data().api().holderClass().isEmpty() || this.entry.data().api().holderClass().get().isInterface();
|
||||
Registry<T> registry = this.entry.registry();
|
||||
this.experimentalKeys = Suppliers.memoize(() -> ExperimentalCollector.collectDataDrivenElementIds(registry));
|
||||
Iterator<Holder.Reference<T>> referenceIterator = registry.listElements().filter(this::canPrintField).sorted(Formatting.HOLDER_ORDER).iterator();
|
||||
|
||||
@@ -108,7 +95,7 @@ public class RegistryFieldRewriter<T> extends SearchReplaceRewriter {
|
||||
}
|
||||
|
||||
protected String rewriteFieldType(Holder.Reference<T> reference) {
|
||||
return this.fieldClass.simpleName();
|
||||
return this.entry.data().api().klass().name().simpleName();
|
||||
}
|
||||
|
||||
protected String rewriteFieldName(Holder.Reference<T> reference) {
|
||||
|
@@ -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<T> extends SearchReplaceRewriter {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public class RegistryTagRewriter<T> extends SearchReplaceRewriter implements RegistryIdentifiable<T> {
|
||||
|
||||
private final ResourceKey<? extends Registry<T>> registryKey;
|
||||
private final Class<? extends Keyed> apiClass;
|
||||
private final String fetchMethod = "getTag";
|
||||
|
||||
public RegistryTagRewriter(ResourceKey<? extends Registry<T>> registryKey, Class<? extends Keyed> apiClass) {
|
||||
public RegistryTagRewriter(ResourceKey<? extends Registry<T>> 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<? extends Registry<T>> getRegistryKey() {
|
||||
return this.registryKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void insert(SearchMetadata metadata, StringBuilder builder) {
|
||||
Registry<T> registry = Main.REGISTRY_ACCESS.lookupOrThrow(this.registryKey);
|
||||
Iterator<? extends TagKey<T>> keyIterator = registry.listTagIds().sorted(Formatting.TAG_ORDER).iterator();
|
||||
RegistryEntry<T> entry = RegistryEntries.byRegistryKey(this.registryKey);
|
||||
Iterator<? extends TagKey<T>> keyIterator = entry.registry().listTagIds().sorted(Formatting.TAG_ORDER).iterator();
|
||||
|
||||
while (keyIterator.hasNext()) {
|
||||
TagKey<T> tagKey = keyIterator.next();
|
||||
@@ -70,7 +51,7 @@ public class RegistryTagRewriter<T> 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<T> extends SearchReplaceRewriter {
|
||||
}
|
||||
|
||||
protected String rewriteFieldValue(TagKey<T> tagKey) {
|
||||
return "%s(%s)".formatted(this.fetchMethod, quoted(tagKey.location().getPath()));
|
||||
return "%s(%s)".formatted(TagRewriter.FETCH_METHOD, quoted(tagKey.location().getPath()));
|
||||
}
|
||||
}
|
||||
|
@@ -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<? extends Keyed> apiType, ResourceKey<? extends Registry<?>> 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<? extends Registry<?>> registryKey) {
|
||||
public TagRegistry(String legacyFolderName, ResourceKey<? extends Registry<?>> 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<TokenType> FORMAT_TOKENS = EnumSet.of(
|
||||
TokenType.COMMENT,
|
||||
TokenType.SINGLE_COMMENT,
|
||||
TokenType.JAVADOC,
|
||||
TokenType.MARKDOWN_JAVADOC
|
||||
);
|
||||
|
||||
private List<String> parseExistingFields(String content) {
|
||||
List<String> 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<String> 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<? extends TagKey<?>> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,4 @@
|
||||
@NullMarked
|
||||
package io.papermc.generator.rewriter.types.registry;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
@@ -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<Class<?>, 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<Property<?>, 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<ClassNamed, String> imported);
|
||||
}
|
||||
|
||||
private static final Map<Property<?>, 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<? super Map.Entry<Property<?>, Field>> FIELD_ORDER =
|
||||
Comparator.<Map.Entry<Property<?>, Field>, String>comparing(entry -> entry.getKey().getClass().getSimpleName())
|
||||
.thenComparing(entry -> entry.getValue().getName());
|
||||
|
||||
@Override
|
||||
protected void insert(SearchMetadata metadata, StringBuilder builder) {
|
||||
Map<Class<? extends Enum<? extends StringRepresentable>>, ClassName> enumTypes = DataFileLoader.get(DataFiles.BLOCK_STATE_ENUM_PROPERTY_TYPES);
|
||||
for (Map.Entry<Property<?>, 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<Integer> 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');
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<Block> {
|
||||
|
||||
@@ -17,11 +16,11 @@ public class BlockTypeRewriter extends RegistryFieldRewriter<Block> {
|
||||
|
||||
@Override
|
||||
protected String rewriteFieldType(Holder.Reference<Block> reference) {
|
||||
Class<? extends BlockData> 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));
|
||||
}
|
||||
}
|
||||
|
@@ -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');
|
||||
});
|
||||
}
|
||||
|
@@ -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<ClassNamed, List<ItemPredicate>> entry : DataFileLoader.get(DataFiles.ITEM_META_PREDICATES).entrySet()) {
|
||||
String field = DataFileLoader.get(DataFiles.ITEM_META_BRIDGE).get(entry.getKey()).field();
|
||||
Iterator<ItemPredicate> 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<Holder<Item>> 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())));
|
||||
}
|
||||
}
|
@@ -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');
|
||||
});
|
||||
}
|
||||
|
@@ -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<EntityType<?>> {
|
||||
|
||||
private static final Map<ResourceKey<EntityType<?>>, Class<? extends Entity>> ENTITY_GENERIC_TYPES =
|
||||
RegistryEntries.byRegistryKey(Registries.ENTITY_TYPE).getFields(field -> {
|
||||
if (field.getGenericType() instanceof ParameterizedType complexType && complexType.getActualTypeArguments().length == 1) {
|
||||
return (Class<? extends Entity>) complexType.getActualTypeArguments()[0];
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
private static final Map<String, String> CLASS_RENAMES = ImmutableMap.<String, String>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<EntityType<?>> 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<EntityType<?>> reference) {
|
||||
protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference<EntityType<?>> 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<String> 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<EntityType<?>> reference) {
|
||||
Class<? extends Entity> internalClass = ENTITY_GENERIC_TYPES.get(reference.key());
|
||||
if (Mob.class.isAssignableFrom(internalClass)) {
|
||||
return this.importCollector.getShortName(MobGoalNames.BUKKIT_BRIDGE.get((Class<? extends Mob>) 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);
|
||||
}
|
||||
}
|
||||
|
@@ -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<Item> {
|
||||
@@ -22,6 +26,21 @@ public class ItemTypeRewriter extends RegistryFieldRewriter<Item> {
|
||||
return super.rewriteFieldType(reference);
|
||||
}
|
||||
|
||||
return "%s<%s>".formatted(ClassHelper.retrieveFullNestedName(ItemType.Typed.class), ItemMeta.class.getSimpleName());
|
||||
ClassNamed implMetaName = null;
|
||||
mainLoop:
|
||||
for (Map.Entry<ClassNamed, List<ItemPredicate>> 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());
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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<Block> {
|
||||
|
||||
public Blocks() {
|
||||
super(Registries.BLOCK, false);
|
||||
super(Registries.BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -33,10 +34,12 @@ public class MaterialRewriter {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EnumValue.Builder rewriteEnumValue(Holder.Reference<Block> reference) {
|
||||
EnumValue.Builder value = super.rewriteEnumValue(reference);
|
||||
protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference<Block> reference) {
|
||||
Block block = reference.value();
|
||||
if (BlockStateMapping.MAPPING.containsKey(block.getClass())) {
|
||||
List<String> 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<Item> 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<Item> {
|
||||
|
||||
public Items() {
|
||||
super(Registries.ITEM, false);
|
||||
super(Registries.ITEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,15 +92,17 @@ public class MaterialRewriter {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EnumValue.Builder rewriteEnumValue(Holder.Reference<Item> reference) {
|
||||
EnumValue.Builder value = super.rewriteEnumValue(reference);
|
||||
protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference<Item> reference) {
|
||||
Item item = reference.value();
|
||||
List<String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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<MemoryModuleType<?>
|
||||
Entity.class
|
||||
);
|
||||
|
||||
private static final Map<Class<?>, Class<?>> API_BRIDGE = Map.of(
|
||||
GlobalPos.class, Location.class
|
||||
private static final Map<Class<?>, ClassNamed> API_BRIDGE = Map.of(
|
||||
GlobalPos.class, Types.LOCATION
|
||||
);
|
||||
|
||||
private static final Map<String, String> FIELD_RENAMES = Map.of(
|
||||
@@ -83,7 +83,7 @@ public class MemoryKeyRewriter extends RegistryFieldRewriter<MemoryModuleType<?>
|
||||
return true;
|
||||
}
|
||||
|
||||
private @MonotonicNonNull Class<?> apiMemoryType;
|
||||
private @MonotonicNonNull ClassNamed apiMemoryType;
|
||||
|
||||
@Override
|
||||
protected String rewriteFieldType(Holder.Reference<MemoryModuleType<?>> reference) {
|
||||
@@ -92,10 +92,10 @@ public class MemoryKeyRewriter extends RegistryFieldRewriter<MemoryModuleType<?>
|
||||
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<MemoryModuleType<?>
|
||||
@Override
|
||||
protected String rewriteFieldValue(Holder.Reference<MemoryModuleType<?>> 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -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<ResourceLocation> {
|
||||
|
||||
public Custom() {
|
||||
super(Registries.CUSTOM_STAT, false);
|
||||
super(Registries.CUSTOM_STAT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EnumValue.Builder rewriteEnumValue(Holder.Reference<ResourceLocation> reference) {
|
||||
return super.rewriteEnumValue(reference).rename(name -> FIELD_RENAMES.getOrDefault(name, name));
|
||||
protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference<ResourceLocation> 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<ResourceLocation> reference) {
|
||||
String keyedName = Formatting.formatKeyAsField(reference.key().location().getPath());
|
||||
|
||||
return super.rewriteEnumValue(reference)
|
||||
protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference<ResourceLocation> 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<StatType<?>, Class<?>> FIELD_GENERIC_TYPE;
|
||||
|
||||
static {
|
||||
final Map<StatType<?>, 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<StatType<?>> reference) {
|
||||
Class<?> genericType = FIELD_GENERIC_TYPE.get(reference.value());
|
||||
protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference<StatType<?>> 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<StatType<?>> {
|
||||
|
||||
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<StatType<?>> reference) {
|
||||
return super.rewriteEnumValue(reference)
|
||||
protected void rewriteConstant(EnumConstant.Builder builder, Holder.Reference<StatType<?>> reference) {
|
||||
builder
|
||||
.rename(name -> FIELD_RENAMES.getOrDefault(name, name))
|
||||
.argument("%s.withDefaultNamespace(%s)".formatted(ResourceLocation.class.getSimpleName(), quoted(reference.key().location().getPath())));
|
||||
}
|
||||
|
@@ -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<Attribute> {
|
||||
|
||||
public AttributeRewriter() {
|
||||
super(Registries.ATTRIBUTE, "getAttribute");
|
||||
}
|
||||
|
||||
private static final Set<TokenType> FORMAT_TOKENS = EnumSet.of(
|
||||
TokenType.COMMENT,
|
||||
TokenType.SINGLE_COMMENT
|
||||
);
|
||||
|
||||
private @MonotonicNonNull Map<String, CharSequenceBlockToken> javadocsPerConstant;
|
||||
|
||||
private Map<String, CharSequenceBlockToken> parseConstantJavadocs(String content) {
|
||||
if (content.isBlank()) {
|
||||
return Map.of();
|
||||
}
|
||||
|
||||
Map<String, CharSequenceBlockToken> 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 -> { // <name>
|
||||
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<Attribute> 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');
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<Pose> {
|
||||
private @MonotonicNonNull Map<String, CharSequenceBlockToken> javadocsPerConstant;
|
||||
|
||||
private Map<String, CharSequenceBlockToken> parseConstantJavadocs(String content) {
|
||||
if (content.isBlank()) {
|
||||
return Map.of();
|
||||
}
|
||||
|
||||
Map<String, CharSequenceBlockToken> map = new HashMap<>();
|
||||
|
||||
Lexer lex = new Lexer(content.toCharArray());
|
||||
@@ -77,17 +81,17 @@ public class PoseRewriter extends EnumCloneRewriter<Pose> {
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
@@ -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<VillagerPr
|
||||
private @MonotonicNonNull Map<String, CharSequenceBlockToken> javadocsPerConstant;
|
||||
|
||||
private Map<String, CharSequenceBlockToken> parseConstantJavadocs(String content) {
|
||||
if (content.isBlank()) {
|
||||
return Map.of();
|
||||
}
|
||||
|
||||
Map<String, CharSequenceBlockToken> map = new HashMap<>();
|
||||
|
||||
Lexer lex = new Lexer(content.toCharArray());
|
||||
@@ -40,46 +43,22 @@ public class VillagerProfessionRewriter extends RegistryFieldRewriter<VillagerPr
|
||||
.group(action -> {
|
||||
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 -> { // <name>
|
||||
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<TokenType> 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;
|
||||
}
|
||||
|
@@ -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<? extends Annotation> clazz, ImportCollector collector, String param, String value) {
|
||||
return annotation(new ClassNamed(clazz), collector, param, value);
|
||||
}
|
||||
|
||||
public static String annotation(Class<? extends Annotation> 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<? extends Annotation> 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');
|
||||
|
@@ -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 <V, A, R> void upgrade(Path resourceDir, DataFile<V, A, R> file) throws IOException {
|
||||
Path filePath = Path.of(file.path());
|
||||
SliceResult<A, R> result = file.upgrade(resourceDir.resolve(filePath));
|
||||
if (result.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FlattenSliceResult<String, String> 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());
|
||||
}
|
||||
}
|
||||
}
|
@@ -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)) {
|
@@ -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<T> extends SimpleGenerator {
|
||||
public abstract class OverriddenClassGenerator extends SimpleGenerator {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
protected final Class<? extends T> baseClass;
|
||||
protected final ClassNamed baseClass;
|
||||
protected boolean printWarningOnMissingOverride;
|
||||
|
||||
protected OverriddenClassGenerator(Class<T> baseClass, String className, String packageName) {
|
||||
protected OverriddenClassGenerator(ClassNamed baseClass, String className, String packageName) {
|
||||
super(className, packageName);
|
||||
this.baseClass = baseClass;
|
||||
}
|
||||
|
||||
public Class<? extends T> 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;
|
||||
|
@@ -6,11 +6,11 @@ import javax.lang.model.element.Modifier;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SimpleEnumGenerator<T extends Enum<T>> extends SimpleGenerator {
|
||||
public class SimpleEnumGenerator<E extends Enum<E>> extends SimpleGenerator {
|
||||
|
||||
private final Class<T> enumClass;
|
||||
private final Class<E> enumClass;
|
||||
|
||||
public SimpleEnumGenerator(Class<T> enumClass, String packageName) {
|
||||
public SimpleEnumGenerator(Class<E> enumClass, String packageName) {
|
||||
super(enumClass.getSimpleName(), packageName);
|
||||
this.enumClass = enumClass;
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public class SimpleEnumGenerator<T extends Enum<T>> 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());
|
||||
}
|
||||
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
|
@@ -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<SourceGenerator> generators) {
|
||||
for (Map.Entry<Class<? extends Block>, BlockStateMapping.BlockData> entry : BlockStateMapping.MAPPING.entrySet()) {
|
||||
Class<? extends BlockData> 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<Class<? extends Block>, BlockStateMapping.BlockData> entry : BlockStateMapping.getOrCreate().entrySet()) {
|
||||
generators.add(new CraftBlockDataGenerator(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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<T extends BlockData> extends OverriddenClassGenerator<T> {
|
||||
public class CraftBlockDataGenerator extends OverriddenClassGenerator {
|
||||
|
||||
private final Class<? extends Block> blockClass;
|
||||
private final BlockStateMapping.BlockData blockData;
|
||||
|
||||
protected CraftBlockDataGenerator(Class<? extends Block> blockClass, BlockStateMapping.BlockData blockData, Class<T> baseClass) {
|
||||
super(baseClass, blockData.implName(), Types.BASE_PACKAGE + ".block.impl");
|
||||
protected CraftBlockDataGenerator(Class<? extends Block> 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<? extends Block> 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<T extends BlockData> 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<T extends BlockData> 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<String, List<String>> ambiguousNames = DataFileLoader.get(DataFiles.BLOCK_STATE_AMBIGUOUS_NAMES);
|
||||
for (Map.Entry<String, List<String>> 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<T extends BlockData> 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<T extends BlockData> 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<T extends BlockData> 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<T extends BlockData> 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()) {
|
||||
|
@@ -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<T extends Enum<T> & 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
|
||||
|
@@ -18,14 +18,14 @@ public class IntegerPropertyWriter extends PropertyWriter<Integer> {
|
||||
}
|
||||
|
||||
@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());
|
||||
|
@@ -23,7 +23,7 @@ import org.jspecify.annotations.NullMarked;
|
||||
public class PropertyWriter<T extends Comparable<T>> implements PropertyMaker {
|
||||
|
||||
protected final Property<T> property;
|
||||
private final Supplier<Class<?>> apiClassSupplier;
|
||||
private final Supplier<TypeName> apiClassSupplier;
|
||||
|
||||
protected PropertyWriter(Property<T> property) {
|
||||
this.property = property;
|
||||
@@ -35,16 +35,16 @@ public class PropertyWriter<T extends Comparable<T>> implements PropertyMaker {
|
||||
return TypeName.get(this.property.getClass());
|
||||
}
|
||||
|
||||
protected Class<?> processApiType() {
|
||||
protected TypeName processApiType() {
|
||||
Class<T> 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<T extends Comparable<T>> 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<Class<?>, String> referenceField(Class<? extends Block> from, Property<?> property, Map<Property<?>, 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<Class<?>, String> referenceFieldFromVar(Class<? extends Block> from, Property<?> property, Map<Property<?>, 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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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<T extends Enum<T> & StringRepresentable, A extends Enum<A>> implements PropertyAppender<T, A> {
|
||||
public class EnumValuesAppender<T extends Enum<T> & StringRepresentable> implements PropertyAppender<T> {
|
||||
|
||||
private final EnumProperty<T> property;
|
||||
private final Class<A> apiType;
|
||||
private final TypeName apiType;
|
||||
private final String methodName;
|
||||
|
||||
public EnumValuesAppender(EnumProperty<T> property, Class<A> apiType, String methodName) {
|
||||
public EnumValuesAppender(EnumProperty<T> property, TypeName apiType, String methodName) {
|
||||
this.property = property;
|
||||
this.apiType = apiType;
|
||||
this.methodName = methodName;
|
||||
@@ -30,15 +32,15 @@ public class EnumValuesAppender<T extends Enum<T> & StringRepresentable, A exten
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<A> 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());
|
||||
}
|
||||
|
@@ -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<T extends Comparable<T>, A> extends AppenderBase {
|
||||
public interface PropertyAppender<T extends Comparable<T>> extends AppenderBase {
|
||||
|
||||
Property<T> getProperty();
|
||||
|
||||
Class<A> getApiType();
|
||||
TypeName getApiType();
|
||||
}
|
||||
|
@@ -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<Property<?>, 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<AppenderBase> callback) {
|
||||
|
@@ -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<T extends Comparable<T>, A> extends ConverterBase {
|
||||
public interface Converter<T extends Comparable<T>> extends ConverterBase {
|
||||
|
||||
Property<T> getProperty();
|
||||
|
||||
@Override
|
||||
Class<A> getApiType();
|
||||
TypeName getApiType();
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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<Integer, Note> {
|
||||
public class NoteConverter implements Converter<Integer> {
|
||||
|
||||
@Override
|
||||
public Property<Integer> getProperty() {
|
||||
@@ -16,8 +17,8 @@ public class NoteConverter implements Converter<Integer, Note> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Note> getApiType() {
|
||||
return Note.class;
|
||||
public TypeName getApiType() {
|
||||
return Types.NOTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -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<Integer, BlockFace> {
|
||||
public class RotationConverter implements Converter<Integer> {
|
||||
|
||||
private static final String DIRECTION_VAR = "dir";
|
||||
private static final String ANGLE_VAR = "angle";
|
||||
@@ -22,13 +22,13 @@ public class RotationConverter implements Converter<Integer, BlockFace> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<BlockFace> 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);
|
||||
}
|
||||
|
@@ -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<Property<?>, Field> fields);
|
||||
|
||||
Class<?> getIndexClass();
|
||||
TypeName getIndexClass();
|
||||
|
||||
@Override
|
||||
DataHolderType getType();
|
||||
|
@@ -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<? extends Property<?>> properties, Class<? extends Block> 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<? extends Enum<?>>) 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));
|
||||
}
|
||||
}
|
||||
|
@@ -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<Property<?>, Field> fields) {
|
||||
protected void createSyntheticMap(CodeBlock.Builder code, TypeName indexClass, Map<Property<?>, Field> fields) {
|
||||
// assume indexClass is an enum with its values matching the property names
|
||||
code.add("$T.of(\n", Map.class).indent();
|
||||
Iterator<? extends Property<?>> properties = this.properties.iterator();
|
||||
@@ -64,5 +65,5 @@ public abstract class DataPropertyWriterBase implements DataPropertyMaker {
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Class<?> getIndexClass();
|
||||
public abstract TypeName getIndexClass();
|
||||
}
|
||||
|
@@ -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<? extends Property<?>> properties, Class<? extends Block> 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<? extends Enum<?>>) 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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -48,9 +48,9 @@ public record VirtualField(
|
||||
private final String baseName;
|
||||
private final @Nullable Class<?> keyClass;
|
||||
|
||||
private @Nullable Collection<T> values;
|
||||
private @Nullable Collection<T> properties;
|
||||
|
||||
public FieldValue(String name, TypeToken<T> valueTypeToken, DataHolderType holderType, String baseName, @Nullable Class<?> keyClass) {
|
||||
private FieldValue(String name, TypeToken<T> 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<T> withValues(Collection<T> properties) {
|
||||
this.values = List.copyOf(properties);
|
||||
public FieldValue<T> group(Collection<T> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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<String, String> INDEX_NAMES = ImmutableMap.<String, String>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<Class<? extends BlockData>> HAS_ALLOWED_METHOD = Set.of(
|
||||
MultipleFacing.class,
|
||||
RedstoneWire.class
|
||||
);
|
||||
|
||||
private static boolean supportsExtraMethod(Class<? extends BlockData> clazz) {
|
||||
for (Class<? extends BlockData> 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<? extends Block> block, ClassNamed type) {
|
||||
Set<Property<?>> propertySet = new HashSet<>(BlockStateMapping.STATEFUL_BLOCKS.get(block));
|
||||
for (Map.Entry<ClassNamed, List<BlockPredicate>> 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;
|
||||
}
|
||||
}
|
||||
|
@@ -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) {
|
||||
}
|
@@ -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<Class<Goal>> 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<GoalKey<Mob>> vanillaGoals = classes.stream()
|
||||
Stream<GoalKey> 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.<GoalKey<?>, String>comparing(o -> o.getEntityClass().getSimpleName())
|
||||
.thenComparing(vanillaGoalKey -> vanillaGoalKey.getNamespacedKey().getKey())
|
||||
.sorted(Comparator.<GoalKey, String>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());
|
||||
});
|
||||
|
||||
|
@@ -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<? extends Goal>, Class<? extends Mob>> GENERIC_TYPE_CACHE = new HashMap<>();
|
||||
public static final Map<Class<? extends net.minecraft.world.entity.Mob>, Class<? extends Mob>> BUKKIT_BRIDGE = Util.make(new LinkedHashMap<>(), map -> {
|
||||
//<editor-fold defaultstate="collapsed" desc="bukkitMap Entities">
|
||||
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);
|
||||
//</editor-fold>
|
||||
});
|
||||
private static final Map<Class<? extends Goal>, EntityClassData> GENERIC_TYPE_CACHE = new HashMap<>();
|
||||
|
||||
// TODO these kinda should be checked on each release, in case nested classes changes
|
||||
private static final Map<String, String> NESTED_CLASS_NAMES = Util.make(new HashMap<>(), map -> {
|
||||
private static final Map<String, String> 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<Class<? extends Mob>> 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<? extends Mob> 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 <T extends Mob> GoalKey<T> getKey(Class<? extends Goal> goalClass) {
|
||||
Class<T> type = getGenericType(goalClass);
|
||||
static GoalKey getKey(Class<? extends Goal> 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 <T extends Mob> Class<T> getGenericType(Class<? extends Goal> goalClass) {
|
||||
//noinspection unchecked
|
||||
return (Class<T>) GENERIC_TYPE_CACHE.computeIfAbsent(goalClass, key -> {
|
||||
private static EntityClassData getGenericType(Class<? extends Goal> 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<? extends net.minecraft.world.entity.Mob>) paramType);
|
||||
} else if (RangedAttackMob.class.isAssignableFrom(paramType)) {
|
||||
return RangedEntity.class;
|
||||
return toBukkitClassData((Class<? extends net.minecraft.world.entity.Mob>) 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<? extends Mob> toBukkitClass(Class<? extends net.minecraft.world.entity.Mob> internalClass) {
|
||||
Class<? extends Mob> bukkitClass = BUKKIT_BRIDGE.get(internalClass);
|
||||
if (bukkitClass == null) {
|
||||
private static EntityClassData toBukkitClassData(Class<? extends net.minecraft.world.entity.Mob> 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;
|
||||
}
|
||||
}
|
||||
|
@@ -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<T> extends SimpleGenerator {
|
||||
public class GeneratedKeyType<T> extends SimpleGenerator implements RegistryIdentifiable<T> {
|
||||
|
||||
private final RegistryEntry<T> entry;
|
||||
private final Supplier<Map<ResourceKey<T>, SingleFlagHolder>> experimentalKeys;
|
||||
@@ -47,20 +47,25 @@ public class GeneratedKeyType<T> 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<? extends Registry<T>> 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<T> 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<T> 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<T> 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<T> reference) {
|
||||
|
@@ -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<T> extends SimpleGenerator implements RegistryIdentifiable<T> {
|
||||
|
||||
private final RegistryEntry<?> entry;
|
||||
private final RegistryEntry<T> entry;
|
||||
|
||||
public GeneratedTagKeyType(RegistryEntry<?> entry, String packageName) {
|
||||
public GeneratedTagKeyType(RegistryEntry<T> entry, String packageName) {
|
||||
super(entry.keyClassName().concat("TagKeys"), packageName);
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceKey<? extends Registry<T>> 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");
|
||||
}
|
||||
}
|
||||
|
@@ -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<AnnotationSpec> 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<AnnotationSpec> CLASS_HEADER = List.of(
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user