From 7463d67c8514b2d02ac24695ea76a9f7c888ae26 Mon Sep 17 00:00:00 2001
From: Player <player@player.to>
Date: Thu, 17 Mar 2022 00:16:03 +0100
Subject: [PATCH] 22w11a

---
 .../lookup/entity/EntityApiLookupImpl.java    |  2 +-
 .../biome/v1/BiomeModificationContext.java    |  6 --
 .../api/biome/v1/BiomeSelectionContext.java   | 10 +--
 .../fabric/api/biome/v1/BiomeSelectors.java   | 16 +---
 .../fabric/impl/biome/TheEndBiomeData.java    | 90 ++++++++++++-------
 .../fabric/impl/biome/WeightedPicker.java     |  4 +
 .../BiomeModificationContextImpl.java         | 13 +--
 .../BiomeSelectionContextImpl.java            | 14 +--
 .../modification/BuiltInRegistryKeys.java     |  8 +-
 .../mixin/biome/MixinChunkGenerator.java      | 37 ++++++++
 .../mixin/biome/MixinTheEndBiomeSource.java   |  8 +-
 .../fabric-biome-api-v1.accesswidener         |  2 -
 .../resources/fabric-biome-api-v1.mixins.json |  1 +
 .../fabric/test/biome/FabricBiomeTest.java    |  4 +-
 .../mixin/command/CommandManagerMixin.java    |  5 +-
 .../v1/provider/FabricTagProvider.java        | 18 ++--
 ...abric-data-generation-api-v1.accesswidener |  5 +-
 .../datagen/DataGeneratorTestEntrypoint.java  |  4 +-
 .../test/dimension/VoidChunkGenerator.java    | 32 ++-----
 .../MixinClientPlayerInteractionManager.java  | 36 +++++---
 .../MixinServerPlayerInteractionManager.java  |  8 +-
 .../mixin/gametest/ArgumentTypesMixin.java    | 13 +--
 .../mixin/gametest/CommandManagerMixin.java   |  5 +-
 .../mininglevel/MiningLevelManagerImpl.java   |  4 +-
 .../resource/loader/GroupResourcePack.java    |  4 +-
 .../resource/loader/ModNioResourcePack.java   | 17 ++--
 .../pack/ProgrammerArtResourcePack.java       |  6 +-
 .../loader/DefaultResourcePackMixin.java      |  4 +-
 .../loader/client/CreateWorldScreenMixin.java |  9 ++
 .../fabric/mixin/screen/MouseMixin.java       |  2 +-
 gradle.properties                             |  8 +-
 src/main/resources/fabric.mod.json            |  2 +-
 32 files changed, 220 insertions(+), 177 deletions(-)
 create mode 100644 fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/mixin/biome/MixinChunkGenerator.java

diff --git a/fabric-api-lookup-api-v1/src/main/java/net/fabricmc/fabric/impl/lookup/entity/EntityApiLookupImpl.java b/fabric-api-lookup-api-v1/src/main/java/net/fabricmc/fabric/impl/lookup/entity/EntityApiLookupImpl.java
index ddebc88f5..c22d22550 100644
--- a/fabric-api-lookup-api-v1/src/main/java/net/fabricmc/fabric/impl/lookup/entity/EntityApiLookupImpl.java
+++ b/fabric-api-lookup-api-v1/src/main/java/net/fabricmc/fabric/impl/lookup/entity/EntityApiLookupImpl.java
@@ -42,7 +42,7 @@ import net.fabricmc.fabric.api.lookup.v1.entity.EntityApiLookup;
 
 public class EntityApiLookupImpl<A, C> implements EntityApiLookup<A, C> {
 	private static final Logger LOGGER = LoggerFactory.getLogger("fabric-api-lookup-api-v1/entity");
-	private static final ApiLookupMap<EntityApiLookup<?, ?>> LOOKUPS = ApiLookupMap.create(EntityApiLookupImpl::new);
+	private static final ApiLookupMap<EntityApiLookup<?, ?>> LOOKUPS = ApiLookupMap.<EntityApiLookup<?, ?>>create(EntityApiLookupImpl::new);
 	private static final Map<Class<?>, Set<EntityType<?>>> REGISTERED_SELVES = new HashMap<>();
 	private static boolean checkEntityLookup = true;
 
diff --git a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeModificationContext.java b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeModificationContext.java
index 6ac6ccaa1..204429eac 100644
--- a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeModificationContext.java
+++ b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeModificationContext.java
@@ -45,12 +45,6 @@ import net.fabricmc.fabric.impl.biome.modification.BuiltInRegistryKeys;
  * <p><b>Experimental feature</b>, may be removed or changed without further notice.
  */
 public interface BiomeModificationContext {
-	/**
-	 * @see Biome#getCategory()
-	 * @see Biome.Builder#category(Biome.Category)
-	 */
-	void setCategory(Biome.Category category);
-
 	/**
 	 * Returns the modification context for the biomes weather properties.
 	 */
diff --git a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeSelectionContext.java b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeSelectionContext.java
index 88a16f311..3fa3ff9c1 100644
--- a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeSelectionContext.java
+++ b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeSelectionContext.java
@@ -26,8 +26,8 @@ import net.minecraft.util.registry.RegistryKey;
 import net.minecraft.world.biome.Biome;
 import net.minecraft.world.dimension.DimensionOptions;
 import net.minecraft.world.gen.feature.ConfiguredFeature;
-import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
 import net.minecraft.world.gen.feature.PlacedFeature;
+import net.minecraft.world.gen.feature.StructureFeature;
 
 import net.fabricmc.fabric.impl.biome.modification.BuiltInRegistryKeys;
 
@@ -121,8 +121,8 @@ public interface BiomeSelectionContext {
 	 *
 	 * <p>This method is intended for use with the Vanilla configured structures found in {@link net.minecraft.world.gen.feature.ConfiguredStructureFeatures}.
 	 */
-	default boolean validForBuiltInStructure(ConfiguredStructureFeature<?, ?> configuredStructure) {
-		RegistryKey<ConfiguredStructureFeature<?, ?>> key = BuiltInRegistryKeys.get(configuredStructure);
+	default boolean validForBuiltInStructure(StructureFeature structureFeature) {
+		RegistryKey<StructureFeature> key = BuiltInRegistryKeys.get(structureFeature);
 		return validForStructure(key);
 	}
 
@@ -130,14 +130,14 @@ public interface BiomeSelectionContext {
 	 * Returns true if the configured structure with the given key can start in this biome in any chunk generator
 	 * used by the current world-save.
 	 */
-	boolean validForStructure(RegistryKey<ConfiguredStructureFeature<?, ?>> key);
+	boolean validForStructure(RegistryKey<StructureFeature> key);
 
 	/**
 	 * Tries to retrieve the registry key for the given configured feature, which should be from this biomes
 	 * current structure list. May be empty if the configured feature is not registered, or does not come
 	 * from this biomes feature list.
 	 */
-	Optional<RegistryKey<ConfiguredStructureFeature<?, ?>>> getStructureKey(ConfiguredStructureFeature<?, ?> configuredStructure);
+	Optional<RegistryKey<StructureFeature>> getStructureKey(StructureFeature structureFeature);
 
 	/**
 	 * Tries to determine whether this biome generates in a specific dimension, based on the {@link net.minecraft.world.gen.GeneratorOptions}
diff --git a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeSelectors.java b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeSelectors.java
index f84c38f59..e91a2938a 100644
--- a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeSelectors.java
+++ b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/api/biome/v1/BiomeSelectors.java
@@ -17,16 +17,14 @@
 package net.fabricmc.fabric.api.biome.v1;
 
 import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
 import java.util.Set;
 import java.util.function.Predicate;
 
 import com.google.common.collect.ImmutableSet;
 
-import net.minecraft.tag.TagKey;
 import net.minecraft.entity.EntityType;
 import net.minecraft.entity.SpawnGroup;
+import net.minecraft.tag.TagKey;
 import net.minecraft.util.registry.BuiltinRegistries;
 import net.minecraft.util.registry.RegistryKey;
 import net.minecraft.world.biome.Biome;
@@ -167,16 +165,4 @@ public final class BiomeSelectors {
 			return false;
 		};
 	}
-
-	/**
-	 * Matches Biomes that have one of the given categories.
-	 *
-	 * @see Biome#getCategory()
-	 */
-	public static Predicate<BiomeSelectionContext> categories(Biome.Category... categories) {
-		Set<Biome.Category> categorySet = EnumSet.noneOf(Biome.Category.class);
-		Collections.addAll(categorySet, categories);
-
-		return context -> categorySet.contains(context.getBiome().category);
-	}
 }
diff --git a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/TheEndBiomeData.java b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/TheEndBiomeData.java
index e465170ef..40f419f94 100644
--- a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/TheEndBiomeData.java
+++ b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/TheEndBiomeData.java
@@ -18,6 +18,9 @@ package net.fabricmc.fabric.impl.biome;
 
 import java.util.IdentityHashMap;
 import java.util.Map;
+import java.util.WeakHashMap;
+
+import javax.annotation.Nullable;
 
 import com.google.common.base.Preconditions;
 import org.jetbrains.annotations.ApiStatus;
@@ -29,6 +32,7 @@ import net.minecraft.util.registry.RegistryKey;
 import net.minecraft.world.biome.Biome;
 import net.minecraft.world.biome.BiomeKeys;
 import net.minecraft.world.biome.source.TheEndBiomeSource;
+import net.minecraft.world.biome.source.util.MultiNoiseUtil;
 import net.minecraft.world.gen.random.AtomicSimpleRandom;
 import net.minecraft.world.gen.random.ChunkRandom;
 
@@ -79,28 +83,30 @@ public final class TheEndBiomeData {
 		END_BARRENS_MAP.computeIfAbsent(highlands, key -> new WeightedPicker<>()).add(barrens, weight);
 	}
 
-	public static Overrides createOverrides(Registry<Biome> biomeRegistry, long seed) {
-		return new Overrides(biomeRegistry, seed);
+	public static Overrides createOverrides(Registry<Biome> biomeRegistry) {
+		return new Overrides(biomeRegistry);
 	}
 
 	/**
 	 * An instance of this class is attached to each {@link TheEndBiomeSource}.
 	 */
 	public static class Overrides {
-		private final PerlinNoiseSampler sampler;
-
 		// Vanilla entries to compare against
 		private final RegistryEntry<Biome> endMidlands;
 		private final RegistryEntry<Biome> endBarrens;
 		private final RegistryEntry<Biome> endHighlands;
 
 		// Maps where the keys have been resolved to actual entries
-		private final Map<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>> endBiomesMap;
-		private final Map<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>> endMidlandsMap;
-		private final Map<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>> endBarrensMap;
+		private final @Nullable Map<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>> endBiomesMap;
+		private final @Nullable Map<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>> endMidlandsMap;
+		private final @Nullable Map<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>> endBarrensMap;
 
-		public Overrides(Registry<Biome> biomeRegistry, long seed) {
-			this.sampler = new PerlinNoiseSampler(new ChunkRandom(new AtomicSimpleRandom(seed)));
+		// cache for our own sampler (used for random biome replacement selection)
+		private final Map<MultiNoiseUtil.MultiNoiseSampler, PerlinNoiseSampler> samplers = new WeakHashMap<>();
+		// current seed, set from ChunkGenerator hook since it is not normally available
+		private static ThreadLocal<Long> seed = new ThreadLocal<>();
+
+		public Overrides(Registry<Biome> biomeRegistry) {
 			this.endMidlands = biomeRegistry.entryOf(BiomeKeys.END_MIDLANDS);
 			this.endBarrens = biomeRegistry.entryOf(BiomeKeys.END_BARRENS);
 			this.endHighlands = biomeRegistry.entryOf(BiomeKeys.END_HIGHLANDS);
@@ -111,40 +117,60 @@ public final class TheEndBiomeData {
 		}
 
 		// Resolves all RegistryKey instances to RegistryEntries
-		private Map<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>> resolveOverrides(Registry<Biome> biomeRegistry, Map<RegistryKey<Biome>, WeightedPicker<RegistryKey<Biome>>> overrides) {
-			var result = new IdentityHashMap<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>>(overrides.size());
+		private @Nullable Map<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>> resolveOverrides(Registry<Biome> biomeRegistry, Map<RegistryKey<Biome>, WeightedPicker<RegistryKey<Biome>>> overrides) {
+			Map<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>> result = new IdentityHashMap<>(overrides.size());
 
 			for (Map.Entry<RegistryKey<Biome>, WeightedPicker<RegistryKey<Biome>>> entry : overrides.entrySet()) {
-				result.put(biomeRegistry.entryOf(entry.getKey()), entry.getValue().map(biomeRegistry::entryOf));
+				WeightedPicker<RegistryKey<Biome>> picker = entry.getValue();
+				if (picker.getEntryCount() <= 1) continue; // don't use no-op entries
+
+				result.put(biomeRegistry.entryOf(entry.getKey()), picker.map(biomeRegistry::entryOf));
 			}
 
-			return result;
+			return result.isEmpty() ? null : result;
 		}
 
-		public RegistryEntry<Biome> pick(int x, int y, int z, RegistryEntry<Biome> vanillaBiome) {
-			RegistryEntry<Biome> replacementKey;
-
-			// The x and z of the entry are divided by 64 to ensure custom biomes are large enough; going larger than this]
-			// seems to make custom biomes too hard to find.
+		public RegistryEntry<Biome> pick(int x, int y, int z, MultiNoiseUtil.MultiNoiseSampler noise, RegistryEntry<Biome> vanillaBiome) {
 			if (vanillaBiome == endMidlands || vanillaBiome == endBarrens) {
-				// Since the highlands picker is statically populated by InternalBiomeData, picker will never be null.
-				WeightedPicker<RegistryEntry<Biome>> highlandsPicker = endBiomesMap.get(endHighlands);
-				RegistryEntry<Biome> highlandsKey = highlandsPicker.pickFromNoise(sampler, x / 64.0, 0, z / 64.0);
+				// select a random highlands biome replacement, then try to replace it with a midlands or barrens biome replacement
+				RegistryEntry<Biome> highlandsReplacement = pick(endHighlands, endHighlands, endBiomesMap, x, z, noise);
+				Map<RegistryEntry<Biome>, WeightedPicker<RegistryEntry<Biome>>> map = vanillaBiome == endMidlands ? endMidlandsMap : endBarrensMap;
 
-				if (vanillaBiome == endMidlands) {
-					WeightedPicker<RegistryEntry<Biome>> midlandsPicker = endMidlandsMap.get(highlandsKey);
-					replacementKey = (midlandsPicker == null) ? vanillaBiome : midlandsPicker.pickFromNoise(sampler, x / 64.0, 0, z / 64.0);
-				} else {
-					WeightedPicker<RegistryEntry<Biome>> barrensPicker = endBarrensMap.get(highlandsKey);
-					replacementKey = (barrensPicker == null) ? vanillaBiome : barrensPicker.pickFromNoise(sampler, x / 64.0, 0, z / 64.0);
-				}
+				return pick(highlandsReplacement, vanillaBiome, map, x, z, noise);
 			} else {
-				// Since the main island and small islands pickers are statically populated by InternalBiomeData, picker will never be null.
-				WeightedPicker<RegistryEntry<Biome>> picker = endBiomesMap.get(vanillaBiome);
-				replacementKey = picker.pickFromNoise(sampler, x / 64.0, 0, z / 64.0);
+				assert END_BIOMES_MAP.containsKey(vanillaBiome.getKey().orElseThrow());
+
+				return pick(vanillaBiome, vanillaBiome, endBiomesMap, x, z, noise);
+			}
+		}
+
+		private <T> T pick(T key, T defaultValue, Map<T, WeightedPicker<T>> pickers, int x, int z, MultiNoiseUtil.MultiNoiseSampler noise) {
+			if (pickers == null) return defaultValue;
+
+			WeightedPicker<T> picker = pickers.get(key);
+			if (picker == null || picker.getEntryCount() <= 1) return defaultValue;
+
+			// The x and z of the entry are divided by 64 to ensure custom biomes are large enough; going larger than this
+			// seems to make custom biomes too hard to find.
+			return picker.pickFromNoise(getSampler(noise), x / 64.0, 0, z / 64.0);
+		}
+
+		private synchronized PerlinNoiseSampler getSampler(MultiNoiseUtil.MultiNoiseSampler noise) {
+			PerlinNoiseSampler ret = samplers.get(noise);
+
+			if (ret == null) {
+				Long seed = Overrides.seed.get();
+				if (seed == null) throw new IllegalStateException("seed isn't set, ChunkGenerator hook not working?");
+
+				ret = new PerlinNoiseSampler(new ChunkRandom(new AtomicSimpleRandom(seed)));
+				samplers.put(noise, ret);
 			}
 
-			return replacementKey;
+			return ret;
+		}
+
+		public static void setSeed(long seed) {
+			Overrides.seed.set(seed);
 		}
 	}
 }
diff --git a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/WeightedPicker.java b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/WeightedPicker.java
index f5201f3f4..dc9e40505 100644
--- a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/WeightedPicker.java
+++ b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/WeightedPicker.java
@@ -50,6 +50,10 @@ public final class WeightedPicker<T> {
 		return currentTotal;
 	}
 
+	int getEntryCount() {
+		return entries.size();
+	}
+
 	public T pickFromNoise(PerlinNoiseSampler sampler, double x, double y, double z) {
 		double target = Math.abs(sampler.sample(x, y, z)) * getCurrentWeightTotal();
 
diff --git a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BiomeModificationContextImpl.java b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BiomeModificationContextImpl.java
index 8c06b4b7a..b028606c8 100644
--- a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BiomeModificationContextImpl.java
+++ b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BiomeModificationContextImpl.java
@@ -33,8 +33,6 @@ import com.google.common.collect.ImmutableMap;
 import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
-import net.minecraft.util.registry.RegistryEntry;
-import net.minecraft.util.registry.RegistryEntryList;
 import net.minecraft.entity.EntityType;
 import net.minecraft.entity.SpawnGroup;
 import net.minecraft.sound.BiomeAdditionsSound;
@@ -44,6 +42,8 @@ import net.minecraft.sound.SoundEvent;
 import net.minecraft.util.collection.Pool;
 import net.minecraft.util.registry.DynamicRegistryManager;
 import net.minecraft.util.registry.Registry;
+import net.minecraft.util.registry.RegistryEntry;
+import net.minecraft.util.registry.RegistryEntryList;
 import net.minecraft.util.registry.RegistryKey;
 import net.minecraft.world.biome.Biome;
 import net.minecraft.world.biome.BiomeEffects;
@@ -52,9 +52,9 @@ import net.minecraft.world.biome.GenerationSettings;
 import net.minecraft.world.biome.SpawnSettings;
 import net.minecraft.world.gen.GenerationStep;
 import net.minecraft.world.gen.carver.ConfiguredCarver;
-import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
 import net.minecraft.world.gen.feature.Feature;
 import net.minecraft.world.gen.feature.PlacedFeature;
+import net.minecraft.world.gen.feature.StructureFeature;
 
 import net.fabricmc.fabric.api.biome.v1.BiomeModificationContext;
 
@@ -78,11 +78,6 @@ public class BiomeModificationContextImpl implements BiomeModificationContext {
 		this.spawnSettings = new SpawnSettingsContextImpl();
 	}
 
-	@Override
-	public void setCategory(Biome.Category category) {
-		biome.category = category;
-	}
-
 	@Override
 	public WeatherContext getWeather() {
 		return weather;
@@ -202,7 +197,7 @@ public class BiomeModificationContextImpl implements BiomeModificationContext {
 	private class GenerationSettingsContextImpl implements GenerationSettingsContext {
 		private final Registry<ConfiguredCarver<?>> carvers = registries.get(Registry.CONFIGURED_CARVER_KEY);
 		private final Registry<PlacedFeature> features = registries.get(Registry.PLACED_FEATURE_KEY);
-		private final Registry<ConfiguredStructureFeature<?, ?>> structures = registries.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY);
+		private final Registry<StructureFeature> structures = registries.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY);
 		private final GenerationSettings generationSettings = biome.getGenerationSettings();
 
 		private boolean rebuildFlowerFeatures;
diff --git a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BiomeSelectionContextImpl.java b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BiomeSelectionContextImpl.java
index ffd9462b5..fd6c6d301 100644
--- a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BiomeSelectionContextImpl.java
+++ b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BiomeSelectionContextImpl.java
@@ -28,8 +28,8 @@ import net.minecraft.util.registry.RegistryKey;
 import net.minecraft.world.biome.Biome;
 import net.minecraft.world.dimension.DimensionOptions;
 import net.minecraft.world.gen.feature.ConfiguredFeature;
-import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
 import net.minecraft.world.gen.feature.PlacedFeature;
+import net.minecraft.world.gen.feature.StructureFeature;
 import net.minecraft.world.level.LevelProperties;
 
 import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
@@ -78,20 +78,20 @@ public class BiomeSelectionContextImpl implements BiomeSelectionContext {
 	}
 
 	@Override
-	public boolean validForStructure(RegistryKey<ConfiguredStructureFeature<?, ?>> key) {
-		ConfiguredStructureFeature<?, ?> instance = dynamicRegistries.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY).get(key);
+	public boolean validForStructure(RegistryKey<StructureFeature> key) {
+		StructureFeature instance = dynamicRegistries.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY).get(key);
 
 		if (instance == null) {
 			return false;
 		}
 
-		return instance.getBiomes().contains(getBiomeRegistryEntry());
+		return instance.method_41607().contains(getBiomeRegistryEntry());
 	}
 
 	@Override
-	public Optional<RegistryKey<ConfiguredStructureFeature<?, ?>>> getStructureKey(ConfiguredStructureFeature<?, ?> configuredStructure) {
-		Registry<ConfiguredStructureFeature<?, ?>> registry = dynamicRegistries.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY);
-		return registry.getKey(configuredStructure);
+	public Optional<RegistryKey<StructureFeature>> getStructureKey(StructureFeature structureFeature) {
+		Registry<StructureFeature> registry = dynamicRegistries.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY);
+		return registry.getKey(structureFeature);
 	}
 
 	@Override
diff --git a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BuiltInRegistryKeys.java b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BuiltInRegistryKeys.java
index afe5ad0cc..73b319ccd 100644
--- a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BuiltInRegistryKeys.java
+++ b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/impl/biome/modification/BuiltInRegistryKeys.java
@@ -22,8 +22,8 @@ import net.minecraft.util.registry.BuiltinRegistries;
 import net.minecraft.util.registry.RegistryKey;
 import net.minecraft.world.gen.carver.ConfiguredCarver;
 import net.minecraft.world.gen.feature.ConfiguredFeature;
-import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
 import net.minecraft.world.gen.feature.PlacedFeature;
+import net.minecraft.world.gen.feature.StructureFeature;
 
 /**
  * Utility class for getting the registry keys of built-in worldgen objects and throwing proper exceptions if they
@@ -34,9 +34,9 @@ public final class BuiltInRegistryKeys {
 	private BuiltInRegistryKeys() {
 	}
 
-	public static RegistryKey<ConfiguredStructureFeature<?, ?>> get(ConfiguredStructureFeature<?, ?> configuredStructure) {
-		return BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE.getKey(configuredStructure)
-				.orElseThrow(() -> new IllegalArgumentException("Given configured structure is not built-in: " + configuredStructure));
+	public static RegistryKey<StructureFeature> get(StructureFeature structureFeature) {
+		return BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE.getKey(structureFeature)
+				.orElseThrow(() -> new IllegalArgumentException("Given structure is not built-in: " + structureFeature));
 	}
 
 	public static RegistryKey<ConfiguredFeature<?, ?>> get(ConfiguredFeature<?, ?> configuredFeature) {
diff --git a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/mixin/biome/MixinChunkGenerator.java b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/mixin/biome/MixinChunkGenerator.java
new file mode 100644
index 000000000..25c6214e2
--- /dev/null
+++ b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/mixin/biome/MixinChunkGenerator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.mixin.biome;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+import net.minecraft.class_7138;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraft.world.gen.chunk.ChunkGenerator;
+
+import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
+
+@Mixin(ChunkGenerator.class)
+public class MixinChunkGenerator {
+	@Inject(method = "method_38267", at = @At("HEAD"))
+	private void populateBiomes_lambda_head(Chunk chunk, class_7138 rng, CallbackInfoReturnable<Chunk> ci) {
+		// capture seed so TheEndBiomeData.Overrides has it if it needs it
+		TheEndBiomeData.Overrides.setSeed(rng.legacyLevelSeed());
+	}
+}
diff --git a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/mixin/biome/MixinTheEndBiomeSource.java b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/mixin/biome/MixinTheEndBiomeSource.java
index 54d5318be..278a4fdb1 100644
--- a/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/mixin/biome/MixinTheEndBiomeSource.java
+++ b/fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/mixin/biome/MixinTheEndBiomeSource.java
@@ -37,12 +37,12 @@ public class MixinTheEndBiomeSource {
 	private TheEndBiomeData.Overrides overrides;
 
 	@Inject(method = "<init>", at = @At("RETURN"))
-	private void init(Registry<Biome> biomeRegistry, long seed, CallbackInfo ci) {
-		overrides = TheEndBiomeData.createOverrides(biomeRegistry, seed);
+	private void init(Registry<Biome> biomeRegistry, CallbackInfo ci) {
+		overrides = TheEndBiomeData.createOverrides(biomeRegistry);
 	}
 
 	@Inject(method = "getBiome", at = @At("RETURN"), cancellable = true)
-	private void getWeightedEndBiome(int biomeX, int biomeY, int biomeZ, MultiNoiseUtil.MultiNoiseSampler multiNoiseSampler, CallbackInfoReturnable<RegistryEntry<Biome>> cir) {
-		cir.setReturnValue(overrides.pick(biomeX, biomeY, biomeZ, cir.getReturnValue()));
+	private void getWeightedEndBiome(int biomeX, int biomeY, int biomeZ, MultiNoiseUtil.MultiNoiseSampler noise, CallbackInfoReturnable<RegistryEntry<Biome>> cir) {
+		cir.setReturnValue(overrides.pick(biomeX, biomeY, biomeZ, noise, cir.getReturnValue()));
 	}
 }
diff --git a/fabric-biome-api-v1/src/main/resources/fabric-biome-api-v1.accesswidener b/fabric-biome-api-v1/src/main/resources/fabric-biome-api-v1.accesswidener
index 869660a35..16763b14c 100644
--- a/fabric-biome-api-v1/src/main/resources/fabric-biome-api-v1.accesswidener
+++ b/fabric-biome-api-v1/src/main/resources/fabric-biome-api-v1.accesswidener
@@ -11,8 +11,6 @@ mutable field net/minecraft/world/biome/source/BiomeSource indexedFeaturesSuppli
 accessible field net/minecraft/world/biome/Biome weather Lnet/minecraft/world/biome/Biome$Weather;
 accessible field net/minecraft/world/biome/Biome generationSettings Lnet/minecraft/world/biome/GenerationSettings;
 accessible field net/minecraft/world/biome/Biome spawnSettings Lnet/minecraft/world/biome/SpawnSettings;
-accessible field net/minecraft/world/biome/Biome category Lnet/minecraft/world/biome/Biome$Category;
-mutable field net/minecraft/world/biome/Biome category Lnet/minecraft/world/biome/Biome$Category;
 
 # Biome Weather
 accessible field net/minecraft/world/biome/Biome$Weather precipitation Lnet/minecraft/world/biome/Biome$Precipitation;
diff --git a/fabric-biome-api-v1/src/main/resources/fabric-biome-api-v1.mixins.json b/fabric-biome-api-v1/src/main/resources/fabric-biome-api-v1.mixins.json
index 069825b79..d6385c66f 100644
--- a/fabric-biome-api-v1/src/main/resources/fabric-biome-api-v1.mixins.json
+++ b/fabric-biome-api-v1/src/main/resources/fabric-biome-api-v1.mixins.json
@@ -5,6 +5,7 @@
   "mixins": [
     "modification.DynamicRegistryManagerImplMixin",
     "modification.MinecraftServerMixin",
+    "MixinChunkGenerator",
     "MixinMultiNoiseBiomeSource",
     "MixinTheEndBiomeSource"
   ],
diff --git a/fabric-biome-api-v1/src/testmod/java/net/fabricmc/fabric/test/biome/FabricBiomeTest.java b/fabric-biome-api-v1/src/testmod/java/net/fabricmc/fabric/test/biome/FabricBiomeTest.java
index b1f3f3879..626b5f22d 100644
--- a/fabric-biome-api-v1/src/testmod/java/net/fabricmc/fabric/test/biome/FabricBiomeTest.java
+++ b/fabric-biome-api-v1/src/testmod/java/net/fabricmc/fabric/test/biome/FabricBiomeTest.java
@@ -102,7 +102,7 @@ public class FabricBiomeTest implements ModInitializer {
 						BiomeSelectors.foundInOverworld(),
 						modification -> modification.getWeather().setDownfall(100))
 				.add(ModificationPhase.ADDITIONS,
-						BiomeSelectors.categories(Biome.Category.DESERT),
+						BiomeSelectors.includeByKey(BiomeKeys.DESERT), // TODO: switch to fabric desert biome tag once it is there?
 						context -> {
 							context.getGenerationSettings().addFeature(GenerationStep.Feature.TOP_LAYER_MODIFICATION,
 									BuiltinRegistries.PLACED_FEATURE.getKey(PLACED_COMMON_DESERT_WELL).orElseThrow()
@@ -134,6 +134,6 @@ public class FabricBiomeTest implements ModInitializer {
 	private static Biome composeEndSpawnSettings(GenerationSettings.Builder builder) {
 		SpawnSettings.Builder builder2 = new SpawnSettings.Builder();
 		DefaultBiomeFeatures.addEndMobs(builder2);
-		return (new Biome.Builder()).precipitation(Biome.Precipitation.NONE).category(Biome.Category.THEEND).temperature(0.5F).downfall(0.5F).effects((new BiomeEffects.Builder()).waterColor(4159204).waterFogColor(329011).fogColor(10518688).skyColor(0).moodSound(BiomeMoodSound.CAVE).build()).spawnSettings(builder2.build()).generationSettings(builder.build()).build();
+		return (new Biome.Builder()).precipitation(Biome.Precipitation.NONE).temperature(0.5F).downfall(0.5F).effects((new BiomeEffects.Builder()).waterColor(4159204).waterFogColor(329011).fogColor(10518688).skyColor(0).moodSound(BiomeMoodSound.CAVE).build()).spawnSettings(builder2.build()).generationSettings(builder.build()).build();
 	}
 }
diff --git a/fabric-command-api-v1/src/main/java/net/fabricmc/fabric/mixin/command/CommandManagerMixin.java b/fabric-command-api-v1/src/main/java/net/fabricmc/fabric/mixin/command/CommandManagerMixin.java
index 182aaefdb..f85a03837 100644
--- a/fabric-command-api-v1/src/main/java/net/fabricmc/fabric/mixin/command/CommandManagerMixin.java
+++ b/fabric-command-api-v1/src/main/java/net/fabricmc/fabric/mixin/command/CommandManagerMixin.java
@@ -24,6 +24,7 @@ import org.spongepowered.asm.mixin.injection.At;
 import org.spongepowered.asm.mixin.injection.Inject;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
 
+import net.minecraft.class_7157;
 import net.minecraft.server.command.CommandManager;
 import net.minecraft.server.command.ServerCommandSource;
 
@@ -42,8 +43,8 @@ public abstract class CommandManagerMixin {
 	 *
 	 * @reason Add commands before ambiguities are calculated.
 	 */
-	@Inject(at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/CommandDispatcher;findAmbiguities(Lcom/mojang/brigadier/AmbiguityConsumer;)V"), method = "<init>")
-	private void fabric_addCommands(CommandManager.RegistrationEnvironment environment, CallbackInfo ci) {
+	@Inject(at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/CommandDispatcher;setConsumer(Lcom/mojang/brigadier/ResultConsumer;)V"), method = "<init>")
+	private void fabric_addCommands(CommandManager.RegistrationEnvironment environment, class_7157 arg, CallbackInfo ci) {
 		CommandRegistrationCallback.EVENT.invoker().register(this.dispatcher, environment == CommandManager.RegistrationEnvironment.DEDICATED);
 	}
 }
diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricTagProvider.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricTagProvider.java
index e10c3aebc..70b3d98a0 100644
--- a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricTagProvider.java
+++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricTagProvider.java
@@ -65,7 +65,6 @@ import net.fabricmc.fabric.mixin.datagen.DynamicRegistryManagerAccessor;
 public abstract class FabricTagProvider<T> extends AbstractTagProvider<T> {
 	private final FabricDataGenerator fabricDataGenerator;
 	private final String path;
-	private final String name;
 
 	/**
 	 * Construct a new {@link FabricTagProvider} with the default computed path.
@@ -76,8 +75,8 @@ public abstract class FabricTagProvider<T> extends AbstractTagProvider<T> {
 	 * @param registry The backing registry for the Tag type.
 	 * @param name The name used for {@link DataProvider#getName()}
 	 */
-	protected FabricTagProvider(FabricDataGenerator dataGenerator, Registry<T> registry, String name) {
-		this(dataGenerator, registry, TagManagerLoader.getPath(registry.getKey()), name);
+	protected FabricTagProvider(FabricDataGenerator dataGenerator, Registry<T> registry) {
+		this(dataGenerator, registry, TagManagerLoader.getPath(registry.getKey()));
 	}
 
 	/**
@@ -88,14 +87,12 @@ public abstract class FabricTagProvider<T> extends AbstractTagProvider<T> {
 	 * @param dataGenerator The data generator instance
 	 * @param registry The backing registry for the Tag type.
 	 * @param path The directory name to write the tag file names. Example: "blocks" or "items"
-	 * @param name The name used for {@link DataProvider#getName()}
 	 */
 	@SuppressWarnings({"unchecked", "rawtypes"})
-	protected FabricTagProvider(FabricDataGenerator dataGenerator, Registry<T> registry, String path, String name) {
+	protected FabricTagProvider(FabricDataGenerator dataGenerator, Registry<T> registry, String path) {
 		super(dataGenerator, registry);
 		this.fabricDataGenerator = dataGenerator;
 		this.path = path.startsWith("tags/") ? path : "tags/" + path;
-		this.name = name;
 
 		if (!(this instanceof DynamicRegistryTagProvider) && BuiltinRegistries.REGISTRIES.contains((RegistryKey) registry.getKey())) {
 			throw new IllegalArgumentException("Using FabricTagProvider to generate dynamic registry tags is not supported, Use DynamicRegistryTagProvider instead.");
@@ -128,11 +125,6 @@ public abstract class FabricTagProvider<T> extends AbstractTagProvider<T> {
 		generateTags();
 	}
 
-	@Override
-	public String getName() {
-		return name;
-	}
-
 	/**
 	 * Extend this class to create {@link Block} tags in the "/blocks" tag directory.
 	 */
@@ -226,8 +218,8 @@ public abstract class FabricTagProvider<T> extends AbstractTagProvider<T> {
 		 * @param name The name used for {@link DataProvider#getName()}
 		 * @throws IllegalArgumentException if the registry is static registry
 		 */
-		protected DynamicRegistryTagProvider(FabricDataGenerator dataGenerator, RegistryKey<? extends Registry<T>> registryKey, String path, String name) {
-			super(dataGenerator, FabricDataGenHelper.getFakeDynamicRegistry(), path, name);
+		protected DynamicRegistryTagProvider(FabricDataGenerator dataGenerator, RegistryKey<? extends Registry<T>> registryKey, String path) {
+			super(dataGenerator, FabricDataGenHelper.getFakeDynamicRegistry(), path);
 			Preconditions.checkArgument(DynamicRegistryManagerAccessor.getInfos().containsKey(registryKey), "Only dynamic registries are supported in this tag provider.");
 		}
 	}
diff --git a/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.accesswidener b/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.accesswidener
index 74552bf58..4b347f451 100644
--- a/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.accesswidener
+++ b/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.accesswidener
@@ -88,6 +88,7 @@ transitive-accessible	method	net/minecraft/data/server/RecipeProvider	convertBet
 transitive-accessible	method	net/minecraft/data/server/RecipeProvider	getSmeltingItemPath	(Lnet/minecraft/item/ItemConvertible;)Ljava/lang/String;
 transitive-accessible	method	net/minecraft/data/server/RecipeProvider	getBlastingItemPath	(Lnet/minecraft/item/ItemConvertible;)Ljava/lang/String;
 transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	createStoneState	(Lnet/minecraft/block/Block;Lnet/minecraft/util/Identifier;Lnet/minecraft/data/client/TextureMap;Ljava/util/function/BiConsumer;)Lnet/minecraft/data/client/BlockStateSupplier;
+transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	method_42039	(Lnet/minecraft/block/Block;Lnet/minecraft/util/Identifier;Lnet/minecraft/data/client/TextureMap;Ljava/util/function/BiConsumer;)Lnet/minecraft/data/client/BlockStateSupplier;
 transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	createDeepslateState	(Lnet/minecraft/block/Block;Lnet/minecraft/util/Identifier;Lnet/minecraft/data/client/TextureMap;Ljava/util/function/BiConsumer;)Lnet/minecraft/data/client/BlockStateSupplier;
 transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	excludeFromSimpleItemModelGeneration	(Lnet/minecraft/block/Block;)V
 transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	registerParentedItemModel	(Lnet/minecraft/block/Block;Lnet/minecraft/util/Identifier;)V
@@ -106,8 +107,8 @@ transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator
 transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	registerMirrorable	(Lnet/minecraft/block/Block;)V
 transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	registerRotatable	(Lnet/minecraft/block/Block;)V
 transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	createButtonBlockState	(Lnet/minecraft/block/Block;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)Lnet/minecraft/data/client/BlockStateSupplier;
-transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	fillDoorVariantMap	(Lnet/minecraft/data/client/BlockStateVariantMap$QuadrupleProperty;Lnet/minecraft/block/enums/DoubleBlockHalf;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)Lnet/minecraft/data/client/BlockStateVariantMap$QuadrupleProperty;
-transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	createDoorBlockState	(Lnet/minecraft/block/Block;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)Lnet/minecraft/data/client/BlockStateSupplier;
+transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	fillDoorVariantMap	(Lnet/minecraft/data/client/BlockStateVariantMap$QuadrupleProperty;Lnet/minecraft/block/enums/DoubleBlockHalf;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)Lnet/minecraft/data/client/BlockStateVariantMap$QuadrupleProperty;
+transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	createDoorBlockState	(Lnet/minecraft/block/Block;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)Lnet/minecraft/data/client/BlockStateSupplier;
 transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	createFenceBlockState	(Lnet/minecraft/block/Block;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)Lnet/minecraft/data/client/BlockStateSupplier;
 transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	createWallBlockState	(Lnet/minecraft/block/Block;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)Lnet/minecraft/data/client/BlockStateSupplier;
 transitive-accessible	method	net/minecraft/data/client/BlockStateModelGenerator	createFenceGateBlockState	(Lnet/minecraft/block/Block;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)Lnet/minecraft/data/client/BlockStateSupplier;
diff --git a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java
index afa2165c7..597257e35 100644
--- a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java
+++ b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java
@@ -87,7 +87,7 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
 		}
 
 		try {
-			new FabricTagProvider.DynamicRegistryTagProvider<>(dataGenerator, Registry.ITEM_KEY, "items", "Item Tags") {
+			new FabricTagProvider.DynamicRegistryTagProvider<>(dataGenerator, Registry.ITEM_KEY, "items") {
 				@Override
 				protected void generateTags() {
 				}
@@ -164,7 +164,7 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
 
 	private static class TestBiomeTagProvider extends FabricTagProvider.DynamicRegistryTagProvider<Biome> {
 		private TestBiomeTagProvider(FabricDataGenerator dataGenerator) {
-			super(dataGenerator, Registry.BIOME_KEY, "biomes", "Biome Tags");
+			super(dataGenerator, Registry.BIOME_KEY, "biomes");
 		}
 
 		@Override
diff --git a/fabric-dimensions-v1/src/testmod/java/net/fabricmc/fabric/test/dimension/VoidChunkGenerator.java b/fabric-dimensions-v1/src/testmod/java/net/fabricmc/fabric/test/dimension/VoidChunkGenerator.java
index dd32dcc22..095913511 100644
--- a/fabric-dimensions-v1/src/testmod/java/net/fabricmc/fabric/test/dimension/VoidChunkGenerator.java
+++ b/fabric-dimensions-v1/src/testmod/java/net/fabricmc/fabric/test/dimension/VoidChunkGenerator.java
@@ -24,6 +24,7 @@ import java.util.concurrent.Executor;
 import com.mojang.serialization.Codec;
 import com.mojang.serialization.codecs.RecordCodecBuilder;
 
+import net.minecraft.class_7138;
 import net.minecraft.block.BlockState;
 import net.minecraft.structure.StructureSet;
 import net.minecraft.util.dynamic.RegistryOps;
@@ -36,7 +37,6 @@ import net.minecraft.world.biome.Biome;
 import net.minecraft.world.biome.BiomeKeys;
 import net.minecraft.world.biome.source.BiomeAccess;
 import net.minecraft.world.biome.source.FixedBiomeSource;
-import net.minecraft.world.biome.source.util.MultiNoiseUtil;
 import net.minecraft.world.chunk.Chunk;
 import net.minecraft.world.gen.GenerationStep;
 import net.minecraft.world.gen.StructureAccessor;
@@ -46,11 +46,8 @@ import net.minecraft.world.gen.chunk.VerticalBlockSample;
 
 public class VoidChunkGenerator extends ChunkGenerator {
 	public static final Codec<VoidChunkGenerator> CODEC = RecordCodecBuilder.create((instance) ->
-			method_41042(instance).and(
-				RegistryOps.createRegistryCodec(Registry.BIOME_KEY).forGetter((generator) -> generator.biomeRegistry)
-			)
-			.apply(instance, instance.stable(VoidChunkGenerator::new))
-	);
+			method_41042(instance).and(RegistryOps.createRegistryCodec(Registry.BIOME_KEY).forGetter((generator) -> generator.biomeRegistry))
+					.apply(instance, instance.stable(VoidChunkGenerator::new)));
 
 	private final Registry<Biome> biomeRegistry;
 
@@ -65,22 +62,11 @@ public class VoidChunkGenerator extends ChunkGenerator {
 	}
 
 	@Override
-	public ChunkGenerator withSeed(long seed) {
-		return this;
+	public void carve(ChunkRegion chunkRegion, long l, class_7138 rng, BiomeAccess biomeAccess, StructureAccessor structureAccessor, Chunk chunk, GenerationStep.Carver carver) {
 	}
 
 	@Override
-	public MultiNoiseUtil.MultiNoiseSampler getMultiNoiseSampler() {
-		// Mirror what Vanilla does in the debug chunk generator
-		return MultiNoiseUtil.method_40443();
-	}
-
-	@Override
-	public void carve(ChunkRegion chunkRegion, long l, BiomeAccess biomeAccess, StructureAccessor structureAccessor, Chunk chunk, GenerationStep.Carver carver) {
-	}
-
-	@Override
-	public void buildSurface(ChunkRegion region, StructureAccessor structureAccessor, Chunk chunk) {
+	public void buildSurface(ChunkRegion region, StructureAccessor structureAccessor, class_7138 rng, Chunk chunk) {
 	}
 
 	@Override
@@ -93,7 +79,7 @@ public class VoidChunkGenerator extends ChunkGenerator {
 	}
 
 	@Override
-	public CompletableFuture<Chunk> populateNoise(Executor executor, Blender blender, StructureAccessor structureAccessor, Chunk chunk) {
+	public CompletableFuture<Chunk> populateNoise(Executor executor, Blender blender, class_7138 rng, StructureAccessor structureAccessor, Chunk chunk) {
 		return CompletableFuture.completedFuture(chunk);
 	}
 
@@ -108,16 +94,16 @@ public class VoidChunkGenerator extends ChunkGenerator {
 	}
 
 	@Override
-	public int getHeight(int x, int z, Heightmap.Type heightmapType, HeightLimitView heightLimitView) {
+	public int getHeight(int x, int z, Heightmap.Type heightmapType, HeightLimitView heightLimitView, class_7138 rng) {
 		return 0;
 	}
 
 	@Override
-	public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView heightLimitView) {
+	public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView heightLimitView, class_7138 rng) {
 		return new VerticalBlockSample(0, new BlockState[0]);
 	}
 
 	@Override
-	public void getDebugHudText(List<String> list, BlockPos blockPos) {
+	public void getDebugHudText(List<String> list, class_7138 rng, BlockPos blockPos) {
 	}
 }
diff --git a/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/mixin/event/interaction/MixinClientPlayerInteractionManager.java b/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/mixin/event/interaction/MixinClientPlayerInteractionManager.java
index 81be1a688..a046d59c8 100644
--- a/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/mixin/event/interaction/MixinClientPlayerInteractionManager.java
+++ b/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/mixin/event/interaction/MixinClientPlayerInteractionManager.java
@@ -23,6 +23,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
 
+import net.minecraft.class_7204;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.network.ClientPlayNetworkHandler;
 import net.minecraft.client.network.ClientPlayerEntity;
@@ -35,6 +36,7 @@ import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
 import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket;
 import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket;
 import net.minecraft.network.packet.c2s.play.PlayerInteractItemC2SPacket;
+import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
 import net.minecraft.util.ActionResult;
 import net.minecraft.util.Hand;
 import net.minecraft.util.TypedActionResult;
@@ -44,7 +46,6 @@ import net.minecraft.util.math.BlockPos;
 import net.minecraft.util.math.Direction;
 import net.minecraft.util.math.Vec3d;
 import net.minecraft.world.GameMode;
-import net.minecraft.world.World;
 
 import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
 import net.fabricmc.fabric.api.event.player.AttackEntityCallback;
@@ -61,9 +62,6 @@ public abstract class MixinClientPlayerInteractionManager {
 	@Shadow
 	private GameMode gameMode;
 
-	@Shadow
-	protected abstract void sendPlayerAction(PlayerActionC2SPacket.Action action, BlockPos pos, Direction direction);
-
 	@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/world/GameMode;isCreative()Z", ordinal = 0), method = "attackBlock", cancellable = true)
 	public void attackBlock(BlockPos pos, Direction direction, CallbackInfoReturnable<Boolean> info) {
 		ActionResult result = AttackBlockCallback.EVENT.invoker().interact(client.player, client.world, Hand.MAIN_HAND, pos, direction);
@@ -74,7 +72,7 @@ public abstract class MixinClientPlayerInteractionManager {
 
 			// We also need to let the server process the action if it's accepted.
 			if (result.isAccepted()) {
-				this.sendPlayerAction(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, pos, direction);
+				method_41931(client.world, id -> new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, pos, direction, id));
 			}
 		}
 	}
@@ -93,13 +91,19 @@ public abstract class MixinClientPlayerInteractionManager {
 		}
 	}
 
-	@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getStackInHand(Lnet/minecraft/util/Hand;)Lnet/minecraft/item/ItemStack;", ordinal = 0), method = "interactBlock", cancellable = true)
-	public void interactBlock(ClientPlayerEntity player, ClientWorld world, Hand hand, BlockHitResult blockHitResult, CallbackInfoReturnable<ActionResult> info) {
-		ActionResult result = UseBlockCallback.EVENT.invoker().interact(player, world, hand, blockHitResult);
+	@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;method_41931(Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/class_7204;)V"), method = "interactBlock", cancellable = true)
+	public void interactBlock(ClientPlayerEntity player, Hand hand, BlockHitResult blockHitResult, CallbackInfoReturnable<ActionResult> info) {
+		// hook interactBlock between the world border check and the actual block interaction to invoke the use block event first
+		// this needs to be in interactBlock to avoid sending a packet in line with the event javadoc
+
+		if (player.isSpectator()) return; // vanilla spectator check happens later, repeat it before the event to avoid false invocations
+
+		ActionResult result = UseBlockCallback.EVENT.invoker().interact(player, player.world, hand, blockHitResult);
 
 		if (result != ActionResult.PASS) {
 			if (result == ActionResult.SUCCESS) {
-				this.networkHandler.sendPacket(new PlayerInteractBlockC2SPacket(hand, blockHitResult));
+				// send interaction packet to the server with a new sequentially assigned id
+				method_41931(player.clientWorld, id -> new PlayerInteractBlockC2SPacket(hand, blockHitResult, id));
 			}
 
 			info.setReturnValue(result);
@@ -107,12 +111,17 @@ public abstract class MixinClientPlayerInteractionManager {
 	}
 
 	@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V", ordinal = 0), method = "interactItem", cancellable = true)
-	public void interactItem(PlayerEntity player, World world, Hand hand, CallbackInfoReturnable<ActionResult> info) {
-		TypedActionResult<ItemStack> result = UseItemCallback.EVENT.invoker().interact(player, world, hand);
+	public void interactItem(PlayerEntity player, Hand hand, CallbackInfoReturnable<ActionResult> info) {
+		// hook interactBlock between the spectator check and sending the first packet to invoke the use item event first
+		// this needs to be in interactBlock to avoid sending a packet in line with the event javadoc
+		TypedActionResult<ItemStack> result = UseItemCallback.EVENT.invoker().interact(player, player.world, hand);
 
 		if (result.getResult() != ActionResult.PASS) {
 			if (result.getResult() == ActionResult.SUCCESS) {
-				this.networkHandler.sendPacket(new PlayerInteractItemC2SPacket(hand));
+				// send the move packet like vanilla to ensure the position+view vectors are accurate
+				networkHandler.sendPacket(new PlayerMoveC2SPacket.Full(player.getX(), player.getY(), player.getZ(), player.getYaw(), player.getPitch(), player.isOnGround()));
+				// send interaction packet to the server with a new sequentially assigned id
+				method_41931((ClientWorld) player.world, id -> new PlayerInteractItemC2SPacket(hand, id));
 			}
 
 			info.setReturnValue(result.getResult());
@@ -145,4 +154,7 @@ public abstract class MixinClientPlayerInteractionManager {
 			info.setReturnValue(result);
 		}
 	}
+
+	@Shadow
+	public abstract void method_41931(ClientWorld clientWorld, class_7204 supplier);
 }
diff --git a/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/mixin/event/interaction/MixinServerPlayerInteractionManager.java b/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/mixin/event/interaction/MixinServerPlayerInteractionManager.java
index 49fecfa0d..efa27fe4a 100644
--- a/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/mixin/event/interaction/MixinServerPlayerInteractionManager.java
+++ b/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/mixin/event/interaction/MixinServerPlayerInteractionManager.java
@@ -27,13 +27,13 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
 import net.minecraft.block.Block;
 import net.minecraft.block.BlockState;
 import net.minecraft.block.entity.BlockEntity;
+import net.minecraft.item.ItemStack;
 import net.minecraft.network.Packet;
 import net.minecraft.network.listener.ClientPlayPacketListener;
+import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
 import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
-import net.minecraft.item.ItemStack;
 import net.minecraft.server.network.ServerPlayerEntity;
 import net.minecraft.server.network.ServerPlayerInteractionManager;
-import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
 import net.minecraft.server.world.ServerWorld;
 import net.minecraft.util.ActionResult;
 import net.minecraft.util.Hand;
@@ -44,9 +44,9 @@ import net.minecraft.util.math.Direction;
 import net.minecraft.world.World;
 
 import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
+import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
 import net.fabricmc.fabric.api.event.player.UseBlockCallback;
 import net.fabricmc.fabric.api.event.player.UseItemCallback;
-import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
 
 @Mixin(ServerPlayerInteractionManager.class)
 public class MixinServerPlayerInteractionManager {
@@ -56,7 +56,7 @@ public class MixinServerPlayerInteractionManager {
 	public ServerPlayerEntity player;
 
 	@Inject(at = @At("HEAD"), method = "processBlockBreakingAction", cancellable = true)
-	public void startBlockBreak(BlockPos pos, PlayerActionC2SPacket.Action playerAction, Direction direction, int i, CallbackInfo info) {
+	public void startBlockBreak(BlockPos pos, PlayerActionC2SPacket.Action playerAction, Direction direction, int worldHeight, int i, CallbackInfo info) {
 		if (playerAction != PlayerActionC2SPacket.Action.START_DESTROY_BLOCK) return;
 		ActionResult result = AttackBlockCallback.EVENT.invoker().interact(player, world, Hand.MAIN_HAND, pos, direction);
 
diff --git a/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/ArgumentTypesMixin.java b/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/ArgumentTypesMixin.java
index 451fdefd2..da951bcc9 100644
--- a/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/ArgumentTypesMixin.java
+++ b/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/ArgumentTypesMixin.java
@@ -21,7 +21,7 @@ import org.spongepowered.asm.mixin.Mixin;
 import org.spongepowered.asm.mixin.Shadow;
 import org.spongepowered.asm.mixin.injection.At;
 import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
 
 import net.minecraft.SharedConstants;
 import net.minecraft.command.argument.ArgumentTypes;
@@ -29,20 +29,21 @@ import net.minecraft.command.argument.TestClassArgumentType;
 import net.minecraft.command.argument.TestFunctionArgumentType;
 import net.minecraft.command.argument.serialize.ArgumentSerializer;
 import net.minecraft.command.argument.serialize.ConstantArgumentSerializer;
+import net.minecraft.util.registry.Registry;
 
 @Mixin(ArgumentTypes.class)
 public abstract class ArgumentTypesMixin {
 	@Shadow
-	public static <T extends ArgumentType<?>> void register(String id, Class<T> argClass, ArgumentSerializer<T> serializer) {
+	private static <A extends ArgumentType<?>, T extends ArgumentSerializer.class_7217<A>> ArgumentSerializer<A, T> register(Registry<ArgumentSerializer<?, ?>> registry, String string, Class<? extends A> clazz, ArgumentSerializer<A, T> argumentSerializer) {
 		throw new AssertionError("Nope.");
 	}
 
-	@Inject(method = "register()V", at = @At("RETURN"))
-	private static void register(CallbackInfo ci) {
+	@Inject(method = "register(Lnet/minecraft/util/registry/Registry;)Lnet/minecraft/command/argument/serialize/ArgumentSerializer;", at = @At("RETURN"))
+	private static void register(Registry<ArgumentSerializer<?, ?>> registry, CallbackInfoReturnable<ArgumentSerializer<?, ?>> ci) {
 		// Registered by vanilla when isDevelopment is enabled.
 		if (!SharedConstants.isDevelopment) {
-			register("test_argument", TestFunctionArgumentType.class, new ConstantArgumentSerializer<>(TestFunctionArgumentType::testFunction));
-			register("test_class", TestClassArgumentType.class, new ConstantArgumentSerializer<>(TestClassArgumentType::testClass));
+			register(registry, "test_argument", TestFunctionArgumentType.class, ConstantArgumentSerializer.method_41999(TestFunctionArgumentType::testFunction));
+			register(registry, "test_class", TestClassArgumentType.class, ConstantArgumentSerializer.method_41999(TestClassArgumentType::testClass));
 		}
 	}
 }
diff --git a/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/CommandManagerMixin.java b/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/CommandManagerMixin.java
index f6c802e46..87b29a67f 100644
--- a/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/CommandManagerMixin.java
+++ b/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/CommandManagerMixin.java
@@ -16,15 +16,16 @@
 
 package net.fabricmc.fabric.mixin.gametest;
 
+import com.mojang.brigadier.CommandDispatcher;
 import org.spongepowered.asm.mixin.Final;
 import org.spongepowered.asm.mixin.Mixin;
 import org.spongepowered.asm.mixin.Shadow;
 import org.spongepowered.asm.mixin.injection.At;
 import org.spongepowered.asm.mixin.injection.Inject;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-import com.mojang.brigadier.CommandDispatcher;
 
 import net.minecraft.SharedConstants;
+import net.minecraft.class_7157;
 import net.minecraft.server.command.CommandManager;
 import net.minecraft.server.command.ServerCommandSource;
 import net.minecraft.server.command.TestCommand;
@@ -36,7 +37,7 @@ public abstract class CommandManagerMixin {
 	private CommandDispatcher<ServerCommandSource> dispatcher;
 
 	@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/command/WorldBorderCommand;register(Lcom/mojang/brigadier/CommandDispatcher;)V", shift = At.Shift.AFTER))
-	private void construct(CommandManager.RegistrationEnvironment environment, CallbackInfo info) {
+	private void construct(CommandManager.RegistrationEnvironment environment, class_7157 arg, CallbackInfo info) {
 		// Registered by vanilla when isDevelopment is enabled.
 		if (!SharedConstants.isDevelopment) {
 			TestCommand.register(this.dispatcher);
diff --git a/fabric-mining-level-api-v1/src/main/java/net/fabricmc/fabric/impl/mininglevel/MiningLevelManagerImpl.java b/fabric-mining-level-api-v1/src/main/java/net/fabricmc/fabric/impl/mininglevel/MiningLevelManagerImpl.java
index a4865ca82..83971ec61 100644
--- a/fabric-mining-level-api-v1/src/main/java/net/fabricmc/fabric/impl/mininglevel/MiningLevelManagerImpl.java
+++ b/fabric-mining-level-api-v1/src/main/java/net/fabricmc/fabric/impl/mininglevel/MiningLevelManagerImpl.java
@@ -26,8 +26,8 @@ import org.slf4j.LoggerFactory;
 
 import net.minecraft.block.Block;
 import net.minecraft.block.BlockState;
-import net.minecraft.tag.TagKey;
 import net.minecraft.tag.BlockTags;
+import net.minecraft.tag.TagKey;
 
 import net.fabricmc.yarn.constants.MiningLevels;
 
@@ -42,7 +42,7 @@ public final class MiningLevelManagerImpl {
 	private static final ThreadLocal<Reference2IntMap<BlockState>> CACHE = ThreadLocal.withInitial(Reference2IntOpenHashMap::new);
 
 	public static int getRequiredMiningLevel(BlockState state) {
-		return CACHE.get().computeIntIfAbsent(state, s -> {
+		return CACHE.get().computeIfAbsent(state, s -> {
 			int miningLevel = MiningLevels.HAND;
 
 			// Handle #fabric:needs_tool_level_N
diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/GroupResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/GroupResourcePack.java
index bfb449b2c..915fc460a 100644
--- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/GroupResourcePack.java
+++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/GroupResourcePack.java
@@ -75,7 +75,7 @@ public abstract class GroupResourcePack implements ResourcePack {
 	}
 
 	@Override
-	public Collection<Identifier> findResources(ResourceType type, String namespace, String prefix, int maxDepth, Predicate<String> pathFilter) {
+	public Collection<Identifier> findResources(ResourceType type, String namespace, String prefix, Predicate<Identifier> predicate) {
 		List<ModResourcePack> packs = this.namespacedPacks.get(namespace);
 
 		if (packs == null) {
@@ -86,7 +86,7 @@ public abstract class GroupResourcePack implements ResourcePack {
 
 		for (int i = packs.size() - 1; i >= 0; i--) {
 			ResourcePack pack = packs.get(i);
-			Collection<Identifier> modResources = pack.findResources(type, namespace, prefix, maxDepth, pathFilter);
+			Collection<Identifier> modResources = pack.findResources(type, namespace, prefix, predicate);
 
 			resources.addAll(modResources);
 		}
diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModNioResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModNioResourcePack.java
index 321a782f1..ab4ac768b 100644
--- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModNioResourcePack.java
+++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ModNioResourcePack.java
@@ -36,8 +36,8 @@ import java.util.Set;
 import java.util.function.Predicate;
 import java.util.regex.Pattern;
 
-import org.slf4j.LoggerFactory;
 import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import net.minecraft.resource.AbstractFileResourcePack;
 import net.minecraft.resource.ResourceType;
@@ -209,7 +209,7 @@ public class ModNioResourcePack extends AbstractFileResourcePack implements ModR
 	}
 
 	@Override
-	public Collection<Identifier> findResources(ResourceType type, String namespace, String path, int depth, Predicate<String> predicate) {
+	public Collection<Identifier> findResources(ResourceType type, String namespace, String path, Predicate<Identifier> predicate) {
 		if (!namespaces.getOrDefault(type, Collections.emptySet()).contains(namespace)) {
 			return Collections.emptyList();
 		}
@@ -227,14 +227,13 @@ public class ModNioResourcePack extends AbstractFileResourcePack implements ModR
 					@Override
 					public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
 						String fileName = file.getFileName().toString();
+						if (fileName.endsWith(".mcmeta")) return FileVisitResult.CONTINUE;
 
-						if (!fileName.endsWith(".mcmeta")
-								&& predicate.test(fileName)) {
-							try {
-								ids.add(new Identifier(namespace, nsPath.relativize(file).toString().replace(separator, "/")));
-							} catch (InvalidIdentifierException e) {
-								LOGGER.error(e.getMessage());
-							}
+						try {
+							Identifier id = new Identifier(namespace, nsPath.relativize(file).toString().replace(separator, "/"));
+							if (predicate.test(id)) ids.add(id);
+						} catch (InvalidIdentifierException e) {
+							LOGGER.error(e.getMessage());
 						}
 
 						return FileVisitResult.CONTINUE;
diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/client/pack/ProgrammerArtResourcePack.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/client/pack/ProgrammerArtResourcePack.java
index fe701a5a5..e28da3a00 100644
--- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/client/pack/ProgrammerArtResourcePack.java
+++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/client/pack/ProgrammerArtResourcePack.java
@@ -71,10 +71,10 @@ public class ProgrammerArtResourcePack extends GroupResourcePack {
 	}
 
 	@Override
-	public Collection<Identifier> findResources(ResourceType type, String namespace, String prefix, int maxDepth, Predicate<String> pathFilter) {
-		Set<Identifier> resources = new HashSet<>(this.originalResourcePack.findResources(type, namespace, prefix, maxDepth, pathFilter));
+	public Collection<Identifier> findResources(ResourceType type, String namespace, String prefix, Predicate<Identifier> predicate) {
+		Set<Identifier> resources = new HashSet<>(this.originalResourcePack.findResources(type, namespace, prefix, predicate));
 
-		resources.addAll(super.findResources(type, namespace, prefix, maxDepth, pathFilter));
+		resources.addAll(super.findResources(type, namespace, prefix, predicate));
 
 		return resources;
 	}
diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DefaultResourcePackMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DefaultResourcePackMixin.java
index 58e96eb49..59d12cad6 100644
--- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DefaultResourcePackMixin.java
+++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/DefaultResourcePackMixin.java
@@ -83,8 +83,8 @@ public abstract class DefaultResourcePackMixin {
 	 * @reason Gets rid of classpath scanning.
 	 */
 	@Overwrite
-	public Collection<Identifier> findResources(ResourceType type, String namespace, String prefix, int maxDepth, Predicate<String> pathFilter) {
-		return fabric_mcJarPack.findResources(type, namespace, prefix, maxDepth, pathFilter);
+	public Collection<Identifier> findResources(ResourceType type, String namespace, String prefix, Predicate<Identifier> predicate) {
+		return fabric_mcJarPack.findResources(type, namespace, prefix, predicate);
 	}
 
 	/**
diff --git a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/client/CreateWorldScreenMixin.java b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/client/CreateWorldScreenMixin.java
index 408b7b09b..ab9a78f94 100644
--- a/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/client/CreateWorldScreenMixin.java
+++ b/fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/mixin/resource/loader/client/CreateWorldScreenMixin.java
@@ -26,6 +26,7 @@ import org.spongepowered.asm.mixin.Shadow;
 import org.spongepowered.asm.mixin.injection.At;
 import org.spongepowered.asm.mixin.injection.Inject;
 import org.spongepowered.asm.mixin.injection.ModifyArg;
+import org.spongepowered.asm.mixin.injection.ModifyVariable;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
 
 import net.minecraft.client.gui.screen.world.CreateWorldScreen;
@@ -44,6 +45,14 @@ public class CreateWorldScreenMixin {
 	@Shadow
 	private ResourcePackManager packManager;
 
+	@ModifyVariable(method = "create(Lnet/minecraft/client/MinecraftClient;Lnet/minecraft/client/gui/screen/Screen;)V",
+			at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/world/CreateWorldScreen;method_41849(Lnet/minecraft/resource/ResourcePackManager;Lnet/minecraft/resource/DataPackSettings;)Lnet/minecraft/class_7237$FunctionLoaderConfig;"))
+	private static ResourcePackManager onCreateResManagerInit(ResourcePackManager manager) {
+		// Add mod data packs to the initial res pack manager so they are active even if the user doesn't use custom data packs
+		((ResourcePackManagerAccessor) manager).getProviders().add(new ModResourcePackCreator(ResourceType.SERVER_DATA));
+		return manager;
+	}
+
 	@Inject(method = "getScannedPack", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePackManager;scanPacks()V", shift = At.Shift.BEFORE))
 	private void onScanPacks(CallbackInfoReturnable<Pair<File, ResourcePackManager>> cir) {
 		// Allow to display built-in data packs in the data pack selection screen at world creation.
diff --git a/fabric-screen-api-v1/src/main/java/net/fabricmc/fabric/mixin/screen/MouseMixin.java b/fabric-screen-api-v1/src/main/java/net/fabricmc/fabric/mixin/screen/MouseMixin.java
index 0bb5c1a63..6d0394f14 100644
--- a/fabric-screen-api-v1/src/main/java/net/fabricmc/fabric/mixin/screen/MouseMixin.java
+++ b/fabric-screen-api-v1/src/main/java/net/fabricmc/fabric/mixin/screen/MouseMixin.java
@@ -127,7 +127,7 @@ abstract class MouseMixin {
 		}
 
 		// Apply same calculations to horizontal scroll as vertical scroll amount has
-		this.horizontalScrollAmount = this.client.options.discreteMouseScroll ? Math.signum(horizontal) : horizontal * this.client.options.mouseWheelSensitivity;
+		this.horizontalScrollAmount = this.client.options.discreteMouseScroll ? Math.signum(horizontal) : horizontal * this.client.options.method_41806().method_41753();
 
 		if (!ScreenMouseEvents.allowMouseScroll(this.currentScreen).invoker().allowMouseScroll(this.currentScreen, mouseX, mouseY, this.horizontalScrollAmount, verticalAmount)) {
 			this.currentScreen = null;
diff --git a/gradle.properties b/gradle.properties
index 91e438f85..4e6b2e0f7 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,9 +1,9 @@
 org.gradle.jvmargs=-Xmx2560M
 
-version=0.48.0
-minecraft_version=1.18.2
-yarn_version=+build.1
-loader_version=0.13.2
+version=0.49.0
+minecraft_version=22w11a
+yarn_version=+build.2
+loader_version=0.13.3
 
 prerelease=false
 
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index 8391565ea..3ab1f111c 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -18,7 +18,7 @@
   "depends": {
     "fabricloader": ">=0.13.2",
     "java": ">=17",
-    "minecraft": "~1.18.2-alpha.22.5.a"
+    "minecraft": "~1.19-alpha.22.11.a"
   },
   "description": "Core API module providing key hooks and intercompatibility features."
 }