update typewriter and split experimental element ids per feature flag

This commit is contained in:
Lulu13022002 2024-11-08 19:45:22 +01:00
parent 5767cee34a
commit ebf6610291
No known key found for this signature in database
GPG Key ID: 491C8F0B8ACDEB01
48 changed files with 406 additions and 507 deletions

View File

@ -30,7 +30,7 @@ dependencies {
val generatedApiPath = file("generatedApi")
val generatedServerPath = file("generatedServer")
tasks.register<JavaExec>("generate") {
val generate by tasks.registering(JavaExec::class) {
dependsOn(tasks.check)
mainClass.set("io.papermc.generator.Main")
classpath(sourceSets.main.map { it.runtimeClasspath })
@ -40,6 +40,13 @@ tasks.register<JavaExec>("generate") {
project(":paper-server").sourceSets["main"].java.srcDirs.first().toString())
}
generate.configure {
delete(generatedApiPath, generatedServerPath)
// the module depends on paper-api but generate into the project which cause conflict
// ideally this module would only depend on vanilla source in the long
// run
}
tasks.register<JavaExec>("scanOldGeneratedSourceCode") {
mainClass.set("io.papermc.generator.rewriter.OldGeneratedCodeTest")
classpath(sourceSets.test.map { it.runtimeClasspath })

View File

@ -5,7 +5,7 @@ import com.mojang.logging.LogUtils;
import io.papermc.generator.rewriter.registration.PaperPatternSourceSetRewriter;
import io.papermc.generator.rewriter.registration.PatternSourceSetRewriter;
import io.papermc.generator.types.SourceGenerator;
import io.papermc.generator.utils.experimental.TagCollector;
import io.papermc.generator.utils.experimental.ExperimentalCollector;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@ -66,7 +66,7 @@ public final class Main {
MoreExecutors.directExecutor()
).join();
reloadableServerResources.updateStaticRegistryTags();
EXPERIMENTAL_TAGS = TagCollector.grabExperimental(resourceManager);
EXPERIMENTAL_TAGS = ExperimentalCollector.collectTags(resourceManager);
}
private Main() {

View File

@ -75,7 +75,7 @@ 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.typewriter.utils.Formatting.quoted;
import static io.papermc.typewriter.util.Formatting.quoted;
@NullMarked
public final class Rewriters {

View File

@ -6,6 +6,7 @@ import io.papermc.paper.registry.data.GameEventRegistryEntry;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
@ -13,6 +14,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import net.minecraft.core.Registry;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.core.registries.Registries;
@ -38,6 +40,7 @@ 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.levelgen.structure.BuiltinStructures;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.saveddata.maps.MapDecorationTypes;
import org.bukkit.Art;
@ -70,36 +73,29 @@ import org.bukkit.map.MapCursor;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
public final class RegistryEntries {
private static <T> RegistryEntry<T> entry(ResourceKey<? extends Registry<T>> registryKey, @Nullable Class<?> registryConstantClass, Class<? extends Keyed> apiClass, String implClass) {
return new RegistryEntry<>(registryKey, (RegistryKeyField<T>) REGISTRY_KEY_FIELDS.get(registryKey), registryConstantClass, apiClass, implClass);
private static <T> RegistryEntry<T> entry(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);
}
// CraftBukkit entry where implementation start by "Craft"
private static <T> RegistryEntry<T> entry(ResourceKey<? extends Registry<T>> registryKey, @Nullable Class<?> registryConstantClass, Class<? extends Keyed> apiClass) {
return entry(registryKey, registryConstantClass, "Craft", apiClass);
private static <T> RegistryEntry<T> entry(ResourceKey<? extends Registry<T>> registryKey, Class<?> holderElementsClass, Class<? extends Keyed> apiClass) {
return entry(registryKey, holderElementsClass, "Craft", apiClass);
}
private static <T> RegistryEntry<T> entry(ResourceKey<? extends Registry<T>> registryKey, @Nullable Class<?> registryConstantClass, String implPrefix, Class<? extends Keyed> apiClass) {
String name = io.papermc.typewriter.utils.ClassHelper.retrieveFullNestedName(apiClass);
private static <T> RegistryEntry<T> entry(ResourceKey<? extends Registry<T>> registryKey, Class<?> holderElementsClass, String implPrefix, Class<? extends Keyed> apiClass) {
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, registryConstantClass, apiClass, implPrefix.concat(apiClass.getSimpleName()));
return new RegistryEntry<>(registryKey, registryKeyField, holderElementsClass, apiClass, implPrefix.concat(apiClass.getSimpleName()));
}
StringBuilder implName = new StringBuilder(name.length() + implPrefix.length() * classes.length);
implName.append(implPrefix.concat(classes[0]));
for (int i = 1; i < classes.length; i++) {
implName.append('.');
implName.append(implPrefix.concat(classes[i]));
}
return new RegistryEntry<>(registryKey, registryKeyField, registryConstantClass, apiClass,implName.toString());
String implName = Arrays.stream(classes).map(implPrefix::concat).collect(Collectors.joining("."));
return new RegistryEntry<>(registryKey, registryKeyField, holderElementsClass, apiClass, implName);
}
private static final Map<ResourceKey<? extends Registry<?>>, RegistryKeyField<?>> REGISTRY_KEY_FIELDS;
@ -148,7 +144,7 @@ public final class RegistryEntries {
public static final List<RegistryEntry<?>> DATA_DRIVEN = List.of(
entry(Registries.BIOME, Biomes.class, Biome.class).delayed(),
entry(Registries.STRUCTURE, null, Structure.class).delayed(),
entry(Registries.STRUCTURE, BuiltinStructures.class, Structure.class).delayed(),
entry(Registries.TRIM_MATERIAL, TrimMaterials.class, TrimMaterial.class).delayed(),
entry(Registries.TRIM_PATTERN, TrimPatterns.class, TrimPattern.class).delayed(),
entry(Registries.DAMAGE_TYPE, DamageTypes.class, DamageType.class).delayed(),

View File

@ -22,8 +22,8 @@ public final class RegistryEntry<T> {
private final ResourceKey<? extends Registry<T>> registryKey;
private final RegistryKeyField<T> registryKeyField;
private final Class<T> registryElementClass;
private final @Nullable Class<?> registryConstantClass;
private final Class<T> elementClass;
private final Class<?> holderElementsClass;
private final Class<? extends Keyed> apiClass; // TODO remove Keyed
private final String implClass;
@ -37,11 +37,11 @@ public final class RegistryEntry<T> {
private @Nullable Map<ResourceKey<T>, String> fieldNames;
public RegistryEntry(ResourceKey<? extends Registry<T>> registryKey, RegistryKeyField<T> registryKeyField, @Nullable Class<?> registryConstantClass, Class<? extends Keyed> apiClass, String implClass) {
public RegistryEntry(ResourceKey<? extends Registry<T>> registryKey, RegistryKeyField<T> registryKeyField, Class<?> holderElementsClass, Class<? extends Keyed> apiClass, String implClass) {
this.registryKey = registryKey;
this.registryKeyField = registryKeyField;
this.registryElementClass = registryKeyField.elementClass();
this.registryConstantClass = registryConstantClass;
this.elementClass = registryKeyField.elementClass();
this.holderElementsClass = holderElementsClass;
this.apiClass = apiClass;
this.implClass = implClass;
}
@ -112,7 +112,7 @@ public final class RegistryEntry<T> {
return this.apiClass.getSimpleName();
}
return this.registryElementClass.getSimpleName();
return this.elementClass.getSimpleName();
}
public boolean allowCustomKeys() {
@ -122,18 +122,18 @@ public final class RegistryEntry<T> {
private <TO> Map<ResourceKey<T>, TO> getFields(Map<ResourceKey<T>, TO> map, Function<Field, @Nullable TO> transform) {
Registry<T> registry = this.registry();
try {
for (Field field : this.registryConstantClass.getDeclaredFields()) {
if (!ResourceKey.class.isAssignableFrom(field.getType()) && !Holder.Reference.class.isAssignableFrom(field.getType()) && !this.registryElementClass.isAssignableFrom(field.getType())) {
for (Field field : this.holderElementsClass.getDeclaredFields()) {
if (!ResourceKey.class.isAssignableFrom(field.getType()) && !Holder.Reference.class.isAssignableFrom(field.getType()) && !this.elementClass.isAssignableFrom(field.getType())) {
continue;
}
if (ClassHelper.isStaticConstant(field, Modifier.PUBLIC)) {
ResourceKey<T> key = null;
if (this.registryElementClass.isAssignableFrom(field.getType())) {
key = registry.getResourceKey(this.registryElementClass.cast(field.get(null))).orElseThrow();
if (this.elementClass.isAssignableFrom(field.getType())) {
key = registry.getResourceKey(this.elementClass.cast(field.get(null))).orElseThrow();
} else {
if (field.getGenericType() instanceof ParameterizedType complexType && complexType.getActualTypeArguments().length == 1 &&
complexType.getActualTypeArguments()[0] == this.registryElementClass) {
complexType.getActualTypeArguments()[0] == this.elementClass) {
if (Holder.Reference.class.isAssignableFrom(field.getType())) {
key = ((Holder.Reference<T>) field.get(null)).key();
@ -164,10 +164,6 @@ public final class RegistryEntry<T> {
}
public <TO> Map<ResourceKey<T>, TO> getFields(Function<Field, @Nullable TO> transform) {
if (this.registryConstantClass == null) {
return Collections.emptyMap();
}
return Collections.unmodifiableMap(this.getFields(new IdentityHashMap<>(), transform));
}

View File

@ -4,12 +4,11 @@ import com.google.common.base.Suppliers;
import io.papermc.generator.Main;
import io.papermc.generator.rewriter.utils.Annotations;
import io.papermc.generator.utils.Formatting;
import io.papermc.generator.utils.RegistryUtils;
import io.papermc.generator.utils.experimental.FlagHolders;
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 java.util.Set;
import java.util.Map;
import java.util.function.Supplier;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
@ -19,13 +18,13 @@ import net.minecraft.world.flag.FeatureFlags;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import static io.papermc.typewriter.utils.Formatting.quoted;
import static io.papermc.typewriter.util.Formatting.quoted;
@NullMarked
public class EnumRegistryRewriter<T> extends EnumRewriter<Holder.Reference<T>> {
private final Registry<T> registry;
private final Supplier<Set<ResourceKey<T>>> experimentalKeys;
private final Supplier<Map<ResourceKey<T>, SingleFlagHolder>> experimentalKeys;
private final boolean isFilteredRegistry;
private final boolean hasKeyArgument;
@ -35,7 +34,7 @@ public class EnumRegistryRewriter<T> extends EnumRewriter<Holder.Reference<T>> {
protected EnumRegistryRewriter(ResourceKey<? extends Registry<T>> registryKey, boolean hasKeyArgument) {
this.registry = Main.REGISTRY_ACCESS.lookupOrThrow(registryKey);
this.experimentalKeys = Suppliers.memoize(() -> RegistryUtils.collectExperimentalDataDrivenKeys(this.registry));
this.experimentalKeys = Suppliers.memoize(() -> ExperimentalCollector.collectDataDrivenElementIds(this.registry));
this.isFilteredRegistry = FeatureElement.FILTERED_REGISTRIES.contains(registryKey);
this.hasKeyArgument = hasKeyArgument;
}
@ -74,9 +73,7 @@ public class EnumRegistryRewriter<T> extends EnumRewriter<Holder.Reference<T>> {
}
} else {
// data-driven registry
if (this.experimentalKeys.get().contains(reference.key())) {
return FlagHolders.NEXT_UPDATE;
}
return this.experimentalKeys.get().get(reference.key());
}
return null;
}

View File

@ -16,7 +16,7 @@ import org.jspecify.annotations.NullMarked;
import org.slf4j.Logger;
import static io.papermc.generator.rewriter.utils.Annotations.annotation;
import static io.papermc.typewriter.utils.Formatting.quoted;
import static io.papermc.typewriter.util.Formatting.quoted;
@NullMarked
public class FeatureFlagRewriter extends SearchReplaceRewriter {

View File

@ -14,7 +14,7 @@ public class PaperFeatureFlagMapping extends SearchReplaceRewriter {
@Override
protected void insert(SearchMetadata metadata, StringBuilder builder) {
Iterator<ResourceLocation> flagIterator = FeatureFlags.REGISTRY.toNames(FeatureFlags.REGISTRY.allFlags()).stream().sorted(Formatting.alphabeticKeyOrder(name -> name.getPath())).iterator();
Iterator<ResourceLocation> flagIterator = FeatureFlags.REGISTRY.toNames(FeatureFlags.REGISTRY.allFlags()).stream().sorted(Formatting.alphabeticKeyOrder(ResourceLocation::getPath)).iterator();
while (flagIterator.hasNext()) {
ResourceLocation name = flagIterator.next();

View File

@ -6,15 +6,14 @@ import com.mojang.logging.LogUtils;
import io.papermc.generator.Main;
import io.papermc.generator.rewriter.utils.Annotations;
import io.papermc.generator.utils.Formatting;
import io.papermc.generator.utils.RegistryUtils;
import io.papermc.generator.utils.experimental.FlagHolders;
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.Set;
import java.util.Map;
import java.util.function.Supplier;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
@ -26,7 +25,7 @@ import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import static io.papermc.typewriter.utils.Formatting.quoted;
import static io.papermc.typewriter.util.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;
@ -37,7 +36,7 @@ public class RegistryFieldRewriter<T> extends SearchReplaceRewriter {
private static final Logger LOGGER = LogUtils.getLogger();
private final Registry<T> registry;
private final Supplier<Set<ResourceKey<T>>> experimentalKeys;
private final Supplier<Map<ResourceKey<T>, SingleFlagHolder>> experimentalKeys;
private final boolean isFilteredRegistry;
private final @Nullable String fetchMethod;
@ -45,7 +44,7 @@ public class RegistryFieldRewriter<T> extends SearchReplaceRewriter {
public RegistryFieldRewriter(ResourceKey<? extends Registry<T>> registryKey, @Nullable String fetchMethod) {
this.registry = Main.REGISTRY_ACCESS.lookupOrThrow(registryKey);
this.experimentalKeys = Suppliers.memoize(() -> RegistryUtils.collectExperimentalDataDrivenKeys(this.registry));
this.experimentalKeys = Suppliers.memoize(() -> ExperimentalCollector.collectDataDrivenElementIds(this.registry));
this.isFilteredRegistry = FeatureElement.FILTERED_REGISTRIES.contains(registryKey);
this.fetchMethod = fetchMethod;
}
@ -127,9 +126,7 @@ public class RegistryFieldRewriter<T> extends SearchReplaceRewriter {
}
} else {
// data-driven registry
if (this.experimentalKeys.get().contains(reference.key())) {
return FlagHolders.NEXT_UPDATE;
}
return this.experimentalKeys.get().get(reference.key());
}
return null;
}

View File

@ -18,7 +18,7 @@ import org.bukkit.Tag;
import org.jspecify.annotations.NullMarked;
import org.slf4j.Logger;
import static io.papermc.typewriter.utils.Formatting.quoted;
import static io.papermc.typewriter.util.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;

View File

@ -21,7 +21,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.entity.EntityType;
import org.jspecify.annotations.NullMarked;
import static io.papermc.typewriter.utils.Formatting.quoted;
import static io.papermc.typewriter.util.Formatting.quoted;
@NullMarked
public class TagRewriter extends SearchReplaceRewriter {

View File

@ -2,7 +2,7 @@ package io.papermc.generator.rewriter.types.simple;
import io.papermc.generator.rewriter.types.registry.RegistryFieldRewriter;
import io.papermc.generator.utils.BlockStateMapping;
import io.papermc.typewriter.utils.ClassHelper;
import io.papermc.typewriter.util.ClassHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.block.Block;

View File

@ -20,7 +20,7 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob;
import static io.papermc.typewriter.utils.Formatting.quoted;
import static io.papermc.typewriter.util.Formatting.quoted;
public class EntityTypeRewriter extends EnumRegistryRewriter<EntityType<?>> {
@ -146,11 +146,11 @@ public class EntityTypeRewriter extends EnumRegistryRewriter<EntityType<?>> {
@Override
protected EnumValue.Builder rewriteEnumValue(Holder.Reference<EntityType<?>> reference) {
String path = reference.key().location().getPath();
List<String> arguments = Util.make(new ArrayList<>(), args -> {
args.add(quoted(path));
args.add(toBukkitClass(reference).concat(".class"));
args.add(Integer.toString(LEGACY_ID.getOrDefault(reference.value(), -1)));
});
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)));
if (!reference.value().canSummon()) {
arguments.add(Boolean.FALSE.toString());
}

View File

@ -1,7 +1,7 @@
package io.papermc.generator.rewriter.types.simple;
import io.papermc.generator.rewriter.types.registry.RegistryFieldRewriter;
import io.papermc.typewriter.utils.ClassHelper;
import io.papermc.typewriter.util.ClassHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.Item;

View File

@ -25,7 +25,7 @@ import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import static io.papermc.typewriter.utils.Formatting.quoted;
import static io.papermc.typewriter.util.Formatting.quoted;
public class MemoryKeyRewriter extends RegistryFieldRewriter<MemoryModuleType<?>> {

View File

@ -22,7 +22,7 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import org.bukkit.Statistic;
import static io.papermc.typewriter.utils.Formatting.quoted;
import static io.papermc.typewriter.util.Formatting.quoted;
@Deprecated(forRemoval = true)
public class StatisticRewriter {
@ -59,7 +59,8 @@ public class StatisticRewriter {
.put("INTERACT_WITH_FURNACE", "FURNACE_INTERACTION")
.put("INTERACT_WITH_CRAFTING_TABLE", "CRAFTING_TABLE_INTERACTION")
.put("OPEN_CHEST", "CHEST_OPENED")
.put("OPEN_SHULKER_BOX", "SHULKER_BOX_OPENED").build();
.put("OPEN_SHULKER_BOX", "SHULKER_BOX_OPENED")
.build();
public static class Custom extends EnumRegistryRewriter<ResourceLocation> {

View File

@ -3,13 +3,11 @@ package io.papermc.generator.rewriter.types.simple;
import io.papermc.generator.rewriter.types.registry.RegistryFieldRewriter;
import io.papermc.generator.utils.Formatting;
import io.papermc.typewriter.parser.Lexer;
import io.papermc.typewriter.parser.exception.ParserException;
import io.papermc.typewriter.parser.token.CharSequenceBlockToken;
import io.papermc.typewriter.parser.token.CharSequenceToken;
import io.papermc.typewriter.parser.token.Token;
import io.papermc.typewriter.parser.token.TokenType;
import io.papermc.typewriter.parser.SequenceTokens;
import io.papermc.typewriter.replace.SearchMetadata;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
@ -20,7 +18,6 @@ import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.npc.VillagerProfession;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.Nullable;
@ApiStatus.Experimental
public class VillagerProfessionRewriter extends RegistryFieldRewriter<VillagerProfession> {
@ -37,108 +34,82 @@ public class VillagerProfessionRewriter extends RegistryFieldRewriter<VillagerPr
private @MonotonicNonNull Map<String, List<String>> javadocsPerConstant;
private static class ConstantInfo {
private @MonotonicNonNull String constantName;
private @MonotonicNonNull List<String> javadocs;
public void constantName(String name) {
this.constantName = name;
}
public void javadocs(List<String> javadocs) {
this.javadocs = javadocs;
}
public String constantName() {
return this.constantName;
}
public List<String> javadocs() {
return this.javadocs;
}
public boolean isEmpty() {
return this.constantName == null || this.javadocs == null;
}
}
private Map<String, List<String>> parseConstantJavadocs(String content) {
Map<String, List<String>> map = new HashMap<>();
Lexer lex = new Lexer(content.toCharArray());
String constantName = null;
List<String> javadocs = null;
boolean firstId = true;
while (lex.canRead()) {
Token token = lex.readToken();
if (token.type() == TokenType.EOI) {
break;
}
if (token.type() == TokenType.SECO) {
if (constantName != null && javadocs != null) {
map.put(constantName, new ArrayList<>(javadocs));
}
firstId = true;
constantName = null;
javadocs = null;
continue;
}
if (FORMAT_TOKENS.contains(token.type())) {
continue;
}
if (token.type() == TokenType.LPAREN && constantName != null) {
if (!this.skipClosure(lex)) {
return map;
}
continue;
}
if (token.type() == TokenType.JAVADOC) {
javadocs = ((CharSequenceBlockToken) token).value();
} else if (token.type() == TokenType.PUBLIC || token.type() == TokenType.STATIC || token.type() == TokenType.FINAL) {
// should check duplicate per statement
continue; // ignore
} else if (token.type() == TokenType.IDENTIFIER && constantName == null) {
if (firstId) {
Token nextToken = this.skipTypeName(lex);
if (nextToken != null && nextToken.type() == TokenType.IDENTIFIER) {
token = nextToken;
}
firstId = false;
}
constantName = ((CharSequenceToken) token).value();
}
}
SequenceTokens.wrap(lex, FORMAT_TOKENS)
.group(action -> {
ConstantInfo info = new ConstantInfo();
action
.map(TokenType.JAVADOC, token -> {
info.javadocs(((CharSequenceBlockToken) token).value());
}, SequenceTokens.TokenTask::asOptional)
.skipQualifiedName(Set.of(TokenType.JAVADOC))
.map(TokenType.IDENTIFIER, token -> {
info.constantName(((CharSequenceToken) token).value());
})
.skip(TokenType.IDENTIFIER)
.skipClosure(TokenType.LPAREN, TokenType.RPAREN, true)
.map(TokenType.SECO, $ -> {
if (!info.isEmpty()) {
map.put(info.constantName(), info.javadocs());
}
});
}, SequenceTokens.TokenTask::asRepeatable)
.execute();
/*
for enums:
SequenceTokens.wrap(lex, FORMAT_TOKENS)
.group(action -> {
ConstantInfo info = new ConstantInfo();
action
.map(TokenType.JAVADOC, token -> {
info.javadocs(((CharSequenceBlockToken) token).value());
}, SequenceTokens.TokenTask::asOptional)
.map(TokenType.IDENTIFIER, token -> {
info.constantName(((CharSequenceToken) token).value());
})
.skipClosure(TokenType.LPAREN, TokenType.RPAREN, true)
.skipClosure(TokenType.LSCOPE, TokenType.RSCOPE, true)
.mapMulti(Set.of(TokenType.CO, TokenType.SECO), $ -> {
// this part will probably fail for the last entry for enum without end (,;)
if (!info.isEmpty()) {
map.put(info.constantName(), info.javadocs());
}
});
}, SequenceTokens.TokenTask::asRepeatable)
.execute();
*/
return map;
}
private boolean skipClosure(Lexer lex) {
int parenDepth = 1;
while (lex.canRead()) {
Token nestedToken = lex.readToken();
if (nestedToken.type() == TokenType.EOI) {
return false;
}
if (nestedToken.type() == TokenType.LPAREN) {
parenDepth++;
} else if (nestedToken.type() == TokenType.RPAREN) {
parenDepth--;
}
if (parenDepth == 0) {
break;
}
if (parenDepth < 0) {
throw new ParserException("Unbalanced parenthesis", nestedToken);
}
}
return true;
}
private @Nullable Token skipTypeName(Lexer lex) {
boolean expectDot = true;
while (lex.canRead()) {
Token token = lex.readToken();
if (token.type() == TokenType.EOI) {
break;
}
if (FORMAT_TOKENS.contains(token.type()) || token.type() == TokenType.JAVADOC) {
continue; // ignore intrusive comments inside the name
}
if (token.type() == (expectDot ? TokenType.DOT : TokenType.IDENTIFIER)) {
expectDot = !expectDot;
} else {
return token;
}
}
return null;
}
@Override
protected void insert(SearchMetadata metadata, StringBuilder builder) {
this.javadocsPerConstant = parseConstantJavadocs(metadata.replacedContent());

View File

@ -2,7 +2,7 @@ package io.papermc.generator.rewriter.utils;
import io.papermc.generator.utils.experimental.SingleFlagHolder;
import io.papermc.typewriter.context.ImportCollector;
import io.papermc.typewriter.utils.ClassHelper;
import io.papermc.typewriter.util.ClassHelper;
import java.lang.annotation.Annotation;
import org.bukkit.MinecraftExperimental;
import org.jetbrains.annotations.ApiStatus;

View File

@ -10,14 +10,14 @@ import org.slf4j.Logger;
import static javax.lang.model.element.Modifier.PUBLIC;
@NullMarked
public abstract class StructuredGenerator<T> extends SimpleGenerator {
public abstract class OverriddenClassGenerator<T> extends SimpleGenerator {
private static final Logger LOGGER = LogUtils.getLogger();
protected final Class<? extends T> baseClass;
protected boolean printWarningOnMissingOverride;
protected StructuredGenerator(Class<T> baseClass, String className, String packageName) {
protected OverriddenClassGenerator(Class<T> baseClass, String className, String packageName) {
super(className, packageName);
this.baseClass = baseClass;
}

View File

@ -8,7 +8,7 @@ import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeSpec;
import io.papermc.generator.types.StructuredGenerator;
import io.papermc.generator.types.OverriddenClassGenerator;
import io.papermc.generator.types.Types;
import io.papermc.generator.types.craftblockdata.property.PropertyMaker;
import io.papermc.generator.types.craftblockdata.property.PropertyWriter;
@ -46,7 +46,7 @@ import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
@NullMarked
public class CraftBlockDataGenerator<T extends BlockData> extends StructuredGenerator<T> {
public class CraftBlockDataGenerator<T extends BlockData> extends OverriddenClassGenerator<T> {
private final Class<? extends Block> blockClass;
private final BlockStateMapping.BlockData blockData;
@ -66,7 +66,7 @@ public class CraftBlockDataGenerator<T extends BlockData> extends StructuredGene
.put(BlockStateProperties.EYE, keywordGet("has"))
.put(BlockStateProperties.BERRIES, keywordGet("has")) // spigot method rename
// data holder keywords is only needed for the first property they hold
.put(ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.get(0), keywordGet("is"))
.put(ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.getFirst(), keywordGet("is"))
.build();
private static final Map<Property<?>, BiConsumer<ParameterSpec, MethodSpec.Builder>> SETTER_PRECONDITIONS = Map.of(

View File

@ -3,7 +3,7 @@ package io.papermc.generator.types.craftblockdata.property;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
import io.papermc.generator.types.StructuredGenerator;
import io.papermc.generator.types.craftblockdata.CraftBlockDataGenerator;
import io.papermc.generator.types.craftblockdata.property.converter.Converters;
import io.papermc.generator.utils.NamingManager;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
@ -18,7 +18,7 @@ public class IntegerPropertyWriter extends PropertyWriter<Integer> {
}
@Override
public void addExtras(TypeSpec.Builder builder, FieldSpec field, StructuredGenerator<?> generator, NamingManager naming) {
public void addExtras(TypeSpec.Builder builder, FieldSpec field, CraftBlockDataGenerator<?> generator, NamingManager naming) {
if (Converters.has(this.property)) {
return;
}

View File

@ -1,15 +1,12 @@
package io.papermc.generator.types.craftblockdata.property;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.primitives.Primitives;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import io.papermc.generator.types.StructuredGenerator;
import io.papermc.generator.types.craftblockdata.property.appender.AppenderBase;
import io.papermc.generator.types.craftblockdata.property.appender.EnumValuesAppender;
import io.papermc.generator.types.craftblockdata.property.appender.PropertyAppender;
import io.papermc.generator.types.craftblockdata.CraftBlockDataGenerator;
import io.papermc.generator.types.craftblockdata.property.appender.PropertyAppenders;
import io.papermc.generator.utils.BlockStateMapping;
import io.papermc.generator.utils.NamingManager;
import it.unimi.dsi.fastutil.Pair;
@ -20,9 +17,6 @@ import java.util.function.Supplier;
import net.minecraft.world.level.block.Block;
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
@ -64,30 +58,9 @@ public class PropertyWriter<T extends Comparable<T>> implements PropertyMaker {
return "this.get(%s)";
}
private static final Map<Property<?>, AppenderBase> APPENDERS;
private static final ImmutableMap.Builder<Property<?>, AppenderBase> builder = ImmutableMap.builder();
static {
register(new EnumValuesAppender<>(BlockStateProperties.AXIS, Axis.class, "getAxes"));
register(new EnumValuesAppender<>(BlockStateProperties.HORIZONTAL_AXIS, Axis.class, "getAxes"));
register(new EnumValuesAppender<>(BlockStateProperties.FACING, BlockFace.class, "getFaces"));
register(new EnumValuesAppender<>(BlockStateProperties.HORIZONTAL_FACING, BlockFace.class, "getFaces"));
register(new EnumValuesAppender<>(BlockStateProperties.FACING_HOPPER, BlockFace.class, "getFaces"));
register(new EnumValuesAppender<>(BlockStateProperties.RAIL_SHAPE, Rail.Shape.class, "getShapes"));
register(new EnumValuesAppender<>(BlockStateProperties.RAIL_SHAPE_STRAIGHT, Rail.Shape.class, "getShapes"));
register(new EnumValuesAppender<>(BlockStateProperties.VERTICAL_DIRECTION, BlockFace.class, "getVerticalDirections"));
APPENDERS = builder.build();
}
private static void register(PropertyAppender<? extends Comparable<?>, ?> converter) {
builder.put(converter.getProperty(), converter);
}
@Override
public void addExtras(TypeSpec.Builder builder, FieldSpec field, StructuredGenerator<?> generator, NamingManager naming) {
if (APPENDERS.containsKey(this.property)) {
APPENDERS.get(this.property).addExtras(builder, field, generator, 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) {

View File

@ -2,12 +2,12 @@ package io.papermc.generator.types.craftblockdata.property.appender;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.TypeSpec;
import io.papermc.generator.types.StructuredGenerator;
import io.papermc.generator.types.craftblockdata.CraftBlockDataGenerator;
import io.papermc.generator.utils.NamingManager;
import org.jspecify.annotations.NullMarked;
@NullMarked
public interface AppenderBase {
void addExtras(TypeSpec.Builder builder, FieldSpec field, StructuredGenerator<?> generator, NamingManager naming);
void addExtras(TypeSpec.Builder builder, FieldSpec field, CraftBlockDataGenerator<?> generator, NamingManager naming);
}

View File

@ -4,7 +4,7 @@ import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
import io.papermc.generator.types.StructuredGenerator;
import io.papermc.generator.types.craftblockdata.CraftBlockDataGenerator;
import io.papermc.generator.utils.NamingManager;
import java.util.Set;
import net.minecraft.util.StringRepresentable;
@ -35,7 +35,7 @@ public class EnumValuesAppender<T extends Enum<T> & StringRepresentable, A exten
}
@Override
public void addExtras(TypeSpec.Builder builder, FieldSpec field, StructuredGenerator<?> 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));

View File

@ -0,0 +1,33 @@
package io.papermc.generator.types.craftblockdata.property.appender;
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")
).collect(Collectors.toUnmodifiableMap(PropertyAppender::getProperty, key -> key));
public static void ifPresent(Property<?> property, Consumer<AppenderBase> callback) {
if (APPENDERS.containsKey(property)) {
callback.accept(APPENDERS.get(property));
}
}
}

View File

@ -8,5 +8,6 @@ public interface Converter<T extends Comparable<T>, A> extends ConverterBase {
Property<T> getProperty();
@Override
Class<A> getApiType();
}

View File

@ -1,22 +1,19 @@
package io.papermc.generator.types.craftblockdata.property.converter;
import com.google.common.collect.ImmutableMap;
import io.papermc.generator.types.craftblockdata.property.PropertyMaker;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.minecraft.world.level.block.state.properties.Property;
import org.jspecify.annotations.NullMarked;
@NullMarked
public final class Converters {
private static final Map<Property<?>, ConverterBase> CONVERTERS;
private static final ImmutableMap.Builder<Property<?>, ConverterBase> builder = ImmutableMap.builder();
static {
register(new RotationConverter());
register(new NoteConverter());
CONVERTERS = builder.build();
}
private static final Map<Property<?>, ConverterBase> CONVERTERS = Stream.of(
new RotationConverter(),
new NoteConverter()
).collect(Collectors.toUnmodifiableMap(Converter::getProperty, key -> key));
public static ConverterBase getOrDefault(Property<?> property, PropertyMaker maker) {
return CONVERTERS.getOrDefault(property, maker);
@ -25,8 +22,4 @@ public final class Converters {
public static boolean has(Property<?> property) {
return CONVERTERS.containsKey(property);
}
private static void register(Converter<? extends Comparable<?>, ?> converter) {
builder.put(converter.getProperty(), converter);
}
}

View File

@ -1,7 +1,5 @@
package io.papermc.generator.types.craftblockdata.property.holder;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.FieldSpec;
@ -9,13 +7,10 @@ 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.StructuredGenerator;
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.ArrayAppender;
import io.papermc.generator.types.craftblockdata.property.holder.appender.DataAppender;
import io.papermc.generator.types.craftblockdata.property.holder.appender.ListAppender;
import io.papermc.generator.types.craftblockdata.property.holder.appender.MapAppender;
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;
@ -160,24 +155,8 @@ public class DataPropertyWriter extends DataPropertyWriterBase {
return name;
}
private static final Map<DataHolderType, DataAppender> APPENDERS;
private static final ImmutableMap.Builder<DataHolderType, DataAppender> builder = ImmutableMap.builder();
static {
register(new ArrayAppender());
register(new ListAppender());
register(new MapAppender());
APPENDERS = Maps.immutableEnumMap(builder.build());
}
private static void register(DataAppender converter) {
builder.put(converter.getType(), converter);
}
@Override
public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, StructuredGenerator<?> generator, NamingManager naming) {
if (APPENDERS.containsKey(this.type)) {
APPENDERS.get(this.type).addExtras(builder, field, indexParameter, childConverter, generator, naming);
}
public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator<?> generator, NamingManager naming) {
DataAppenders.ifPresent(this.type, appender -> appender.addExtras(builder, field, indexParameter, childConverter, generator, naming));
}
}

View File

@ -7,7 +7,7 @@ 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.StructuredGenerator;
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;
@ -93,7 +93,7 @@ public class VirtualDataPropertyWriter extends DataPropertyWriterBase {
}
@Override
public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase converter, StructuredGenerator<?> generator, NamingManager naming) {
public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase converter, CraftBlockDataGenerator<?> generator, NamingManager naming) {
}
}

View File

@ -6,7 +6,7 @@ import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
import io.papermc.generator.types.StructuredGenerator;
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.CommonVariable;
@ -23,7 +23,7 @@ public class ArrayAppender implements DataAppender {
}
@Override
public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, StructuredGenerator<?> generator, NamingManager naming) {
public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator<?> generator, NamingManager naming) {
if (childConverter.getApiType() == Boolean.TYPE) {
String collectVarName = naming.getVariableNameWrapper().post("s").concat();
MethodSpec.Builder methodBuilder = generator.createMethod(naming.getMethodNameWrapper().post("s").concat());

View File

@ -3,7 +3,7 @@ package io.papermc.generator.types.craftblockdata.property.holder.appender;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeSpec;
import io.papermc.generator.types.StructuredGenerator;
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.NamingManager;
@ -14,5 +14,5 @@ public interface DataAppender {
DataHolderType getType();
void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase converter, StructuredGenerator<?> generator, NamingManager naming);
void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase converter, CraftBlockDataGenerator<?> generator, NamingManager naming);
}

View File

@ -0,0 +1,24 @@
package io.papermc.generator.types.craftblockdata.property.holder.appender;
import io.papermc.generator.types.craftblockdata.property.holder.DataHolderType;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jspecify.annotations.NullMarked;
@NullMarked
public final class DataAppenders {
private static final Map<DataHolderType, DataAppender> APPENDERS = Stream.of(
new ArrayAppender(),
new ListAppender(),
new MapAppender()
).collect(Collectors.toUnmodifiableMap(DataAppender::getType, key -> key));
public static void ifPresent(DataHolderType type, Consumer<DataAppender> callback) {
if (APPENDERS.containsKey(type)) {
callback.accept(APPENDERS.get(type));
}
}
}

View File

@ -6,7 +6,7 @@ import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
import io.papermc.generator.types.StructuredGenerator;
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.CommonVariable;
@ -28,7 +28,7 @@ public class ListAppender implements DataAppender {
}
@Override
public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, StructuredGenerator<?> generator, NamingManager naming) {
public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator<?> generator, NamingManager naming) {
NamingManager.NameWrapper methodName = NamingManager.NameWrapper.wrap("get", METHOD_BASE_RENAMES.getOrDefault(naming.getMethodBaseName(), naming.getMethodBaseName()));
if (childConverter.getApiType() == Boolean.TYPE) {

View File

@ -7,7 +7,7 @@ import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
import io.papermc.generator.types.StructuredGenerator;
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.CommonVariable;
@ -27,7 +27,7 @@ public class MapAppender implements DataAppender {
}
@Override
public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, StructuredGenerator<?> generator, NamingManager naming) {
public void addExtras(TypeSpec.Builder builder, FieldSpec field, ParameterSpec indexParameter, ConverterBase childConverter, CraftBlockDataGenerator<?> generator, NamingManager naming) {
if (childConverter.getApiType() == Boolean.TYPE) {
String collectVarName = naming.getVariableNameWrapper().post("s").concat();
MethodSpec.Builder methodBuilder = generator.createMethod(naming.getMethodNameWrapper().post("s").concat());

View File

@ -1,32 +1,25 @@
package io.papermc.generator.types.craftblockdata.property.holder.converter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import io.papermc.generator.types.craftblockdata.property.holder.DataHolderType;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jspecify.annotations.NullMarked;
@NullMarked
public final class DataConverters {
private static final ImmutableMap<DataHolderType, DataConverter> CONVERTERS;
private static final ImmutableMap.Builder<DataHolderType, DataConverter> builder = ImmutableMap.builder();
static {
register(new ArrayConverter());
register(new ListConverter());
register(new MapConverter());
CONVERTERS = Maps.immutableEnumMap(builder.build());
}
private static final Map<DataHolderType, DataConverter> CONVERTERS = Stream.of(
new ArrayConverter(),
new ListConverter(),
new MapConverter()
).collect(Collectors.toUnmodifiableMap(DataConverter::getType, key -> key));
public static DataConverter getOrThrow(DataHolderType type) {
DataConverter converter = CONVERTERS.get(type);
if (converter == null) {
throw new IllegalStateException("Cannot handle " + type);
throw new IllegalStateException("Cannot handle data holder type: " + type);
}
return converter;
}
private static void register(DataConverter converter) {
builder.put(converter.getType(), converter);
}
}

View File

@ -15,9 +15,10 @@ import io.papermc.generator.types.SimpleGenerator;
import io.papermc.generator.utils.Annotations;
import io.papermc.generator.utils.Formatting;
import io.papermc.generator.utils.Javadocs;
import io.papermc.typewriter.utils.ClassHelper;
import io.papermc.typewriter.util.ClassHelper;
import java.util.Comparator;
import java.util.List;
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;
@ -64,17 +65,16 @@ public class MobGoalGenerator extends SimpleGenerator {
classes = scanResult.getSubclasses(Goal.class.getName()).loadClasses(Goal.class);
}
List<GoalKey<Mob>> vanillaGoals = classes.stream()
Stream<GoalKey<Mob>> 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())
)
.toList();
);
for (GoalKey<?> goalKey : vanillaGoals) {
vanillaGoals.forEach(goalKey -> {
String keyPath = goalKey.getNamespacedKey().getKey();
String fieldName = Formatting.formatKeyAsField(keyPath);
@ -82,7 +82,7 @@ public class MobGoalGenerator extends SimpleGenerator {
FieldSpec.Builder fieldBuilder = FieldSpec.builder(typedKey, fieldName, PUBLIC, STATIC, FINAL)
.initializer("$N($S, $T.class)", createMethod.build(), keyPath, goalKey.getEntityClass());
typeBuilder.addField(fieldBuilder.build());
}
});
return typeBuilder.addMethod(createMethod.build()).build();
}

View File

@ -13,12 +13,11 @@ import io.papermc.generator.types.SimpleGenerator;
import io.papermc.generator.utils.Annotations;
import io.papermc.generator.utils.Formatting;
import io.papermc.generator.utils.Javadocs;
import io.papermc.generator.utils.RegistryUtils;
import io.papermc.generator.utils.experimental.FlagHolders;
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.Set;
import java.util.Map;
import java.util.function.Supplier;
import javax.lang.model.SourceVersion;
import net.kyori.adventure.key.Key;
@ -43,14 +42,14 @@ public class GeneratedKeyType<T> extends SimpleGenerator {
private final RegistryEntry<T> entry;
private final Registry<T> registry;
private final Supplier<Set<ResourceKey<T>>> experimentalKeys;
private final Supplier<Map<ResourceKey<T>, SingleFlagHolder>> experimentalKeys;
private final boolean isFilteredRegistry;
public GeneratedKeyType(String packageName, RegistryEntry<T> entry) {
super(entry.keyClassName().concat("Keys"), packageName);
this.entry = entry;
this.registry = entry.registry();
this.experimentalKeys = Suppliers.memoize(() -> RegistryUtils.collectExperimentalDataDrivenKeys(this.registry));
this.experimentalKeys = Suppliers.memoize(() -> ExperimentalCollector.collectDataDrivenElementIds(this.registry));
this.isFilteredRegistry = FeatureElement.FILTERED_REGISTRIES.contains(entry.registryKey());
}
@ -124,7 +123,7 @@ public class GeneratedKeyType<T> extends SimpleGenerator {
return builder.addStaticImport(Key.class, "key");
}
public @Nullable SingleFlagHolder getRequiredFeature(Holder.Reference<T> reference) {
protected @Nullable SingleFlagHolder getRequiredFeature(Holder.Reference<T> reference) {
if (this.isFilteredRegistry) {
// built-in registry
FeatureElement element = (FeatureElement) reference.value();
@ -133,9 +132,7 @@ public class GeneratedKeyType<T> extends SimpleGenerator {
}
} else {
// data-driven registry
if (this.experimentalKeys.get().contains(reference.key())) {
return FlagHolders.NEXT_UPDATE;
}
return this.experimentalKeys.get().get(reference.key());
}
return null;
}

View File

@ -8,7 +8,6 @@ import net.minecraft.SharedConstants;
import org.bukkit.MinecraftExperimental;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
public final class Annotations {
@ -23,24 +22,6 @@ public final class Annotations {
);
}
public static AnnotationSpec deprecatedVersioned(@Nullable String version, boolean forRemoval) {
AnnotationSpec.Builder annotationSpec = AnnotationSpec.builder(Deprecated.class);
if (forRemoval) {
annotationSpec.addMember("forRemoval", "$L", true);
}
if (version != null) {
annotationSpec.addMember("since", "$S", version);
}
return annotationSpec.build();
}
public static AnnotationSpec scheduledRemoval(String version) {
return AnnotationSpec.builder(ApiStatus.ScheduledForRemoval.class)
.addMember("inVersion", "$S", version)
.build();
}
public static AnnotationSpec suppressWarnings(String... values) {
AnnotationSpec.Builder builder = AnnotationSpec.builder(SuppressWarnings.class);
for (String value : values) {
@ -53,12 +34,11 @@ 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();
private static final AnnotationSpec SUPPRESS_WARNINGS = suppressWarnings("unused", "SpellCheckingInspection");
public static final AnnotationSpec GENERATED_FROM = AnnotationSpec.builder(GeneratedFrom.class)
.addMember("value", "$S", SharedConstants.getCurrentVersion().getName())
.build();
public static final Iterable<AnnotationSpec> CLASS_HEADER = List.of(
SUPPRESS_WARNINGS,
suppressWarnings("unused", "SpellCheckingInspection"),
NULL_MARKED,
GENERATED_FROM
);

View File

@ -59,7 +59,7 @@ public final class ClassHelper {
return (field.getModifiers() & flags) == flags;
}
public static <T> Class<? extends T> classOr(String className, Class<? extends T> defaultClass) {
public static <T> @Nullable Class<? extends T> classOr(String className, @Nullable Class<? extends T> defaultClass) {
try {
return (Class<? extends T>) Class.forName(className);
} catch (ClassNotFoundException ignored) {

View File

@ -4,7 +4,6 @@ import java.util.Optional;
import org.apache.commons.lang3.math.NumberUtils;
import java.util.Comparator;
import java.util.Locale;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.Function;
import java.util.regex.Pattern;
@ -12,7 +11,6 @@ import java.util.stream.IntStream;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import org.apache.commons.lang3.math.NumberUtils;
import org.jspecify.annotations.NullMarked;
@NullMarked
@ -75,7 +73,7 @@ public final class Formatting {
return newName;
}
public static Comparator<String> ALPHABETIC_KEY_ORDER = alphabeticKeyOrder(path -> path);
public static final Comparator<String> ALPHABETIC_KEY_ORDER = alphabeticKeyOrder(path -> path);
public static <T> Comparator<T> alphabeticKeyOrder(Function<T, String> mapper) {
return (o1, o2) -> {

View File

@ -1,46 +0,0 @@
package io.papermc.generator.utils;
import com.google.common.collect.Sets;
import io.papermc.generator.utils.experimental.CollectingContext;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistrySetBuilder;
import net.minecraft.data.registries.VanillaRegistries;
import net.minecraft.data.registries.WinterDropRegistries;
import net.minecraft.resources.ResourceKey;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
public class RegistryUtils {
private static final Map<ResourceKey<? extends Registry<?>>, RegistrySetBuilder.RegistryBootstrap<?>> VANILLA_REGISTRY_ENTRIES = VanillaRegistries.BUILDER.entries.stream()
.collect(Collectors.toMap(RegistrySetBuilder.RegistryStub::key, RegistrySetBuilder.RegistryStub::bootstrap));
private static final Map<ResourceKey<? extends Registry<?>>, RegistrySetBuilder.RegistryBootstrap<?>> EXPERIMENTAL_REGISTRY_ENTRIES = WinterDropRegistries.BUILDER.entries.stream()
.collect(Collectors.toMap(RegistrySetBuilder.RegistryStub::key, RegistrySetBuilder.RegistryStub::bootstrap)); // Update for Experimental API
@SuppressWarnings("unchecked")
public static <T> Set<ResourceKey<T>> collectExperimentalDataDrivenKeys(Registry<T> registry) {
RegistrySetBuilder.@Nullable RegistryBootstrap<T> experimentalBootstrap = (RegistrySetBuilder.RegistryBootstrap<T>) EXPERIMENTAL_REGISTRY_ENTRIES.get(registry.key());
if (experimentalBootstrap == null) {
return Collections.emptySet();
}
Set<ResourceKey<T>> experimental = Collections.newSetFromMap(new IdentityHashMap<>());
CollectingContext<T> experimentalCollector = new CollectingContext<>(experimental, registry);
experimentalBootstrap.run(experimentalCollector);
RegistrySetBuilder.@Nullable RegistryBootstrap<T> vanillaBootstrap = (RegistrySetBuilder.RegistryBootstrap<T>) VANILLA_REGISTRY_ENTRIES.get(registry.key());
if (vanillaBootstrap != null) {
Set<ResourceKey<T>> vanilla = Collections.newSetFromMap(new IdentityHashMap<>());
CollectingContext<T> vanillaCollector = new CollectingContext<>(vanilla, registry);
vanillaBootstrap.run(vanillaCollector);
return Sets.difference(experimental, vanilla);
}
return experimental;
}
}

View File

@ -0,0 +1,134 @@
package io.papermc.generator.utils.experimental;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.mojang.logging.LogUtils;
import io.papermc.generator.Main;
import io.papermc.generator.utils.Formatting;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.RegistrySetBuilder;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.registries.TradeRebalanceRegistries;
import net.minecraft.data.registries.VanillaRegistries;
import net.minecraft.data.registries.WinterDropRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.repository.BuiltInPackSource;
import net.minecraft.server.packs.resources.MultiPackResourceManager;
import net.minecraft.tags.TagKey;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
@NullMarked
public final class ExperimentalCollector {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Map<ResourceKey<? extends Registry<?>>, RegistrySetBuilder.RegistryBootstrap<?>> VANILLA_REGISTRY_ENTRIES = VanillaRegistries.BUILDER.entries.stream()
.collect(Collectors.toMap(RegistrySetBuilder.RegistryStub::key, RegistrySetBuilder.RegistryStub::bootstrap));
private static final Map<RegistrySetBuilder, SingleFlagHolder> EXPERIMENTAL_REGISTRY_FLAGS = Map.of(
// Update for Experimental API
WinterDropRegistries.BUILDER, FlagHolders.WINTER_DROP,
TradeRebalanceRegistries.BUILDER, FlagHolders.TRADE_REBALANCE
);
private static final Multimap<ResourceKey<? extends Registry<?>>, Map.Entry<SingleFlagHolder, RegistrySetBuilder.RegistryBootstrap<?>>> EXPERIMENTAL_REGISTRY_ENTRIES;
static {
EXPERIMENTAL_REGISTRY_ENTRIES = HashMultimap.create();
for (Map.Entry<RegistrySetBuilder, SingleFlagHolder> entry : EXPERIMENTAL_REGISTRY_FLAGS.entrySet()) {
for (RegistrySetBuilder.RegistryStub<?> stub : entry.getKey().entries) {
EXPERIMENTAL_REGISTRY_ENTRIES.put(stub.key(), Map.entry(entry.getValue(), stub.bootstrap()));
}
}
}
@SuppressWarnings("unchecked")
public static <T> Map<ResourceKey<T>, SingleFlagHolder> collectDataDrivenElementIds(Registry<T> registry) {
Collection<Map.Entry<SingleFlagHolder, RegistrySetBuilder.RegistryBootstrap<?>>> experimentalEntries = EXPERIMENTAL_REGISTRY_ENTRIES.get(registry.key());
if (experimentalEntries.isEmpty()) {
return Collections.emptyMap();
}
Map<ResourceKey<T>, SingleFlagHolder> result = new IdentityHashMap<>();
for (Map.Entry<SingleFlagHolder, RegistrySetBuilder.RegistryBootstrap<?>> experimentalEntry : experimentalEntries) {
RegistrySetBuilder.RegistryBootstrap<T> experimentalBootstrap = (RegistrySetBuilder.RegistryBootstrap<T>) experimentalEntry.getValue();
Set<ResourceKey<T>> experimental = Collections.newSetFromMap(new IdentityHashMap<>());
CollectingContext<T> experimentalCollector = new CollectingContext<>(experimental, registry);
experimentalBootstrap.run(experimentalCollector);
result.putAll(experimental.stream().collect(Collectors.toMap(key -> key, key -> experimentalEntry.getKey())));
}
RegistrySetBuilder.@Nullable RegistryBootstrap<T> vanillaBootstrap = (RegistrySetBuilder.RegistryBootstrap<T>) VANILLA_REGISTRY_ENTRIES.get(registry.key());
if (vanillaBootstrap != null) {
Set<ResourceKey<T>> vanilla = Collections.newSetFromMap(new IdentityHashMap<>());
CollectingContext<T> vanillaCollector = new CollectingContext<>(vanilla, registry);
vanillaBootstrap.run(vanillaCollector);
result.keySet().removeAll(vanilla);
}
return result;
}
// collect all the tags by grabbing the json from the data-packs
// another (probably) way is to hook into the data generator like the typed keys generator
public static Map<TagKey<?>, String> collectTags(MultiPackResourceManager resourceManager) {
Map<TagKey<?>, String> result = new IdentityHashMap<>();
// collect all vanilla tags
Multimap<ResourceKey<? extends Registry<?>>, String> vanillaTags = HashMultimap.create();
PackResources vanillaPack = resourceManager.listPacks()
.filter(packResources -> packResources.packId().equals(BuiltInPackSource.VANILLA_ID))
.findFirst()
.orElseThrow();
collectTagsFromPack(vanillaPack, (entry, path) -> vanillaTags.put(entry.key(), path));
// then distinct with other data-pack tags to know for sure newly created tags and so experimental one
resourceManager.listPacks().forEach(pack -> {
String packId = pack.packId();
if (packId.equals(BuiltInPackSource.VANILLA_ID)) return;
collectTagsFromPack(pack, (entry, path) -> {
if (vanillaTags.get(entry.key()).contains(path)) {
return;
}
result.put(entry.value().listTagIds()
.filter(tagKey -> tagKey.location().getPath().equals(path))
.findFirst()
.orElseThrow(), packId);
});
});
return Collections.unmodifiableMap(result);
}
private static void collectTagsFromPack(PackResources pack, BiConsumer<RegistryAccess.RegistryEntry<?>, String> output) {
Set<String> namespaces = pack.getNamespaces(PackType.SERVER_DATA);
for (String namespace : namespaces) {
Main.REGISTRY_ACCESS.registries().forEach(entry -> {
// this is probably expensive but can't find another way around and data-pack loader has similar logic
// the issue is that registry key can have parent/key but tag key can also have parent/key so parsing become a mess
// without having at least one of the two values
String tagDir = Registries.tagsDirPath(entry.key());
pack.listResources(PackType.SERVER_DATA, namespace, tagDir, (id, supplier) -> {
Formatting.formatTagKey(tagDir, id.getPath()).ifPresentOrElse(path -> output.accept(entry, path), () -> {
LOGGER.warn("Unable to parse the path: {}/{}/{}.json in the data-pack {} into a tag key", namespace, tagDir, id.getPath(), pack.packId());
});
});
});
}
}
private ExperimentalCollector() {
}
}

View File

@ -8,18 +8,17 @@ import net.minecraft.world.flag.FeatureFlag;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.MinecraftExperimental;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
public class FlagHolders {
public static final @Nullable SingleFlagHolder NEXT_UPDATE = SingleFlagHolder.fromValue(FeatureFlags.WINTER_DROP)/*SingleFlagHolder.fromValue(FeatureFlags.UPDATE_1_22)*/;
public static final SingleFlagHolder WINTER_DROP = SingleFlagHolder.fromValue(FeatureFlags.WINTER_DROP);
public static final SingleFlagHolder TRADE_REBALANCE = SingleFlagHolder.fromValue(FeatureFlags.TRADE_REBALANCE);
public static final SingleFlagHolder REDSTONE_EXPERIMENTS = SingleFlagHolder.fromValue(FeatureFlags.REDSTONE_EXPERIMENTS);
public static final SingleFlagHolder MINECART_IMPROVEMENTS = SingleFlagHolder.fromValue(FeatureFlags.MINECART_IMPROVEMENTS);
static final Map<FeatureFlag, MinecraftExperimental.Requires> ANNOTATION_EQUIVALENT = Util.make(new HashMap<SingleFlagHolder, MinecraftExperimental.Requires>(), map -> {
map.put(NEXT_UPDATE, MinecraftExperimental.Requires.WINTER_DROP); //map.put(NEXT_UPDATE, MinecraftExperimental.Requires.UPDATE_1_22);
map.put(WINTER_DROP, MinecraftExperimental.Requires.WINTER_DROP);
map.put(TRADE_REBALANCE, MinecraftExperimental.Requires.TRADE_REBALANCE);
map.put(REDSTONE_EXPERIMENTS, MinecraftExperimental.Requires.REDSTONE_EXPERIMENTS);
map.put(MINECART_IMPROVEMENTS, MinecraftExperimental.Requires.MINECART_IMPROVEMENTS);

View File

@ -42,7 +42,7 @@ public record SingleFlagHolder(FeatureFlag flag) implements FlagHolder { // todo
public MinecraftExperimental.Requires asAnnotationMember() {
MinecraftExperimental.Requires annotationMember = FlagHolders.ANNOTATION_EQUIVALENT.get(this.flag);
if (annotationMember == null) {
throw new UnsupportedOperationException("Don't know that feature flag : " + FEATURE_FLAG_NAME.get(this.flag));
throw new UnsupportedOperationException("Don't know that feature flag: " + FEATURE_FLAG_NAME.get(this.flag));
}
return annotationMember;
}

View File

@ -1,82 +0,0 @@
package io.papermc.generator.utils.experimental;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.mojang.logging.LogUtils;
import io.papermc.generator.Main;
import io.papermc.generator.utils.Formatting;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.repository.BuiltInPackSource;
import net.minecraft.server.packs.resources.MultiPackResourceManager;
import net.minecraft.tags.TagKey;
import org.jspecify.annotations.NullMarked;
import org.slf4j.Logger;
// collect all the tags by grabbing the json from the data-packs
// another (probably) way is to hook into the data generator like the typed keys generator
@NullMarked
public final class TagCollector {
private static final Logger LOGGER = LogUtils.getLogger();
public static Map<TagKey<?>, String> grabExperimental(MultiPackResourceManager resourceManager) {
Map<TagKey<?>, String> result = new IdentityHashMap<>();
// collect all vanilla tags
Multimap<ResourceKey<? extends Registry<?>>, String> vanillaTags = HashMultimap.create();
PackResources vanillaPack = resourceManager.listPacks()
.filter(packResources -> packResources.packId().equals(BuiltInPackSource.VANILLA_ID))
.findFirst()
.orElseThrow();
collectFromPack(vanillaPack, (entry, path) -> vanillaTags.put(entry.key(), path));
// then distinct with other data-pack tags to know for sure newly created tags and so experimental one
resourceManager.listPacks().forEach(pack -> {
String packId = pack.packId();
if (packId.equals(BuiltInPackSource.VANILLA_ID)) return;
collectFromPack(pack, (entry, path) -> {
if (vanillaTags.get(entry.key()).contains(path)) {
return;
}
result.put(entry.value().listTagIds()
.filter(tagKey -> tagKey.location().getPath().equals(path))
.findFirst()
.orElseThrow(), packId);
});
});
return Collections.unmodifiableMap(result);
}
private static void collectFromPack(PackResources pack, BiConsumer<RegistryAccess.RegistryEntry<?>, String> output) {
Set<String> namespaces = pack.getNamespaces(PackType.SERVER_DATA);
for (String namespace : namespaces) {
Main.REGISTRY_ACCESS.registries().forEach(entry -> {
// this is probably expensive but can't find another way around and data-pack loader has similar logic
// the issue is that registry key can have parent/key (and custom folder too) but tag key can also have parent/key so parsing become a mess
// without having at least one of the two values
String tagDir = Registries.tagsDirPath(entry.key());
pack.listResources(PackType.SERVER_DATA, namespace, tagDir, (id, supplier) -> {
Formatting.formatTagKey(tagDir, id.getPath()).ifPresentOrElse(path -> output.accept(entry, path), () -> {
LOGGER.warn("Unable to parse the path: {}/{}/{}.json in the data-pack {} into a tag key", namespace, tagDir, id.getPath(), pack.packId());
});
});
});
}
}
private TagCollector() {
}
}

View File

@ -1,23 +1,26 @@
package io.papermc.generator;
import io.papermc.generator.utils.BlockStateMapping;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.minecraft.SharedConstants;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.level.block.ChiseledBookShelfBlock;
import net.minecraft.world.level.block.MossyCarpetBlock;
import net.minecraft.world.level.block.PipeBlock;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.fail;
public class BlockStatePropertyTest {
private static Set<Class<? extends Comparable<?>>> ENUM_PROPERTY_VALUES;
@ -49,24 +52,24 @@ public class BlockStatePropertyTest {
}
}
{
// reference test
// if renamed should change DataPropertyWriter#FIELD_TO_BASE_NAME
var a = ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES;
var b = PipeBlock.PROPERTY_BY_DIRECTION;
@Test
public void testReferences() throws NoSuchFieldException, IllegalAccessException {
// if renamed should change DataPropertyWriter#FIELD_TO_BASE_NAME/FIELD_TO_BASE_NAME_SPECIFICS
MethodHandles.Lookup lookup = MethodHandles.lookup();
lookup.findStaticVarHandle(ChiseledBookShelfBlock.class, "SLOT_OCCUPIED_PROPERTIES", List.class);
lookup.findStaticVarHandle(PipeBlock.class, "PROPERTY_BY_DIRECTION", Map.class);
MethodHandles.privateLookupIn(MossyCarpetBlock.class, lookup).findStaticVarHandle(MossyCarpetBlock.class, "PROPERTY_BY_DIRECTION", Map.class);
}
@Test
public void testBridge() {
Set<String> missingApisEquivalent = new HashSet<>();
Set<String> missingApiEquivalents = new HashSet<>();
for (Class<? extends Comparable<?>> value : ENUM_PROPERTY_VALUES) {
if (!BlockStateMapping.ENUM_BRIDGE.containsKey(value)) {
missingApisEquivalent.add(value.getCanonicalName());
missingApiEquivalents.add(value.getCanonicalName());
}
}
if (!missingApisEquivalent.isEmpty()) {
fail("Missing some api equivalent in the blockstate mapping enum bridge (BlockStateMapping#ENUM_BRIDGE) : " + String.join(", ", missingApisEquivalent));
}
Assertions.assertTrue(missingApiEquivalents.isEmpty(), () -> "Missing some api equivalent in the block state mapping enum bridge (BlockStateMapping#ENUM_BRIDGE) : " + String.join(", ", missingApiEquivalents));
}
}

View File

@ -10,14 +10,14 @@ import net.minecraft.world.entity.Mob;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class MobGoalConverterTest {
@Test
public void testBukkitMap() {
final List<Class<Mob>> classes;
try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages(Entity.class.getPackageName()).scan()) {
try (ScanResult scanResult = new ClassGraph().enableClassInfo().whitelistPackages(Entity.class.getPackageName()).scan()) {
classes = scanResult.getSubclasses(Mob.class.getName()).loadClasses(Mob.class);
}
@ -30,8 +30,6 @@ public class MobGoalConverterTest {
}
}
if (!missingClasses.isEmpty()) {
fail("Missing some entity classes in the bukkit map: " + String.join(", ", missingClasses));
}
assertTrue(missingClasses.isEmpty(), () -> "Missing some entity classes in the bukkit map: " + String.join(", ", missingClasses));
}
}

View File

@ -648,7 +648,7 @@ index a8d6d7054110b5d95830296699f004418dae10db..acc25b08ed3b9f978229fa017d23f9fa
LOOK,
JUMP,
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 6b042419af11730b0159c030ea1881dcfbb37dcd..8339da59b7a73411f45b77f6eb93e8ad65a1ef48 100644
index 89a37c31c0376d66251fee36df4a78dac05c2031..b91dc9532380788f7b6b7a50a53625e1cb3889d2 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2956,5 +2956,11 @@ public final class CraftServer implements Server {
@ -663,46 +663,3 @@ index 6b042419af11730b0159c030ea1881dcfbb37dcd..8339da59b7a73411f45b77f6eb93e8ad
+ }
// Paper end
}
diff --git a/src/test/java/io/papermc/paper/entity/ai/MobGoalConverterTest.java b/src/test/java/io/papermc/paper/entity/ai/MobGoalConverterTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b020f795846d98f5464b390008be8815e892f9e8
--- /dev/null
+++ b/src/test/java/io/papermc/paper/entity/ai/MobGoalConverterTest.java
@@ -0,0 +1,37 @@
+package io.papermc.paper.entity.ai;
+
+import com.destroystokyo.paper.entity.ai.MobGoalHelper;
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ScanResult;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.Mob;
+import org.junit.jupiter.api.Test;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class MobGoalConverterTest {
+
+ @Test
+ public void testBukkitMap() {
+ List<Class<Mob>> classes;
+ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages(Entity.class.getPackageName()).scan()) {
+ classes = scanResult.getSubclasses(Mob.class.getName()).loadClasses(Mob.class);
+ }
+ assertFalse(classes.isEmpty(), "There are supposed to be more than 0 mob classes!");
+
+ List<String> missingClasses = new ArrayList<>();
+ for (Class<Mob> nmsClass : classes) {
+ Class<? extends org.bukkit.entity.Mob> bukkitClass = MobGoalHelper.toBukkitClass(nmsClass);
+ if (bukkitClass == null) {
+ missingClasses.add(nmsClass.getCanonicalName());
+ }
+ }
+
+ if (!missingClasses.isEmpty()) {
+ fail("Missing some entity classes in the bukkit map (MobGoalHelper): " + String.join(", ", missingClasses));
+ }
+ }
+}