diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea46962fd..e72d5aada 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -147,7 +147,7 @@ jobs: uses: actions/setup-java@v2 with: distribution: "zulu" - java-version: "17" + java-version: "21" - name: Test Build run: ./gradlew build diff --git a/extractor/build.gradle b/extractor/build.gradle index aa098ac28..a09b75fde 100644 --- a/extractor/build.gradle +++ b/extractor/build.gradle @@ -1,9 +1,9 @@ plugins { - id 'fabric-loom' version '1.2-SNAPSHOT' + id 'fabric-loom' version '1.7-SNAPSHOT' } -sourceCompatibility = JavaVersion.VERSION_17 -targetCompatibility = JavaVersion.VERSION_17 +sourceCompatibility = JavaVersion.VERSION_21 +targetCompatibility = JavaVersion.VERSION_21 archivesBaseName = project.archives_base_name version = project.mod_version @@ -28,7 +28,7 @@ processResources { } tasks.withType(JavaCompile).configureEach { - it.options.release = 17 + it.options.release = 21 } java { diff --git a/extractor/gradle.properties b/extractor/gradle.properties index f75e33115..a22477821 100644 --- a/extractor/gradle.properties +++ b/extractor/gradle.properties @@ -2,12 +2,12 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.20.1 -yarn_mappings=1.20.1+build.1 -loader_version=0.14.21 +minecraft_version=1.21 +yarn_mappings=1.21+build.9 +loader_version=0.15.11 # Mod Properties mod_version=1.0.0 maven_group=dev.00a archives_base_name=valence-extractor # Dependencies -fabric_version=0.83.0+1.20.1 +fabric_version=0.100.7+1.21 diff --git a/extractor/gradle/wrapper/gradle-wrapper.jar b/extractor/gradle/wrapper/gradle-wrapper.jar index 249e5832f..d64cd4917 100644 Binary files a/extractor/gradle/wrapper/gradle-wrapper.jar and b/extractor/gradle/wrapper/gradle-wrapper.jar differ diff --git a/extractor/gradle/wrapper/gradle-wrapper.properties b/extractor/gradle/wrapper/gradle-wrapper.properties index 59bc51a20..dab2a015b 100644 --- a/extractor/gradle/wrapper/gradle-wrapper.properties +++ b/extractor/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/extractor/gradlew b/extractor/gradlew index a69d9cb6c..1aa94a426 100755 --- a/extractor/gradlew +++ b/extractor/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/extractor/gradlew.bat b/extractor/gradlew.bat index 53a6b238d..6689b85be 100644 --- a/extractor/gradlew.bat +++ b/extractor/gradlew.bat @@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% diff --git a/extractor/src/main/java/rs/valence/extractor/ClassComparator.java b/extractor/src/main/java/rs/valence/extractor/ClassComparator.java index fed1baf75..675f0c82a 100644 --- a/extractor/src/main/java/rs/valence/extractor/ClassComparator.java +++ b/extractor/src/main/java/rs/valence/extractor/ClassComparator.java @@ -1,11 +1,12 @@ package rs.valence.extractor; +import java.io.Serializable; import java.util.Comparator; /** * Compare Class objects by their simple names lexicographically. */ -public class ClassComparator implements Comparator> { +public class ClassComparator implements Comparator>, Serializable { public ClassComparator() { } diff --git a/extractor/src/main/java/rs/valence/extractor/DummyPlayerEntity.java b/extractor/src/main/java/rs/valence/extractor/DummyPlayerEntity.java index 9e8a4974d..0bd933307 100644 --- a/extractor/src/main/java/rs/valence/extractor/DummyPlayerEntity.java +++ b/extractor/src/main/java/rs/valence/extractor/DummyPlayerEntity.java @@ -15,18 +15,10 @@ public class DummyPlayerEntity extends PlayerEntity { static { INSTANCE = Main.magicallyInstantiate(DummyPlayerEntity.class); - try { - var dataTrackerField = Entity.class.getDeclaredField("dataTracker"); - dataTrackerField.setAccessible(true); - dataTrackerField.set(INSTANCE, new DataTracker(INSTANCE)); - - INSTANCE.initDataTracker(); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); - } + INSTANCE.initDataTracker(new DataTracker.Builder(INSTANCE)); } - private DummyPlayerEntity(World world, BlockPos pos, float yaw, GameProfile gameProfile, @Nullable PlayerPublicKey publicKey) { + public DummyPlayerEntity(World world, BlockPos pos, float yaw, GameProfile gameProfile, @Nullable PlayerPublicKey publicKey) { super(world, pos, yaw, gameProfile); } diff --git a/extractor/src/main/java/rs/valence/extractor/DummyWorld.java b/extractor/src/main/java/rs/valence/extractor/DummyWorld.java index a33bc35c1..c2a65f0ae 100644 --- a/extractor/src/main/java/rs/valence/extractor/DummyWorld.java +++ b/extractor/src/main/java/rs/valence/extractor/DummyWorld.java @@ -2,12 +2,15 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.component.type.MapIdComponent; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.fluid.Fluid; import net.minecraft.item.map.MapState; +import net.minecraft.recipe.BrewingRecipeRegistry; import net.minecraft.recipe.RecipeManager; import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.registry.Registries; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.resource.featuretoggle.FeatureFlags; @@ -30,6 +33,7 @@ import net.minecraft.world.entity.EntityLookup; import net.minecraft.world.event.GameEvent; import net.minecraft.world.tick.QueryableTickScheduler; +import net.minecraft.world.tick.TickManager; import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.function.Supplier; @@ -90,20 +94,25 @@ public Entity getEntityById(int id) { return null; } + @Override + public TickManager getTickManager() { + return null; + } + @Nullable @Override - public MapState getMapState(String id) { + public MapState getMapState(MapIdComponent id) { return null; } @Override - public void putMapState(String id, MapState state) { + public void putMapState(MapIdComponent id, MapState state) { } @Override - public int getNextMapId() { - return 0; + public MapIdComponent increaseAndGetMapId() { + return null; } @Override @@ -118,7 +127,7 @@ public Scoreboard getScoreboard() { @Override public RecipeManager getRecipeManager() { - return new RecipeManager(); + return null; } @Override @@ -147,12 +156,18 @@ public void syncWorldEvent(@Nullable PlayerEntity player, int eventId, BlockPos } @Override - public void emitGameEvent(GameEvent event, Vec3d emitterPos, GameEvent.Emitter emitter) { + public void emitGameEvent(RegistryEntry event, Vec3d emitterPos, GameEvent.Emitter emitter) { } + @Override public DynamicRegistryManager getRegistryManager() { + return DynamicRegistryManager.of(Registries.REGISTRIES); + } + + @Override + public BrewingRecipeRegistry getBrewingRecipeRegistry() { return null; } @@ -178,34 +193,10 @@ public RegistryEntry getGeneratorStoredBiome(int biomeX, int biomeY, int private static class DummyMutableWorldProperties implements MutableWorldProperties { - @Override - public int getSpawnX() { - return 0; - } - - @Override - public void setSpawnX(int spawnX) { - - } @Override - public int getSpawnY() { - return 0; - } - - @Override - public void setSpawnY(int spawnY) { - - } - - @Override - public int getSpawnZ() { - return 0; - } - - @Override - public void setSpawnZ(int spawnZ) { - + public BlockPos getSpawnPos() { + return null; } @Override @@ -213,10 +204,6 @@ public float getSpawnAngle() { return 0; } - @Override - public void setSpawnAngle(float spawnAngle) { - - } @Override public long getTime() { @@ -262,5 +249,10 @@ public Difficulty getDifficulty() { public boolean isDifficultyLocked() { return false; } + + @Override + public void setSpawnPos(BlockPos pos, float angle) { + + } } } diff --git a/extractor/src/main/java/rs/valence/extractor/Main.java b/extractor/src/main/java/rs/valence/extractor/Main.java index ce183b88c..8cbff3f14 100644 --- a/extractor/src/main/java/rs/valence/extractor/Main.java +++ b/extractor/src/main/java/rs/valence/extractor/Main.java @@ -44,10 +44,7 @@ public void onInitialize() { new Attributes(), new Blocks(), new Effects(), - new Enchants(), - new Entities(), new Misc(), - new Items(), new Packets(), new Sounds(), new TranslationKeys(), @@ -75,27 +72,28 @@ public void onInitialize() { } } - ServerLifecycleEvents.SERVER_STARTING.register(server -> { + ServerLifecycleEvents.SERVER_STARTED.register(server -> { LOGGER.info("Server starting, Running startup extractors..."); // TODO: make `Codec` implement `Extractor` - var codecExtractor = new Codec(server); + // TODO: the way to get Codex has changed, this is not working anymore + var packetRegistryExtractor = new PacketRegistries(server); try { - var out = outputDirectory.resolve(codecExtractor.fileName()); - var compound = codecExtractor.extract(); - // read the compound byte-wise and write it to the file - try { - NbtIo.write(compound, out.toFile()); - } catch (IOException var3) { - throw new EncoderException(var3); - } + var out = outputDirectory.resolve(packetRegistryExtractor.fileName()); + var fileWriter = new FileWriter(out.toFile(), StandardCharsets.UTF_8); + gson.toJson(packetRegistryExtractor.extract(), fileWriter); + fileWriter.close(); LOGGER.info("Wrote " + out.toAbsolutePath()); } catch (Exception e) { - LOGGER.error("Extractor for \"" + codecExtractor.fileName() + "\" failed.", e); + LOGGER.error("Extractor for \"" + packetRegistryExtractor.fileName() + "\" failed.", e); } var startupExtractors = new Extractor[]{ new Tags(server), + new Paintings(server), + new Enchants(server), + new Entities(server), + new Items(server), }; for (var ext : startupExtractors) { @@ -111,7 +109,7 @@ public void onInitialize() { } LOGGER.info("Done."); - server.shutdown(); + server.stop(false); }); } diff --git a/extractor/src/main/java/rs/valence/extractor/RegistryKeyComparator.java b/extractor/src/main/java/rs/valence/extractor/RegistryKeyComparator.java index a07875d1e..e69c6d0db 100644 --- a/extractor/src/main/java/rs/valence/extractor/RegistryKeyComparator.java +++ b/extractor/src/main/java/rs/valence/extractor/RegistryKeyComparator.java @@ -2,9 +2,10 @@ import net.minecraft.registry.RegistryKey; +import java.io.Serializable; import java.util.Comparator; -public class RegistryKeyComparator implements Comparator> { +public class RegistryKeyComparator implements Comparator>, Serializable { public RegistryKeyComparator() { } @@ -12,7 +13,7 @@ public RegistryKeyComparator() { public int compare(RegistryKey o1, RegistryKey o2) { var c1 = o1.getRegistry().compareTo(o2.getRegistry()); - if (c1 != 0) { + if (0 != c1) { return c1; } diff --git a/extractor/src/main/java/rs/valence/extractor/ValenceUtils.java b/extractor/src/main/java/rs/valence/extractor/ValenceUtils.java index 847da11ab..a116ec81e 100644 --- a/extractor/src/main/java/rs/valence/extractor/ValenceUtils.java +++ b/extractor/src/main/java/rs/valence/extractor/ValenceUtils.java @@ -8,6 +8,8 @@ private ValenceUtils() { throw new UnsupportedOperationException("This class cannot be instantiated"); } + + /** * Converts a string to PascalCase. * @@ -19,7 +21,7 @@ public static String toPascalCase(String str) { boolean capitalizeNext = true; for (char c : str.toCharArray()) { - if (Character.isWhitespace(c) || c == '_') { + if (Character.isWhitespace(c) || '_' == c) { capitalizeNext = true; } else if (capitalizeNext) { result.append(Character.toUpperCase(c)); diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java deleted file mode 100644 index c93aa6aa8..000000000 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ /dev/null @@ -1,129 +0,0 @@ -package rs.valence.extractor.extractors; - -// TODO: where is the biome registry in 1.19.3+? - -/* -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import net.minecraft.entity.SpawnGroup; -import net.minecraft.util.Identifier; -import net.minecraft.util.collection.Weighted; -import net.minecraft.registry.Registries; -import net.minecraft.world.biome.BiomeParticleConfig; -import rs.valence.extractor.Main; - -import java.lang.reflect.Field; - -public class Biomes implements Main.Extractor { - public Biomes() { - } - - @Override - public String fileName() { - return "biomes.json"; - } - - @Override - public JsonElement extract() { - // The biome particle probability field is private. - // We have to resort to reflection, unfortunately. - Field particleConfigProbabilityField; - try { - particleConfigProbabilityField = BiomeParticleConfig.class.getDeclaredField("probability"); - particleConfigProbabilityField.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); - } - - for (var biome : BuiltinRegistries.BIOME) { - var biomeIdent = BuiltinRegistries.BIOME.getId(biome); - assert biomeIdent != null; - - var biomeJson = new JsonObject(); - biomeJson.addProperty("precipitation", biome.getPrecipitation().getName()); - biomeJson.addProperty("temperature", biome.getTemperature()); - biomeJson.addProperty("downfall", biome.getDownfall()); - - var effectJson = new JsonObject(); - var biomeEffects = biome.getEffects(); - - effectJson.addProperty("sky_color", biomeEffects.getSkyColor()); - effectJson.addProperty("water_fog_color", biomeEffects.getWaterFogColor()); - effectJson.addProperty("fog_color", biomeEffects.getFogColor()); - effectJson.addProperty("water_color", biomeEffects.getWaterColor()); - biomeEffects.getFoliageColor().ifPresent(color -> effectJson.addProperty("foliage_color", color)); - biomeEffects.getGrassColor().ifPresent(color -> effectJson.addProperty("grass_color", color)); - effectJson.addProperty("grass_color_modifier", biomeEffects.getGrassColorModifier().getName()); - biomeEffects.getMusic().ifPresent(biome_music -> { - var music = new JsonObject(); - music.addProperty("replace_current_music", biome_music.shouldReplaceCurrentMusic()); - music.addProperty("sound", biome_music.getSound().getId().getPath()); - music.addProperty("max_delay", biome_music.getMaxDelay()); - music.addProperty("min_delay", biome_music.getMinDelay()); - effectJson.add("music", music); - }); - - biomeEffects.getLoopSound().ifPresent(soundEvent -> effectJson.addProperty("ambient_sound", soundEvent.getId().getPath())); - biomeEffects.getAdditionsSound().ifPresent(soundEvent -> { - var sound = new JsonObject(); - sound.addProperty("sound", soundEvent.getSound().getId().getPath()); - sound.addProperty("tick_chance", soundEvent.getChance()); - effectJson.add("additions_sound", sound); - }); - biomeEffects.getMoodSound().ifPresent(soundEvent -> { - var sound = new JsonObject(); - sound.addProperty("sound", soundEvent.getSound().getId().getPath()); - sound.addProperty("tick_delay", soundEvent.getCultivationTicks()); - sound.addProperty("offset", soundEvent.getExtraDistance()); - sound.addProperty("block_search_extent", soundEvent.getSpawnRange()); - - effectJson.add("mood_sound", sound); - }); - - biome.getParticleConfig().ifPresent(biomeParticleConfig -> { - try { - var particleConfig = new JsonObject(); - // We must first convert it into an identifier, because asString() returns a resource identifier as string. - Identifier id = new Identifier(biomeParticleConfig.getParticle().asString()); - particleConfig.addProperty("kind", id.getPath()); - particleConfig.addProperty("probability" ,particleConfigProbabilityField.getFloat(biomeParticleConfig)); - biomeJson.add("particle", particleConfig); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }); - - var spawnSettingsJson = new JsonObject(); - var spawnSettings = biome.getSpawnSettings(); - spawnSettingsJson.addProperty("probability", spawnSettings.getCreatureSpawnProbability()); - - var spawnGroupsJson = new JsonObject(); - for (var spawnGroup : SpawnGroup.values()) { - var spawnGroupJson = new JsonArray(); - for (var entry : spawnSettings.getSpawnEntries(spawnGroup).getEntries()) { - var groupEntryJson = new JsonObject(); - groupEntryJson.addProperty("name", Registry.ENTITY_TYPE.getId(entry.type).getPath()); - groupEntryJson.addProperty("min_group_size", entry.minGroupSize); - groupEntryJson.addProperty("max_group_size", entry.maxGroupSize); - groupEntryJson.addProperty("weight", ((Weighted) entry).getWeight().getValue()); - spawnGroupJson.add(groupEntryJson); - } - spawnGroupsJson.add(spawnGroup.getName(), spawnGroupJson); - } - spawnSettingsJson.add("groups", spawnGroupsJson); - - biomeJson.add("effects", effectJson); - biomeJson.add("spawn_settings", spawnSettingsJson); - - var entryJson = new JsonObject(); - entryJson.addProperty("name", biomeIdent.getPath()); - entryJson.addProperty("id", BuiltinRegistries.BIOME.getRawId(biome)); - entryJson.add("element", biomeJson); - biomesJson.add(entryJson); - } - - return biomesJson; - } -} - */ diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Blocks.java b/extractor/src/main/java/rs/valence/extractor/extractors/Blocks.java index e2dd2fdf3..bb3e5c613 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Blocks.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Blocks.java @@ -66,13 +66,12 @@ public JsonElement extract() { var statesJson = new JsonArray(); for (var state : block.getStateManager().getStates()) { var stateJson = new JsonObject(); - var id = stateIdCounter++; + var id = stateIdCounter; + stateIdCounter++; stateJson.addProperty("id", id); stateJson.addProperty("luminance", state.getLuminance()); stateJson.addProperty("opaque", state.isOpaque()); stateJson.addProperty("replaceable", state.isReplaceable()); - // TODO `blocksMovement` seems to be deprecated. How else can one get this property? - stateJson.addProperty("blocks_motion", state.blocksMovement()); if (block.getDefaultState().equals(state)) { blockJson.addProperty("default_state_id", id); diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Codec.java b/extractor/src/main/java/rs/valence/extractor/extractors/Codec.java deleted file mode 100644 index 521e2c21f..000000000 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Codec.java +++ /dev/null @@ -1,34 +0,0 @@ -package rs.valence.extractor.extractors; - -import io.netty.handler.codec.EncoderException; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtOps; -import net.minecraft.registry.DynamicRegistryManager; -import net.minecraft.registry.Registries; -import net.minecraft.registry.RegistryOps; -import net.minecraft.registry.SerializableRegistries; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.Util; - -public class Codec { - - private static final RegistryOps REGISTRY_OPS= RegistryOps.of(NbtOps.INSTANCE, DynamicRegistryManager.of(Registries.REGISTRIES)); - private final DynamicRegistryManager.Immutable registryManager; - - public Codec(MinecraftServer server) { - this.registryManager = server.getRegistryManager(); - } - - public String fileName() { - return "registry_codec.dat"; - } - - public NbtCompound extract() { - com.mojang.serialization.Codec codec = SerializableRegistries.CODEC; - //DynamicRegistryManager.get(net.minecraft.registry.RegistryKey>) method. - - NbtElement nbtElement = Util.getResult(codec.encodeStart(REGISTRY_OPS, registryManager), (error) -> new EncoderException("Failed to encode: " + error + " " + registryManager)); - return (NbtCompound) nbtElement; - } -} diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Effects.java b/extractor/src/main/java/rs/valence/extractor/extractors/Effects.java index c89de4245..414fdd099 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Effects.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Effects.java @@ -32,18 +32,18 @@ public JsonElement extract() { var attributeModifiersJson = new JsonArray(); - for (var entry : effect.getAttributeModifiers().entrySet()) { + effect.forEachAttributeModifier(0, (attribute, modifier) -> { var attributeModifierJson = new JsonObject(); - attributeModifierJson.addProperty("attribute", Registries.ATTRIBUTE.getRawId(entry.getKey())); - attributeModifierJson.addProperty("operation", entry.getValue().getOperation().getId()); - attributeModifierJson.addProperty("value", entry.getValue().getValue()); - attributeModifierJson.addProperty("uuid", entry.getValue().getId().toString()); + attributeModifierJson.addProperty("attribute", attribute.getIdAsString()); + attributeModifierJson.addProperty("operation", modifier.operation().getId()); + attributeModifierJson.addProperty("base_value", modifier.value()); + attributeModifierJson.addProperty("uuid", modifier.id().toTranslationKey()); attributeModifiersJson.add(attributeModifierJson); - } + }); - if (attributeModifiersJson.size() > 0) { + if (!attributeModifiersJson.isEmpty()) { effectJson.add("attribute_modifiers", attributeModifiersJson); } diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Enchants.java b/extractor/src/main/java/rs/valence/extractor/extractors/Enchants.java index 8bf9bdb62..7407ce67a 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Enchants.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Enchants.java @@ -3,11 +3,20 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.mojang.serialization.JsonOps; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.RegistryOps; +import net.minecraft.server.MinecraftServer; import rs.valence.extractor.Main; public class Enchants implements Main.Extractor { - public Enchants() { + private final DynamicRegistryManager.Immutable registryManager; + + public Enchants(MinecraftServer server) { + this.registryManager = server.getRegistryManager(); } @Override @@ -17,29 +26,11 @@ public String fileName() { @Override public JsonElement extract() { - var enchantsJson = new JsonArray(); - - for (var enchant : Registries.ENCHANTMENT) { - var enchantJson = new JsonObject(); - - enchantJson.addProperty("id", Registries.ENCHANTMENT.getRawId(enchant)); - enchantJson.addProperty("name", Registries.ENCHANTMENT.getId(enchant).getPath()); - enchantJson.addProperty("translation_key", enchant.getTranslationKey()); - - enchantJson.addProperty("min_level", enchant.getMinLevel()); - enchantJson.addProperty("max_level", enchant.getMaxLevel()); - enchantJson.addProperty("rarity_weight", enchant.getRarity().getWeight()); - enchantJson.addProperty("cursed", enchant.isCursed()); - - var enchantmentSources = new JsonObject(); - enchantmentSources.addProperty("treasure", enchant.isTreasure()); - enchantmentSources.addProperty("enchantment_table", enchant.isAvailableForEnchantedBookOffer()); - // All enchants except for 'Soul speed' and 'Swift sneak' are available for random selection and are only obtainable from loot chests. - enchantmentSources.addProperty("random_selection", enchant.isAvailableForRandomSelection()); + var enchantsJson = new JsonObject(); - enchantJson.add("sources", enchantmentSources); + for (var enchant : registryManager.get(RegistryKeys.ENCHANTMENT).streamEntries().toList()) { + enchantsJson.add(enchant.getKey().orElseThrow().getValue().toString(), Enchantment.CODEC.encodeStart(RegistryOps.of(JsonOps.INSTANCE, registryManager), enchant.value()).getOrThrow()); - enchantsJson.add(enchantJson); } return enchantsJson; diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Entities.java b/extractor/src/main/java/rs/valence/extractor/extractors/Entities.java index 172d01f25..2a1c8929a 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Entities.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Entities.java @@ -2,6 +2,7 @@ import com.google.gson.*; +import com.mojang.authlib.GameProfile; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityPose; @@ -13,18 +14,19 @@ import net.minecraft.entity.data.DataTracker; import net.minecraft.entity.data.TrackedData; import net.minecraft.entity.data.TrackedDataHandlerRegistry; -import net.minecraft.entity.passive.CatVariant; -import net.minecraft.entity.passive.FrogVariant; -import net.minecraft.entity.passive.SnifferEntity; +import net.minecraft.entity.passive.*; import net.minecraft.item.ItemStack; import net.minecraft.particle.ParticleEffect; import net.minecraft.registry.Registries; import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.EulerAngle; import net.minecraft.util.math.GlobalPos; import net.minecraft.village.VillagerData; +import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import org.joml.Quaternionf; import org.joml.Vector3f; @@ -33,56 +35,59 @@ import rs.valence.extractor.DummyPlayerEntity; import rs.valence.extractor.DummyWorld; import rs.valence.extractor.Main; -import rs.valence.extractor.Main.Pair; + import java.lang.reflect.ParameterizedType; import java.util.*; public class Entities implements Main.Extractor { - public Entities() { + private final ServerWorld world; + + public Entities(MinecraftServer server) { + this.world = server.getOverworld(); } - private static Pair trackedDataToJson(TrackedData data, DataTracker tracker) { - final var handler = data.getType(); + private static Main.Pair trackedDataToJson(TrackedData data, DataTracker tracker) { + final var handler = data.dataType(); final var val = tracker.get(data); if (handler == TrackedDataHandlerRegistry.BYTE) { - return new Pair<>("byte", new JsonPrimitive((Byte) val)); + return new Main.Pair<>("byte", new JsonPrimitive((Byte) val)); } else if (handler == TrackedDataHandlerRegistry.INTEGER) { - return new Pair<>("integer", new JsonPrimitive((Integer) val)); + return new Main.Pair<>("integer", new JsonPrimitive((Integer) val)); } else if (handler == TrackedDataHandlerRegistry.LONG) { - return new Pair<>("long", new JsonPrimitive((Long) val)); + return new Main.Pair<>("long", new JsonPrimitive((Long) val)); } else if (handler == TrackedDataHandlerRegistry.FLOAT) { - return new Pair<>("float", new JsonPrimitive((Float) val)); + return new Main.Pair<>("float", new JsonPrimitive((Float) val)); } else if (handler == TrackedDataHandlerRegistry.STRING) { - return new Pair<>("string", new JsonPrimitive((String) val)); + return new Main.Pair<>("string", new JsonPrimitive((String) val)); } else if (handler == TrackedDataHandlerRegistry.TEXT_COMPONENT) { // TODO: return text as json element. - return new Pair<>("text_component", new JsonPrimitive(((Text) val).getString())); + return new Main.Pair<>("text_component", new JsonPrimitive(((Text) val).getString())); } else if (handler == TrackedDataHandlerRegistry.OPTIONAL_TEXT_COMPONENT) { var res = ((Optional) val).map(o -> (JsonElement) new JsonPrimitive(((Text) o).getString())) .orElse(JsonNull.INSTANCE); - return new Pair<>("optional_text_component", res); + return new Main.Pair<>("optional_text_component", res); } else if (handler == TrackedDataHandlerRegistry.ITEM_STACK) { // TODO - return new Pair<>("item_stack", new JsonPrimitive(((ItemStack) val).toString())); + return new Main.Pair<>("item_stack", new JsonPrimitive(((ItemStack) val).toString())); } else if (handler == TrackedDataHandlerRegistry.BOOLEAN) { - return new Pair<>("boolean", new JsonPrimitive((Boolean) val)); + return new Main.Pair<>("boolean", new JsonPrimitive((Boolean) val)); } else if (handler == TrackedDataHandlerRegistry.ROTATION) { var json = new JsonObject(); var ea = (EulerAngle) val; json.addProperty("pitch", ea.getPitch()); json.addProperty("yaw", ea.getYaw()); json.addProperty("roll", ea.getRoll()); - return new Pair<>("rotation", json); + return new Main.Pair<>("rotation", json); } else if (handler == TrackedDataHandlerRegistry.BLOCK_POS) { var bp = (BlockPos) val; var json = new JsonObject(); json.addProperty("x", bp.getX()); json.addProperty("y", bp.getY()); json.addProperty("z", bp.getZ()); - return new Pair<>("block_pos", json); + return new Main.Pair<>("block_pos", json); } else if (handler == TrackedDataHandlerRegistry.OPTIONAL_BLOCK_POS) { - return new Pair<>("optional_block_pos", ((Optional) val).map(o -> { + return new Main.Pair<>("optional_block_pos", ((Optional) val).map(o -> { var bp = (BlockPos) o; var json = new JsonObject(); json.addProperty("x", bp.getX()); @@ -91,26 +96,34 @@ private static Pair trackedDataToJson(TrackedData data, return (JsonElement) json; }).orElse(JsonNull.INSTANCE)); } else if (handler == TrackedDataHandlerRegistry.FACING) { - return new Pair<>("facing", new JsonPrimitive(val.toString())); + return new Main.Pair<>("facing", new JsonPrimitive(val.toString())); } else if (handler == TrackedDataHandlerRegistry.OPTIONAL_UUID) { var res = ((Optional) val).map(o -> (JsonElement) new JsonPrimitive(o.toString())) .orElse(JsonNull.INSTANCE); - return new Pair<>("optional_uuid", res); + return new Main.Pair<>("optional_uuid", res); } else if (handler == TrackedDataHandlerRegistry.BLOCK_STATE) { // TODO: get raw block state ID. var state = (BlockState) val; - return new Pair<>("block_state", new JsonPrimitive(state.toString())); + return new Main.Pair<>("block_state", new JsonPrimitive(state.toString())); } else if (handler == TrackedDataHandlerRegistry.OPTIONAL_BLOCK_STATE) { // TODO: get raw block state ID. var res = ((Optional) val).map(o -> (JsonElement) new JsonPrimitive(o.toString())) .orElse(JsonNull.INSTANCE); - return new Pair<>("optional_block_state", res); + return new Main.Pair<>("optional_block_state", res); } else if (handler == TrackedDataHandlerRegistry.NBT_COMPOUND) { // TODO: base64 binary representation or SNBT? - return new Pair<>("nbt_compound", new JsonPrimitive(val.toString())); + return new Main.Pair<>("nbt_compound", new JsonPrimitive(val.toString())); } else if (handler == TrackedDataHandlerRegistry.PARTICLE) { var id = Registries.PARTICLE_TYPE.getId(((ParticleEffect) val).getType()); - return new Pair<>("particle", new JsonPrimitive(id.getPath())); + return new Main.Pair<>("particle", new JsonPrimitive(id.getPath())); + } else if (handler == TrackedDataHandlerRegistry.PARTICLE_LIST) { + List particleList = (List) val; + JsonArray json = new JsonArray(); + for (ParticleEffect particleEffect : particleList) { + var id = Registries.PARTICLE_TYPE.getId(((ParticleEffect) val).getType()); + json.add(id.getPath()); + } + return new Main.Pair<>("particle_list", json); } else if (handler == TrackedDataHandlerRegistry.VILLAGER_DATA) { var vd = (VillagerData) val; var json = new JsonObject(); @@ -119,45 +132,51 @@ private static Pair trackedDataToJson(TrackedData data, json.addProperty("type", type); json.addProperty("profession", profession); json.addProperty("level", vd.getLevel()); - return new Pair<>("villager_data", json); + return new Main.Pair<>("villager_data", json); } else if (handler == TrackedDataHandlerRegistry.OPTIONAL_INT) { var opt = (OptionalInt) val; - return new Pair<>("optional_int", opt.isPresent() ? new JsonPrimitive(opt.getAsInt()) : JsonNull.INSTANCE); + return new Main.Pair<>("optional_int", opt.isPresent() ? new JsonPrimitive(opt.getAsInt()) : JsonNull.INSTANCE); } else if (handler == TrackedDataHandlerRegistry.ENTITY_POSE) { - return new Pair<>("entity_pose", new JsonPrimitive(((EntityPose) val).name().toLowerCase(Locale.ROOT))); + return new Main.Pair<>("entity_pose", new JsonPrimitive(((EntityPose) val).name().toLowerCase(Locale.ROOT))); } else if (handler == TrackedDataHandlerRegistry.CAT_VARIANT) { - return new Pair<>("cat_variant", - new JsonPrimitive(Registries.CAT_VARIANT.getId((CatVariant) val).getPath())); + return new Main.Pair<>("cat_variant", + new JsonPrimitive(((RegistryEntry) val).getIdAsString())); + } else if (handler == TrackedDataHandlerRegistry.WOLF_VARIANT) { + return new Main.Pair<>("wolf_variant", + new JsonPrimitive(((RegistryEntry) val).getIdAsString())); } else if (handler == TrackedDataHandlerRegistry.FROG_VARIANT) { - return new Pair<>("frog_variant", - new JsonPrimitive(Registries.FROG_VARIANT.getId((FrogVariant) val).getPath())); + return new Main.Pair<>("frog_variant", + new JsonPrimitive(((RegistryEntry) val).getIdAsString())); } else if (handler == TrackedDataHandlerRegistry.OPTIONAL_GLOBAL_POS) { - return new Pair<>("optional_global_pos", ((Optional) val).map(o -> { + return new Main.Pair<>("optional_global_pos", ((Optional) val).map(o -> { var gp = (GlobalPos) o; var json = new JsonObject(); - json.addProperty("dimension", gp.getDimension().getValue().toString()); + json.addProperty("dimension", gp.dimension().getValue().toString()); var posJson = new JsonObject(); - posJson.addProperty("x", gp.getPos().getX()); - posJson.addProperty("y", gp.getPos().getY()); - posJson.addProperty("z", gp.getPos().getZ()); + posJson.addProperty("x", gp.pos().getX()); + posJson.addProperty("y", gp.pos().getY()); + posJson.addProperty("z", gp.pos().getZ()); json.add("position", posJson); return (JsonElement) json; }).orElse(JsonNull.INSTANCE)); } else if (handler == TrackedDataHandlerRegistry.PAINTING_VARIANT) { var variant = ((RegistryEntry) val).getKey().map(k -> k.getValue().getPath()).orElse(""); - return new Pair<>("painting_variant", new JsonPrimitive(variant)); + return new Main.Pair<>("painting_variant", new JsonPrimitive(variant)); } else if (handler == TrackedDataHandlerRegistry.SNIFFER_STATE) { - return new Pair<>("sniffer_state", + return new Main.Pair<>("sniffer_state", new JsonPrimitive(((SnifferEntity.State) val).name().toLowerCase(Locale.ROOT))); + } else if (handler == TrackedDataHandlerRegistry.ARMADILLO_STATE) { + return new Main.Pair<>("armadillo_state", + new JsonPrimitive(((ArmadilloEntity.State) val).name().toLowerCase(Locale.ROOT))); } else if (handler == TrackedDataHandlerRegistry.VECTOR3F) { var vec = (Vector3f) val; var json = new JsonObject(); json.addProperty("x", vec.x); json.addProperty("y", vec.y); json.addProperty("z", vec.z); - return new Pair<>("vector3f", json); + return new Main.Pair<>("vector3f", json); } else if (handler == TrackedDataHandlerRegistry.QUATERNIONF) { var quat = (Quaternionf) val; var json = new JsonObject(); @@ -165,10 +184,10 @@ private static Pair trackedDataToJson(TrackedData data, json.addProperty("y", quat.y); json.addProperty("z", quat.z); json.addProperty("w", quat.w); - return new Pair<>("quaternionf", json); + return new Main.Pair<>("quaternionf", json); } else { throw new IllegalArgumentException( - "Unexpected tracked handler of ID " + TrackedDataHandlerRegistry.getId(handler)); + "Unexpected tracked handler of ID " + TrackedDataHandlerRegistry.getId(handler) + handler.toString()); } } @@ -181,14 +200,16 @@ public String fileName() { @SuppressWarnings("unchecked") public JsonElement extract() throws IllegalAccessException, NoSuchFieldException { - final var entityClassToType = new HashMap, EntityType>(); + final var entityList = new ArrayList, EntityType>>(); + var entityClassTypeMap = new HashMap, EntityType>(); for (var f : EntityType.class.getFields()) { if (f.getType().equals(EntityType.class)) { var entityClass = (Class) ((ParameterizedType) f.getGenericType()) .getActualTypeArguments()[0]; var entityType = (EntityType) f.get(null); - entityClassToType.put(entityClass, entityType); + entityList.add(new Main.Pair<>(entityClass, entityType)); + entityClassTypeMap.put(entityClass, entityType); } } @@ -197,11 +218,11 @@ public JsonElement extract() throws IllegalAccessException, NoSuchFieldException var entitiesMap = new TreeMap, JsonElement>(new ClassComparator()); - for (var entry : entityClassToType.entrySet()) { - var entityClass = entry.getKey(); + for (var entry : entityList) { + var entityClass = entry.left(); @Nullable - var entityType = entry.getValue(); - assert entityType != null; + var entityType = entry.right(); + assert null != entityType; // While we can use the tracked data registry and reflection to get the tracked // fields on entities, we won't know what their default values are because they @@ -210,22 +231,23 @@ public JsonElement extract() throws IllegalAccessException, NoSuchFieldException // the data tracker field from the base entity class. // We also handle player entities specially since they cannot be spawned with // EntityType#create. - final var entityInstance = entityType.equals(EntityType.PLAYER) ? DummyPlayerEntity.INSTANCE - : entityType.create(DummyWorld.INSTANCE); + final var entityInstance = entityType.equals(EntityType.PLAYER) ? new DummyPlayerEntity(world, BlockPos.ofFloored(0, 70, 0), 0, new GameProfile(UUID.randomUUID(), "cooldude"), null) + : entityType.create(world); + final var dataTracker = (DataTracker) dataTrackerField.get(entityInstance); - while (entitiesMap.get(entityClass) == null) { + while (null == entitiesMap.get(entityClass)) { var entityJson = new JsonObject(); var parent = entityClass.getSuperclass(); - var hasParent = parent != null && Entity.class.isAssignableFrom(parent); + var hasParent = null != parent && Entity.class.isAssignableFrom(parent); if (hasParent) { entityJson.addProperty("parent", parent.getSimpleName()); } - if (entityType != null) { + if (null != entityType) { entityJson.addProperty("type", Registries.ENTITY_TYPE.getId(entityType).getPath()); entityJson.add("translation_key", new JsonPrimitive(entityType.getTranslationKey())); @@ -238,10 +260,11 @@ public JsonElement extract() throws IllegalAccessException, NoSuchFieldException var trackedData = (TrackedData) entityField.get(null); + var fieldJson = new JsonObject(); var fieldName = entityField.getName().toLowerCase(Locale.ROOT); fieldJson.addProperty("name", fieldName); - fieldJson.addProperty("index", trackedData.getId()); + fieldJson.addProperty("index", trackedData.id()); var data = Entities.trackedDataToJson(trackedData, dataTracker); fieldJson.addProperty("type", data.left()); @@ -256,14 +279,14 @@ public JsonElement extract() throws IllegalAccessException, NoSuchFieldException var type = (EntityType) entityType; var defaultAttributes = DefaultAttributeRegistry.get(type); var attributesJson = new JsonArray(); - if (defaultAttributes != null) { + if (null != defaultAttributes) { var instancesField = defaultAttributes.getClass().getDeclaredField("instances"); instancesField.setAccessible(true); var instances = (Map) instancesField .get(defaultAttributes); for (var instance : instances.values()) { - var attribute = instance.getAttribute(); + var attribute = instance.getAttribute().value(); var attributeJson = new JsonObject(); @@ -278,12 +301,12 @@ public JsonElement extract() throws IllegalAccessException, NoSuchFieldException } var bb = entityInstance.getBoundingBox(); - if (bb != null && entityType != null) { + if (null != bb && null != entityType) { var boundingBoxJson = new JsonObject(); - boundingBoxJson.addProperty("size_x", bb.getXLength()); - boundingBoxJson.addProperty("size_y", bb.getYLength()); - boundingBoxJson.addProperty("size_z", bb.getZLength()); + boundingBoxJson.addProperty("size_x", bb.getLengthX()); + boundingBoxJson.addProperty("size_y", bb.getLengthY()); + boundingBoxJson.addProperty("size_z", bb.getLengthZ()); entityJson.add("default_bounding_box", boundingBoxJson); } @@ -295,7 +318,7 @@ public JsonElement extract() throws IllegalAccessException, NoSuchFieldException } entityClass = (Class) parent; - entityType = entityClassToType.get(entityClass); + entityType = entityClassTypeMap.get(entityClass); } } diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Items.java b/extractor/src/main/java/rs/valence/extractor/extractors/Items.java index ed745badb..f202e96b1 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Items.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Items.java @@ -3,11 +3,25 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.mojang.serialization.JsonOps; +import net.minecraft.component.ComponentMap; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.FoodComponent; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.RegistryOps; +import net.minecraft.server.MinecraftServer; import rs.valence.extractor.Main; public class Items implements Main.Extractor { - public Items() { + private final DynamicRegistryManager.Immutable registryManager; + + public Items(MinecraftServer server) { + this.registryManager = server.getRegistryManager(); } @Override @@ -19,48 +33,22 @@ public String fileName() { public JsonElement extract() throws Exception { var itemsJson = new JsonArray(); - for (var item : Registries.ITEM) { + for (var item : registryManager.get(RegistryKeys.ITEM).streamEntries().toList()) { var itemJson = new JsonObject(); - itemJson.addProperty("id", Registries.ITEM.getRawId(item)); - itemJson.addProperty("name", Registries.ITEM.getId(item).getPath()); - itemJson.addProperty("translation_key", item.getTranslationKey()); - itemJson.addProperty("max_stack", item.getMaxCount()); - itemJson.addProperty("max_durability", item.getMaxDamage()); - itemJson.addProperty("enchantability", item.getEnchantability()); - itemJson.addProperty("fireproof", item.isFireproof()); - - if (item.getFoodComponent() != null) { - var foodJson = new JsonObject(); - var foodComp = item.getFoodComponent(); - - foodJson.addProperty("hunger", foodComp.getHunger()); - foodJson.addProperty("saturation", foodComp.getSaturationModifier()); - foodJson.addProperty("always_edible", foodComp.isAlwaysEdible()); - foodJson.addProperty("meat", foodComp.isMeat()); - foodJson.addProperty("snack", foodComp.isSnack()); - - itemJson.add("food", foodJson); - var effectsJson = new JsonArray(); - for (var pair : foodComp.getStatusEffects()) { - var effectJson = new JsonObject(); + itemJson.addProperty("id", item.getKey().orElseThrow().getValue().toString()); + itemJson.addProperty("name", item.getKey().orElseThrow().getValue().toString()); + Item realItem = item.value(); + itemJson.addProperty("translation_key", realItem.getTranslationKey()); + itemJson.addProperty("max_stack", realItem.getMaxCount()); + itemJson.addProperty("max_durability", realItem.getDefaultStack().getMaxDamage()); + itemJson.addProperty("enchantability", realItem.getEnchantability()); + itemJson.addProperty("fireproof", realItem.getComponents().contains(DataComponentTypes.FIRE_RESISTANT)); - var effect = pair.getFirst(); - var chance = pair.getSecond(); - - effectJson.addProperty("chance", chance); - effectJson.addProperty("translation_key", effect.getEffectType().getTranslationKey()); - // TODO: more effect information. - - effectsJson.add(effectJson); - } - - foodJson.add("effects", effectsJson); - } + itemJson.add("components", ComponentMap.CODEC.encodeStart(RegistryOps.of(JsonOps.INSTANCE, registryManager), realItem.getComponents()).getOrThrow()); itemsJson.add(itemJson); } - return itemsJson; } } diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Misc.java b/extractor/src/main/java/rs/valence/extractor/extractors/Misc.java index f0dc34229..43269280f 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Misc.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Misc.java @@ -2,6 +2,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import net.fabricmc.fabric.impl.biome.modification.BuiltInRegistryKeys; import net.minecraft.entity.EntityPose; import net.minecraft.entity.EntityStatuses; import net.minecraft.entity.attribute.ClampedEntityAttribute; @@ -10,7 +11,10 @@ import net.minecraft.entity.data.TrackedDataHandlerRegistry; import net.minecraft.entity.passive.SnifferEntity; import net.minecraft.network.packet.s2c.play.EntityAnimationS2CPacket; +import net.minecraft.registry.BuiltinRegistries; import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryBuilder; +import net.minecraft.registry.RegistryWrapper; import net.minecraft.util.math.Direction; import rs.valence.extractor.Main; import java.lang.reflect.Modifier; @@ -36,7 +40,7 @@ public JsonElement extract() throws Exception { var entityStatusJson = new JsonObject(); for (var field : EntityStatuses.class.getDeclaredFields()) { if (field.canAccess(null) && field.get(null) instanceof Byte code) { - if (field.getName().equals("field_30030")) { + if ("field_30030".equals(field.getName())) { entityStatusJson.addProperty("stop_attack", code); } else { entityStatusJson.addProperty(field.getName().toLowerCase(Locale.ROOT), code); @@ -82,15 +86,7 @@ public JsonElement extract() throws Exception { } miscJson.add("frog_variant", frogVariantJson); - var paintingVariantJson = new JsonObject(); - for (var variant : Registries.PAINTING_VARIANT) { - var variantJson = new JsonObject(); - variantJson.addProperty("id", Registries.PAINTING_VARIANT.getRawId(variant)); - variantJson.addProperty("width", variant.getWidth()); - variantJson.addProperty("height", variant.getHeight()); - paintingVariantJson.add(Registries.PAINTING_VARIANT.getId(variant).getPath(), variantJson); - } - miscJson.add("painting_variant", paintingVariantJson); + var directionJson = new JsonObject(); for (var dir : Direction.values()) { diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/PacketRegistries.java b/extractor/src/main/java/rs/valence/extractor/extractors/PacketRegistries.java new file mode 100644 index 000000000..13c1583cf --- /dev/null +++ b/extractor/src/main/java/rs/valence/extractor/extractors/PacketRegistries.java @@ -0,0 +1,45 @@ +package rs.valence.extractor.extractors; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.serialization.Codec; +import com.mojang.serialization.JsonOps; +import net.minecraft.registry.*; +import net.minecraft.server.MinecraftServer; +import rs.valence.extractor.Main; + +import java.util.stream.Stream; + +public class PacketRegistries implements Main.Extractor { + + private final DynamicRegistryManager.Immutable registryManager; + private final CombinedDynamicRegistries registries; + + public PacketRegistries(MinecraftServer server) { + this.registryManager = server.getRegistryManager(); + this.registries = server.getCombinedDynamicRegistries(); + } + + public String fileName() { + return "registry_codec.json"; + } + + public static JsonObject mapJson(RegistryLoader.Entry registry_entry, DynamicRegistryManager.Immutable registryManager, CombinedDynamicRegistries combinedRegistries) { + Codec codec = registry_entry.elementCodec(); + Registry registry = registryManager.get(registry_entry.key()); + JsonObject json = new JsonObject(); + registry.streamEntries().forEach(entry -> { + json.add(entry.getKey().orElseThrow().getValue().toString(), codec.encodeStart(combinedRegistries.getCombinedRegistryManager().getOps(JsonOps.INSTANCE), entry.value()).resultOrPartial((e) -> Main.LOGGER.error("Cannot encode json: {}", e)).orElseThrow()); + }); + return json; + } + + public JsonElement extract() { + Stream> registries = RegistryLoader.SYNCED_REGISTRIES.stream(); + JsonObject json = new JsonObject(); + registries.forEach(entry -> { + json.add(entry.key().getValue().toString(), mapJson(entry, registryManager, this.registries)); + }); + return json; + } +} diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Packets.java b/extractor/src/main/java/rs/valence/extractor/extractors/Packets.java index 9f1ae64b9..d007565bd 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Packets.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Packets.java @@ -3,12 +3,13 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import net.minecraft.network.NetworkSide; +import io.netty.buffer.ByteBuf; import net.minecraft.network.NetworkState; +import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.state.*; import rs.valence.extractor.Main; -import java.util.Locale; -import java.util.TreeSet; +import java.io.IOException; public class Packets implements Main.Extractor { @Override @@ -17,26 +18,30 @@ public String fileName() { } @Override - public JsonElement extract() { + public JsonElement extract() throws IOException { var packetsJson = new JsonArray(); - for (var side : NetworkSide.values()) { - for (var state : NetworkState.values()) { - var map = state.getPacketIdToPacketMap(side); - - for (var id : new TreeSet<>(map.keySet())) { - var packetJson = new JsonObject(); - - packetJson.addProperty("name", map.get(id.intValue()).getSimpleName()); - packetJson.addProperty("side", side.name().toLowerCase(Locale.ROOT)); - packetJson.addProperty("state", state.name().toLowerCase(Locale.ROOT)); - packetJson.addProperty("id", id); - - packetsJson.add(packetJson); - } - } - } + serializeFactory(HandshakeStates.C2S_FACTORY, packetsJson); + serializeFactory(QueryStates.C2S_FACTORY, packetsJson); + serializeFactory(QueryStates.S2C_FACTORY, packetsJson); + serializeFactory(LoginStates.C2S_FACTORY, packetsJson); + serializeFactory(LoginStates.S2C_FACTORY, packetsJson); + serializeFactory(ConfigurationStates.C2S_FACTORY, packetsJson); + serializeFactory(ConfigurationStates.S2C_FACTORY, packetsJson); + serializeFactory(PlayStateFactories.C2S, packetsJson); + serializeFactory(PlayStateFactories.S2C, packetsJson); return packetsJson; } + + private static void serializeFactory(NetworkState.Factory factory, JsonArray json) { + factory.forEachPacketType((type, i) -> { + var packetJson = new JsonObject(); + packetJson.addProperty("name", type.id().getPath()); + packetJson.addProperty("phase", factory.phase().getId()); + packetJson.addProperty("side", factory.side().getName()); + packetJson.addProperty("id", i); + json.add(packetJson); + }); + } } diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Paintings.java b/extractor/src/main/java/rs/valence/extractor/extractors/Paintings.java new file mode 100644 index 000000000..8a22a72a1 --- /dev/null +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Paintings.java @@ -0,0 +1,41 @@ +package rs.valence.extractor.extractors; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.serialization.JsonOps; +import net.minecraft.entity.decoration.painting.PaintingVariant; +import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.RegistryOps; +import net.minecraft.server.MinecraftServer; +import rs.valence.extractor.Main; + +public class Paintings implements Main.Extractor { + + private final DynamicRegistryManager.Immutable registryManager; + + public Paintings(MinecraftServer server) { + this.registryManager = server.getRegistryManager(); + } + + @Override + public String fileName() { + return "paintings.json"; + } + + @Override + public JsonElement extract() throws Exception { + var dataDrivenMiscJson = new JsonObject(); + + var paintingRegistry = registryManager.get(RegistryKeys.PAINTING_VARIANT); + + var codec = PaintingVariant.CODEC; + + JsonObject json = new JsonObject(); + paintingRegistry.streamEntries().forEach(entry -> { + json.add(entry.getKey().orElseThrow().getValue().toString(), codec.encodeStart(RegistryOps.of(JsonOps.INSTANCE, registryManager), entry.value()).getOrThrow()); + }); + + return json; + } +} diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Tags.java b/extractor/src/main/java/rs/valence/extractor/extractors/Tags.java index 2ef189144..f7d3976af 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Tags.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Tags.java @@ -64,7 +64,7 @@ private static Map serializeTags(Registry registry RegistryEntryList registryEntryList = pair.getSecond(); JsonArray intList = new JsonArray(registryEntryList.size()); for (RegistryEntry registryEntry : registryEntryList) { - if (registryEntry.getType() != RegistryEntry.Type.REFERENCE) { + if (RegistryEntry.Type.REFERENCE != registryEntry.getType()) { throw new IllegalStateException("Can't serialize unregistered value " + registryEntry); } intList.add(registry.getRawId(registryEntry.value())); diff --git a/extractor/src/main/resources/fabric.mod.json b/extractor/src/main/resources/fabric.mod.json index 89a8967cb..b4e79d041 100644 --- a/extractor/src/main/resources/fabric.mod.json +++ b/extractor/src/main/resources/fabric.mod.json @@ -22,8 +22,8 @@ ], "depends": { "fabricloader": ">=0.14.6", - "minecraft": "~1.20.1", - "java": ">=17" + "minecraft": "~1.21", + "java": ">=21" }, "suggests": { "another-mod": "*"