trial Pose

This commit is contained in:
Lulu13022002 2025-04-20 18:39:21 +02:00
parent b18437b870
commit e31316b7f9
No known key found for this signature in database
GPG Key ID: 491C8F0B8ACDEB01
8 changed files with 104 additions and 287 deletions

View File

@ -5,9 +5,10 @@ package org.bukkit.entity;
*/
public enum Pose {
// Start generate - Pose
// @GeneratedFrom 1.21.5
/**
* Entity is standing normally.
*
*/
STANDING,
/**
@ -78,4 +79,5 @@ public enum Pose {
* Entity is inhaling.
*/
INHALING;
// End generate - Pose
}

View File

@ -20,6 +20,7 @@ import io.papermc.generator.rewriter.types.simple.ItemTypeRewriter;
import io.papermc.generator.rewriter.types.simple.MapPaletteRewriter;
import io.papermc.generator.rewriter.types.simple.MemoryKeyRewriter;
import io.papermc.generator.rewriter.types.simple.StatisticRewriter;
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.rewriter.types.registry.RegistriesArgumentProviderRewriter;
@ -89,6 +90,7 @@ public final class Rewriters {
return EnumValue.builder(name).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

View File

@ -38,13 +38,12 @@ public final class Types {
public static final ClassNamed LOCATION = ClassNamed.of(API_PACKAGE, "Location");
@Deprecated
public static final ClassNamed MUSIC_INSTRUMENT = ClassNamed.of(API_PACKAGE, "MusicInstrument");
public static final ClassNamed FIREWORK_EFFECT = ClassNamed.of(API_PACKAGE, "FireworkEffect");
public static final ClassNamed MATERIAL = ClassNamed.of(API_PACKAGE, "Material");
public static final ClassNamed POSE = ClassNamed.of(API_PACKAGE + ".entity", "Pose");
@Deprecated
public static final ClassNamed VILLAGER = ClassNamed.of(API_PACKAGE + ".entity", "Villager");
@ -78,6 +77,8 @@ public final class Types {
public static final ClassNamed KEY = typed(io.papermc.generator.types.Types.KEY);
public static final ClassNamed TAG_KEY = typed(io.papermc.generator.types.Types.TAG_KEY);
public static final ClassNamed REGISTRY_KEY = typed(io.papermc.generator.types.Types.REGISTRY_KEY);
public static final ClassNamed REGISTRY_EVENTS = ClassNamed.of(PAPER_PACKAGE + ".registry.event", "RegistryEvents");

View File

@ -1,255 +0,0 @@
package io.papermc.generator.rewriter.types.simple.trial;
import com.google.gson.internal.Primitives;
import com.mojang.serialization.Codec;
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 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.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.Unit;
import net.minecraft.world.item.AdventureModePredicate;
import net.minecraft.world.item.Instrument;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.component.BlockItemStateProperties;
import net.minecraft.world.item.component.FireworkExplosion;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.equipment.trim.ArmorTrim;
import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.index.qual.Positive;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.jspecify.annotations.Nullable;
import static io.papermc.generator.utils.Formatting.quoted;
public class DataComponentTypesRewriter extends RegistryFieldRewriter<DataComponentType<?>> {
public DataComponentTypesRewriter() {
super(Registries.DATA_COMPONENT_TYPE, null);
}
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) {
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.PUBLIC).skip(TokenType.STATIC).skip(TokenType.FINAL)
.skipQualifiedName(Predicate.isEqual(TokenType.JAVADOC))
.skipClosure(TokenType.LT, TokenType.GT, true, TokenTaskBuilder::asOptional) // skip generic
.map(TokenType.IDENTIFIER, token -> {
constant.name(((CharSequenceToken) token).value());
})
.skip(TokenType.IDENTIFIER)
.skipClosure(TokenType.LPAREN, TokenType.RPAREN, true)
.map(TokenType.SECO, $ -> {
if (constant.isComplete()) {
map.put(constant.name(), constant.javadocs());
}
});
}, TokenTaskBuilder::asRepeatable)
.executeOrThrow();
return map;
}
private static final Set<DataComponentType<?>> UNSUPPORTED_TYPES = Set.of(
DataComponents.CUSTOM_DATA,
DataComponents.CREATIVE_SLOT_LOCK,
DataComponents.DEBUG_STICK_STATE,
DataComponents.ENTITY_DATA,
DataComponents.BUCKET_ENTITY_DATA,
DataComponents.BLOCK_ENTITY_DATA,
DataComponents.BEES,
DataComponents.LOCK
);
private static final Map<ResourceKey<DataComponentType<?>>, Type> COMPONENT_GENERIC_TYPES = RegistryEntries.byRegistryKey(Registries.DATA_COMPONENT_TYPE).getFields(field -> {
if (field.getGenericType() instanceof ParameterizedType complexType && complexType.getActualTypeArguments().length == 1) {
return complexType.getActualTypeArguments()[0];
}
return null;
});
private static final Map<Class<?>, ClassNamed> API_BRIDGE = Map.of(
Component.class, Types.COMPONENT,
ResourceLocation.class, Types.KEY,
Instrument.class, Types.MUSIC_INSTRUMENT,
FireworkExplosion.class, Types.FIREWORK_EFFECT,
Rarity.class, Types.ITEM_RARITY,
ArmorTrim.class, Types.ITEM_ARMOR_TRIM,
// renames
BlockItemStateProperties.class, Types.BLOCK_ITEM_DATA_PROPERTIES,
AdventureModePredicate.class, Types.ITEM_ADVENTURE_PREDICATE
);
@Deprecated
private static final Map<String, String> FIELD_RENAMES = Map.of(
"BLOCK_STATE", "BLOCK_DATA"
);
@Override
protected void insert(SearchMetadata metadata, StringBuilder builder) {
this.javadocsPerConstant = parseConstantJavadocs(metadata.replacedContent());
super.insert(metadata, builder);
}
@Override
protected boolean canPrintField(Holder.Reference<DataComponentType<?>> reference) {
return !UNSUPPORTED_TYPES.contains(reference.value());
}
@Override
protected void rewriteJavadocs(Holder.Reference<DataComponentType<?>> 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');
}
}
private boolean isValued;
private Class<?> handleParameterizedType(Type type) {
if (type instanceof ParameterizedType complexType) {
Type[] args = complexType.getActualTypeArguments();
if (args.length != 1) {
throw new UnsupportedOperationException("Unsupported type " + complexType);
}
Class<?> baseClass = ClassHelper.eraseType(complexType);
if (baseClass == Holder.class) {
return ClassHelper.eraseType(args[0]);
}
if (baseClass == ResourceKey.class) {
Class<?> componentClass = ClassHelper.eraseType(args[0]);
if (componentClass == Recipe.class) {
return ResourceLocation.class; // special case recipe registry is not really a thing
}
}
}
throw new UnsupportedOperationException("Unsupported type " + type);
}
@Override
protected String rewriteFieldType(Holder.Reference<DataComponentType<?>> reference) {
Type componentType = COMPONENT_GENERIC_TYPES.get(reference.key());
this.isValued = componentType != Unit.class;
if (this.isValued) {
Class<?> componentClass = null;
UnaryOperator<String> tryToWrap = UnaryOperator.identity();
if (!reference.value().isTransient()) {
final Class<? extends Annotation> annotation = guessAnnotationType(reference.value().codecOrThrow());
if (annotation != null) {
tryToWrap = value -> "@%s %s".formatted(this.importCollector.getShortName(annotation), value);
}
}
if (componentType instanceof Class<?> clazz) {
componentClass = clazz;
} else if (componentType instanceof ParameterizedType complexType) {
Type[] args = complexType.getActualTypeArguments();
if (args.length != 1) {
throw new UnsupportedOperationException("Unsupported type " + componentType);
}
Class<?> baseClass = ClassHelper.eraseType(complexType);
if (baseClass == List.class) {
tryToWrap = value -> "%s<%s>".formatted(this.importCollector.getShortName(List.class), value);
componentClass = this.handleParameterizedType(args[0]);
} else {
componentClass = this.handleParameterizedType(complexType);
}
}
if (componentClass == null) {
throw new UnsupportedOperationException("Unsupported type " + componentType);
}
ClassNamed apiComponentClass = null;
if (Primitives.isWrapperType(componentClass)) {
apiComponentClass = new ClassNamed(componentClass);
} else if (API_BRIDGE.containsKey(componentClass)) {
apiComponentClass = API_BRIDGE.get(componentClass);
}
final ClassNamed finalClass;
if (apiComponentClass == null) {
finalClass = this.classNamedView.tryFindFirst(io.papermc.typewriter.util.ClassHelper.retrieveFullNestedName(componentClass)).orElse(null);
} else {
finalClass = apiComponentClass;
}
return "%s.%s<%s>".formatted(
Types.DATA_COMPONENT_VALUED.topLevel().simpleName(),
Types.DATA_COMPONENT_VALUED.simpleName(),
tryToWrap.apply(Optional.ofNullable(finalClass).map(this.importCollector::getShortName).orElse(componentClass.getSimpleName()))
);
} else {
return "%s.%s".formatted(
Types.DATA_COMPONENT_NON_VALUED.topLevel().simpleName(),
Types.DATA_COMPONENT_NON_VALUED.simpleName()
);
}
}
private @Nullable Class<? extends Annotation> guessAnnotationType(Codec<?> codec) {
Class<? extends Annotation> annotation = null; // int range maybe?
if (codec == ExtraCodecs.POSITIVE_INT || codec == ExtraCodecs.POSITIVE_FLOAT) {
annotation = Positive.class;
} else if (codec == ExtraCodecs.NON_NEGATIVE_INT || codec == ExtraCodecs.NON_NEGATIVE_FLOAT) {
annotation = NonNegative.class;
}
return annotation;
}
@Override
protected String rewriteFieldName(Holder.Reference<DataComponentType<?>> reference) {
String keyedName = super.rewriteFieldName(reference);
return FIELD_RENAMES.getOrDefault(keyedName, keyedName);
}
@Override
protected String rewriteFieldValue(Holder.Reference<DataComponentType<?>> reference) {
return "%s(%s)".formatted(this.isValued ? "valued" : "unvalued", quoted(reference.key().location().getPath()));
}
}

View File

@ -0,0 +1,93 @@
package io.papermc.generator.rewriter.types.simple.trial;
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.preset.EnumCloneRewriter;
import io.papermc.typewriter.preset.model.EnumValue;
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.world.entity.Pose;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public class PoseRewriter extends EnumCloneRewriter<Pose> {
public PoseRewriter() {
super(Pose.class);
}
private static final Set<TokenType> FORMAT_TOKENS = EnumSet.of(
TokenType.COMMENT,
TokenType.SINGLE_COMMENT
);
private static final Set<TokenType> END_VALUE_MARKERS = EnumSet.of(
TokenType.CO,
TokenType.SECO
);
private @MonotonicNonNull Map<String, CharSequenceBlockToken> javadocsPerConstant;
private Map<String, CharSequenceBlockToken> parseConstantJavadocs(String content) {
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)
.map(TokenType.IDENTIFIER, token -> {
constant.name(((CharSequenceToken) token).value());
})
.skipClosure(TokenType.LPAREN, TokenType.RPAREN, true, TokenTaskBuilder::asOptional)
.skipClosure(TokenType.LSCOPE, TokenType.RSCOPE, true, TokenTaskBuilder::asOptional)
.map(END_VALUE_MARKERS::contains, $ -> {
// this part will fail for the last entry for enum without end (,;)
if (constant.isComplete()) {
map.put(constant.name(), constant.javadocs());
}
});
}, TokenTaskBuilder::asRepeatable)
.executeOrThrow();
return map;
}
private @MonotonicNonNull SearchMetadata metadata;
private static final Map<String, String> RENAMES = Map.of(
Pose.CROUCHING.name(), "SNEAKING"
);
@Override
protected void insert(SearchMetadata metadata, StringBuilder builder) {
this.javadocsPerConstant = parseConstantJavadocs(metadata.replacedContent());
this.metadata = metadata;
super.insert(metadata, builder);
}
@Override
protected EnumValue.Builder rewriteEnumValue(Pose item) {
return super.rewriteEnumValue(item).rename(name -> RENAMES.getOrDefault(name, name));
}
@Override
protected void appendEnumValue(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);
}
}

View File

@ -56,30 +56,6 @@ public class VillagerProfessionRewriter extends RegistryFieldRewriter<VillagerPr
});
}, 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;
}

View File

@ -180,7 +180,7 @@ public class PrepareInputFiles {
LOGGER.info("Added the following elements in {}: {}", filePath, result.added());
}
if (!result.removed().isEmpty()) {
LOGGER.info("Removed the following keys in {}: {}", filePath, result.removed());
LOGGER.warn("Removed the following keys in {}: {}", filePath, result.removed());
}
}
}

View File

@ -60,14 +60,12 @@ public class BlockStatePropertyTest extends BootstrapTest {
@Test
public void testBridge() {
Set<Class<? extends Enum<? extends StringRepresentable>>> missingApiEquivalents = new HashSet<>();
Set<Class<? extends Enum<? extends StringRepresentable>>> registeredTypes = new HashSet<>(BlockStateMapping.ENUM_PROPERTY_TYPES.keySet());
for (Class<? extends Enum<? extends StringRepresentable>> type : ENUM_PROPERTY_TYPES) {
if (!registeredTypes.remove(type)) {
if (!BlockStateMapping.ENUM_PROPERTY_TYPES.containsKey(type)) {
missingApiEquivalents.add(type);
}
}
Assertions.assertTrue(missingApiEquivalents.isEmpty(), () -> "Missing some api equivalent in the block state mapping enum bridge (BlockStateMapping#ENUM_PROPERTY_TYPES) : " + missingApiEquivalents.stream().map(Class::getCanonicalName).collect(Collectors.joining(", ")));
Assertions.assertTrue(registeredTypes.isEmpty(), () -> "Extra api equivalent in the block state mapping enum bridge (BlockStateMapping#ENUM_PROPERTY_TYPES) : " + registeredTypes.stream().map(Class::getCanonicalName).collect(Collectors.joining(", ")));
}
}