1.18.2-pre

This commit is contained in:
gnembon committed 2022-02-20 01:50:46 +01:00
1 parent 702022bce0
commit c01ad9ce9d
20 files changed
+303 -422

No files matched your search

+3 -2
View File
@@ -758,7 +758,8 @@ These contain some popular features and structures that are impossible or diffic
### `structure_eligibility(pos, ?structure, ?size_needed)` ### `structure_eligibility(pos, ?structure, ?size_needed)`
Checks wordgen eligibility for a structure in a given chunk. Requires a `Standard Structure` name (see above). Checks wordgen eligibility for a structure in a given chunk. Requires a `Structure Variant` name (see above),
or `Standard Structure` to check structures of this type.
If no structure is given, or `null`, then it will check If no structure is given, or `null`, then it will check
for all structures. If bounding box of the structures is also requested, it will compute size of potential for all structures. If bounding box of the structures is also requested, it will compute size of potential
structures. This function, unlike other in the `structure*` category is not using world data nor accesses chunks structures. This function, unlike other in the `structure*` category is not using world data nor accesses chunks
@@ -771,7 +772,7 @@ If structure is specified, it will return `null` if a chunk is not eligible or i
a map with two values: `'box'` for a pair of coordinates indicating bounding box of the structure, and `'pieces'` for a map with two values: `'box'` for a pair of coordinates indicating bounding box of the structure, and `'pieces'` for
list of elements of the structure (as a tuple), with its name, direction, and box coordinates of the piece. list of elements of the structure (as a tuple), with its name, direction, and box coordinates of the piece.
If structure is not specified, it will return a set of structure names that are eligible, or a map with structures If structure is not specified, or a `Standard Structure` was specified, like `'village'`,it will return a set of structure names that are eligible, or a map with structures
as keys, and same type of map values as with a single structure call. An empty set or an empty map would indicate that nothing as keys, and same type of map values as with a single structure call. An empty set or an empty map would indicate that nothing
should be generated there. should be generated there.
+1 -1
View File
@@ -357,7 +357,7 @@ Here is a list of built-in types, with their return value formats, as well as a
* `'loottable'`: name of a loot table source * `'loottable'`: name of a loot table source
* `'attribute'`: an attribute name * `'attribute'`: an attribute name
* `'boss'`: a bossbar name * `'boss'`: a bossbar name
* `'biome'`: a biome name * `'biome'`: a biome name. or biome tag
* `'sound'`: name of a sound * `'sound'`: name of a sound
* `'storekey'`: string of a valid current data store key. * `'storekey'`: string of a valid current data store key.
* `'identifier'`: any valid identifier. 'minecraft:' prefix is stripped off as a default. * `'identifier'`: any valid identifier. 'minecraft:' prefix is stripped off as a default.
+1 -1
View File
@@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/use # check these on https://fabricmc.net/use
# or better: https://modmuss50.me/fabric.html # or better: https://modmuss50.me/fabric.html
minecraft_version=22w07a minecraft_version=1.18.2-pre1
loader_version=0.12.12 loader_version=0.12.12
fabric_version=0.46.2+1.18 fabric_version=0.46.2+1.18
@@ -1,9 +1,12 @@
package carpet.fakes; package carpet.fakes;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
import java.util.List;
public interface ChunkGeneratorInterface public interface ChunkGeneratorInterface
{ {
//void initStrongholds(); void initStrongholds();
//boolean canPlaceStrongholdInBiomeCM(Biome biome); List<StructurePlacement> getPlacementsForFeatureCM(final ConfiguredStructureFeature<?, ?> structure);
} }
@@ -1,12 +0,0 @@
package carpet.fakes;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
public interface StructureFeatureInterface<C extends FeatureConfiguration>
{
boolean plopAnywhere(ServerLevel world, BlockPos pos, ChunkGenerator generator, boolean wireOnly,Biome biome, C config);
}
@@ -1,16 +0,0 @@
package carpet.helpers;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.MobSpawnSettings;
public class CustomSpawnLists
{
public static final WeightedRandomList<MobSpawnSettings.SpawnerData> PYRAMID_SPAWNS = WeightedRandomList.create(new MobSpawnSettings.SpawnerData(EntityType.HUSK, 1, 1, 1));
public static final WeightedRandomList<MobSpawnSettings.SpawnerData> SHULKER_SPAWNS = WeightedRandomList.create(new MobSpawnSettings.SpawnerData(EntityType.SHULKER, 10, 4, 4));
public static final WeightedRandomList<MobSpawnSettings.SpawnerData> BASTION_SPAWNS = WeightedRandomList.create(
new MobSpawnSettings.SpawnerData(EntityType.PIGLIN_BRUTE, 5, 1, 2),
new MobSpawnSettings.SpawnerData(EntityType.PIGLIN, 10, 2, 4),
new MobSpawnSettings.SpawnerData(EntityType.HOGLIN, 2, 1, 2)
);
}
+112 -121
View File
@@ -2,64 +2,52 @@ package carpet.helpers;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import carpet.fakes.ChunkGeneratorInterface; import carpet.fakes.ChunkGeneratorInterface;
import carpet.fakes.PlacedFeatureInterface;
import carpet.fakes.StructureFeatureInterface;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMultimap;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt; import java.util.OptionalInt;
import java.util.Set; import java.util.Random;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet; import net.minecraft.core.HolderSet;
import net.minecraft.core.QuartPos;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.data.worldgen.ProcessorLists; import net.minecraft.data.worldgen.ProcessorLists;
import net.minecraft.data.worldgen.StructureFeatures;
import net.minecraft.data.worldgen.placement.PlacementUtils; import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BiomeTags;
import net.minecraft.util.valueproviders.ConstantInt; import net.minecraft.util.valueproviders.ConstantInt;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.StructureSettings;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.StructureFeature; import net.minecraft.world.level.levelgen.feature.StructureFeature;
//import net.minecraft.world.level.levelgen.feature.configurations.StructureFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.JigsawConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.JigsawConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.SimpleRandomFeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.SimpleRandomFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration;
import net.minecraft.world.level.levelgen.feature.featuresize.TwoLayersFeatureSize; import net.minecraft.world.level.levelgen.feature.featuresize.TwoLayersFeatureSize;
import net.minecraft.world.level.levelgen.feature.foliageplacers.BlobFoliagePlacer; import net.minecraft.world.level.levelgen.feature.foliageplacers.BlobFoliagePlacer;
import net.minecraft.world.level.levelgen.feature.foliageplacers.FancyFoliagePlacer; import net.minecraft.world.level.levelgen.feature.foliageplacers.FancyFoliagePlacer;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider; import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.structure.pools.StructurePoolElement; import net.minecraft.world.level.levelgen.structure.pools.StructurePoolElement;
import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool; import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool;
import net.minecraft.world.level.levelgen.feature.treedecorators.BeehiveDecorator; import net.minecraft.world.level.levelgen.feature.treedecorators.BeehiveDecorator;
import net.minecraft.world.level.levelgen.feature.trunkplacers.FancyTrunkPlacer; import net.minecraft.world.level.levelgen.feature.trunkplacers.FancyTrunkPlacer;
import net.minecraft.world.level.levelgen.feature.trunkplacers.StraightTrunkPlacer; import net.minecraft.world.level.levelgen.feature.trunkplacers.StraightTrunkPlacer;
import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.structure.StructureCheckResult;
import net.minecraft.world.level.levelgen.structure.StructureStart; import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement; import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
public class FeatureGenerator public class FeatureGenerator
@@ -76,10 +64,7 @@ public class FeatureGenerator
ConfiguredStructureFeature<?, ?> structureFeature = world.registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY).get(id); ConfiguredStructureFeature<?, ?> structureFeature = world.registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY).get(id);
if (structureFeature != null) if (structureFeature != null)
{ {
return ((StructureFeatureInterface)structureFeature.feature).plopAnywhere( return plopAnywhere( structureFeature, world, pos, world.getChunkSource().getGenerator(), false);
world, pos, world.getChunkSource().getGenerator(),
false, world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).get(Biomes.PLAINS), structureFeature.config);
} }
ConfiguredFeature<?, ?> configuredFeature = world.registryAccess().registryOrThrow(Registry.CONFIGURED_FEATURE_REGISTRY).get(id); ConfiguredFeature<?, ?> configuredFeature = world.registryAccess().registryOrThrow(Registry.CONFIGURED_FEATURE_REGISTRY).get(id);
@@ -98,12 +83,9 @@ public class FeatureGenerator
StructureFeature<?> structure = Registry.STRUCTURE_FEATURE.get(id); StructureFeature<?> structure = Registry.STRUCTURE_FEATURE.get(id);
if (structure != null) if (structure != null)
{ {
ConfiguredStructureFeature<?,?> configuredStandard = getDefaultFeature(structure, world, pos, true); ConfiguredStructureFeature<?,?> configuredStandard = getDefaultFeature(structure, world, pos);
if (configuredStandard != null) if (configuredStandard != null)
return ((StructureFeatureInterface)configuredStandard.feature).plopAnywhere( return plopAnywhere(configuredStandard, world, pos, world.getChunkSource().getGenerator(), false);
world, pos, world.getChunkSource().getGenerator(),
false, world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).get(Biomes.PLAINS), configuredStandard.config);
} }
Feature<?> feature = Registry.FEATURE.get(id); Feature<?> feature = Registry.FEATURE.get(id);
if (feature != null) if (feature != null)
@@ -132,14 +114,12 @@ public class FeatureGenerator
if (configuredStructureFeature != null) return configuredStructureFeature; if (configuredStructureFeature != null) return configuredStructureFeature;
StructureFeature<?> structureFeature = Registry.STRUCTURE_FEATURE.get(id); StructureFeature<?> structureFeature = Registry.STRUCTURE_FEATURE.get(id);
if (structureFeature == null) return null; if (structureFeature == null) return null;
return getDefaultFeature(structureFeature, world, pos, true); return getDefaultFeature(structureFeature, world, pos);
} }
synchronized public static Boolean plopGrid(ConfiguredStructureFeature<?, ?> structureFeature, ServerLevel world, BlockPos pos) synchronized public static Boolean plopGrid(ConfiguredStructureFeature<?, ?> structureFeature, ServerLevel world, BlockPos pos)
{ {
return ((StructureFeatureInterface)structureFeature.feature).plopAnywhere( return plopAnywhere( structureFeature, world, pos, world.getChunkSource().getGenerator(), true);
world, pos, world.getChunkSource().getGenerator(),
true, world.getServer().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).get(net.minecraft.world.level.biome.Biomes.PLAINS), structureFeature.config);
} }
@FunctionalInterface @FunctionalInterface
@@ -167,24 +147,19 @@ public class FeatureGenerator
return simplePlop(new ConfiguredFeature<>(feature, config)); return simplePlop(new ConfiguredFeature<>(feature, config));
} }
private static Thing simplePlop(Holder<PlacedFeature> hpf)
{
return simplePlop(hpf.value().feature().value());
}
private static Thing simpleTree(TreeConfiguration config) private static Thing simpleTree(TreeConfiguration config)
{ {
//config.ignoreFluidCheck(); //config.ignoreFluidCheck();
return simplePlop(new ConfiguredFeature(Feature.TREE, config)); return simplePlop(new ConfiguredFeature(Feature.TREE, config));
} }
private static Thing spawnCustomStructure(StructureFeature structure, FeatureConfiguration conf, ResourceKey<Biome> biome) private static Thing spawnCustomStructure(ConfiguredStructureFeature<?,?> structure)
{ {
return setupCustomStructure(structure, conf, biome, false); return setupCustomStructure(structure,false);
} }
private static Thing setupCustomStructure(StructureFeature structure, FeatureConfiguration conf, ResourceKey<Biome> biome, boolean wireOnly) private static Thing setupCustomStructure(ConfiguredStructureFeature<?,?> structure, boolean wireOnly)
{ {
return (w, p) -> ((StructureFeatureInterface)structure).plopAnywhere(w, p, w.getChunkSource().getGenerator(), wireOnly, w.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).get(biome), conf); return (w, p) -> plopAnywhere(structure, w, p, w.getChunkSource().getGenerator(), wireOnly);
} }
public static Boolean spawn(String name, ServerLevel world, BlockPos pos) public static Boolean spawn(String name, ServerLevel world, BlockPos pos)
@@ -194,21 +169,19 @@ public class FeatureGenerator
return null; return null;
} }
private static ConfiguredStructureFeature<?, ?> getDefaultFeature(StructureFeature<?> structure, ServerLevel world, BlockPos pos, boolean tryHard) private static ConfiguredStructureFeature<?, ?> getDefaultFeature(StructureFeature<?> structure, ServerLevel world, BlockPos pos)
{ {
var definedStructures = world.getChunkSource().getGenerator().getAllConfigurationsFor(structure); // would be nice to have a way to grab structures of this type for position
Holder<Biome> existingBiome = world.getBiome(pos);
for (final Holder.Reference<ConfiguredStructureFeature<?, ?>> featureConfig : definedStructures) { Holder<Biome> existingBiome = world.getBiome(pos);
final HolderSet<Biome> biomeAllowedForStructure = featureConfig.value().biomes(); ConfiguredStructureFeature<?, ?> result = null;
if (biomeAllowedForStructure.contains(existingBiome)) { for (var confstr : world.registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY).entrySet().stream().
return featureConfig.value(); filter(cS -> cS.getValue().feature == structure).map(Map.Entry::getValue).toList())
} {
result = confstr;
if (confstr.biomes.contains(existingBiome)) return result;
} }
if (!tryHard) return null; return result;
return world.registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY).entrySet().stream().
filter(cS -> cS.getValue().feature == structure).
findFirst().map(Map.Entry::getValue).orElse(null);
} }
private static ConfiguredFeature<?, ?> getDefaultFeature(Feature<?> feature, ServerLevel world, BlockPos pos, boolean tryHard) private static ConfiguredFeature<?, ?> getDefaultFeature(Feature<?> feature, ServerLevel world, BlockPos pos, boolean tryHard)
@@ -226,70 +199,35 @@ public class FeatureGenerator
findFirst().map(Map.Entry::getValue).orElse(null); findFirst().map(Map.Entry::getValue).orElse(null);
} }
public static <T extends FeatureConfiguration> StructureStart shouldStructureStartAt(ServerLevel world, BlockPos pos, StructureFeature<T> structure, boolean computeBox) public static <T extends FeatureConfiguration> StructureStart shouldStructureStartAt(ServerLevel world, BlockPos pos, ConfiguredStructureFeature<T, ?> structure, boolean computeBox)
{ {
//if (structure == StructureFeature.STRONGHOLD)
// return shouldStrongholdStartAt(world, pos, computeBox);
long seed = world.getSeed(); long seed = world.getSeed();
ChunkGenerator generator = world.getChunkSource().getGenerator(); ChunkGenerator generator = world.getChunkSource().getGenerator();
StructureSettings settings = generator.getSettings(); ChunkGeneratorInterface cgi = (ChunkGeneratorInterface) generator;
StructurePlacement structureConfig = settings.getConfig(structure); List<StructurePlacement> structureConfig = cgi.getPlacementsForFeatureCM(structure);
if (structureConfig instanceof ConcentricRingsStructurePlacement rings)
{
return shouldStrongholdStartAt(generator, rings, world, pos, computeBox);
}
if (structureConfig == null)
{
return null;
}
ChunkPos chunkPos = new ChunkPos(pos); ChunkPos chunkPos = new ChunkPos(pos);
boolean couldPlace = structureConfig.stream().anyMatch(p -> p.isFeatureChunk(generator, chunkPos.x, chunkPos.z));
if (!couldPlace) return null;
StructureFeatureManager structureManager = world.structureFeatureManager(); final HolderSet<Biome> structureBiomes = structure.biomes();
StructureCheckResult isThere = structureManager.checkStructurePresence(chunkPos, structure, false);
if (isThere == StructureCheckResult.START_NOT_PRESENT)
{
return null;
}
if (!structureConfig.isFeatureChunk(generator, chunkPos.x, chunkPos.z)) { if (!computeBox) {
return null; Holder<Biome> genBiome = generator.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ()));
}; if (structureBiomes.contains(genBiome) && structure.feature.canGenerate(
for (final Holder.Reference<ConfiguredStructureFeature<?, ?>> featureConfig : generator.getAllConfigurationsFor(structure)) { world.registryAccess(), generator, generator.getBiomeSource(), world.getStructureManager(),
final HolderSet<Biome> biomeAllowedForStructure = featureConfig.value().biomes(); seed, chunkPos, structure.config, world, structureBiomes::contains
if (!computeBox) { ))
if (biomeAllowedForStructure.contains(world.getBiome(pos))) { {
return StructureStart.INVALID_START; return StructureStart.INVALID_START;
}
}
else {
final StructureStart<?> filledStructure = featureConfig.value().generate(
world.registryAccess(), generator, generator.getBiomeSource(), world.getStructureManager(),
seed, chunkPos, 0, world, biomeAllowedForStructure::contains);
if (filledStructure != null && filledStructure.isValid()) {
return filledStructure;
}
} }
} }
return null; else {
} final StructureStart filledStructure = structure.generate(
world.registryAccess(), generator, generator.getBiomeSource(), world.getStructureManager(),
public static StructureStart<?> shouldStrongholdStartAt(ChunkGenerator generator, ConcentricRingsStructurePlacement rings, ServerLevel world, BlockPos pos, boolean computeBox) seed, chunkPos, 0, world, structureBiomes::contains);
{ if (filledStructure != null && filledStructure.isValid()) {
final List<ChunkPos> positions = generator.getRingPositionsFor(rings);
if (world.dimension() != Level.OVERWORLD || !positions.contains(new ChunkPos(pos))) return null;
if (!computeBox) return StructureStart.INVALID_START;
StructureSettings settings = generator.getSettings();
StructurePlacement structureConfig = settings.getConfig(StructureFeature.STRONGHOLD);
if (structureConfig != null) {
final List<Holder.Reference<ConfiguredStructureFeature<?, ?>>> configurations = generator.getAllConfigurationsFor(StructureFeature.STRONGHOLD);
final Set<Holder<Biome>> allowedBiomes = configurations.stream().flatMap(s -> s.value().biomes().stream()).distinct().collect(Collectors.toSet());
StructureStart<?> filledStructure = StructureFeature.STRONGHOLD.generate(world.registryAccess(), generator, generator.getBiomeSource(),
world.getStructureManager(), world.getSeed(), new ChunkPos(pos), 0, NoneFeatureConfiguration.INSTANCE, world, allowedBiomes::contains
);
if (filledStructure != null && filledStructure.isValid())
return filledStructure; return filledStructure;
}
} }
return null; return null;
} }
@@ -298,13 +236,12 @@ public class FeatureGenerator
return new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(block), new StraightTrunkPlacer(i, j, k), BlockStateProvider.simple(block2), new BlobFoliagePlacer(ConstantInt.of(l), ConstantInt.of(0), 3), new TwoLayersFeatureSize(1, 0, 1)); return new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(block), new StraightTrunkPlacer(i, j, k), BlockStateProvider.simple(block2), new BlobFoliagePlacer(ConstantInt.of(l), ConstantInt.of(0), 3), new TwoLayersFeatureSize(1, 0, 1));
} }
public static final Map<String, Thing> featureMap = new HashMap<String, Thing>() {{ public static final Map<String, Thing> featureMap = new HashMap<>() {{
put("oak_bees", simpleTree( createTree(Blocks.OAK_LOG, Blocks.OAK_LEAVES, 4, 2, 0, 2).ignoreVines().decorators(List.of(new BeehiveDecorator(1.00F))).build())); put("oak_bees", simpleTree( createTree(Blocks.OAK_LOG, Blocks.OAK_LEAVES, 4, 2, 0, 2).ignoreVines().decorators(List.of(new BeehiveDecorator(1.00F))).build()));
put("fancy_oak_bees", simpleTree( (new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(Blocks.OAK_LOG), new FancyTrunkPlacer(3, 11, 0), BlockStateProvider.simple(Blocks.OAK_LEAVES), new FancyFoliagePlacer(ConstantInt.of(2), ConstantInt.of(4), 4), new TwoLayersFeatureSize(0, 0, 0, OptionalInt.of(4)))).ignoreVines().decorators(List.of(new BeehiveDecorator(1.00F))).build())); put("fancy_oak_bees", simpleTree( (new TreeConfiguration.TreeConfigurationBuilder(BlockStateProvider.simple(Blocks.OAK_LOG), new FancyTrunkPlacer(3, 11, 0), BlockStateProvider.simple(Blocks.OAK_LEAVES), new FancyFoliagePlacer(ConstantInt.of(2), ConstantInt.of(4), 4), new TwoLayersFeatureSize(0, 0, 0, OptionalInt.of(4)))).ignoreVines().decorators(List.of(new BeehiveDecorator(1.00F))).build()));
put("birch_bees", simpleTree( createTree(Blocks.BIRCH_LOG, Blocks.BIRCH_LEAVES, 5, 2, 0, 2).ignoreVines().decorators(List.of(new BeehiveDecorator(1.00F))).build())); put("birch_bees", simpleTree( createTree(Blocks.BIRCH_LOG, Blocks.BIRCH_LEAVES, 5, 2, 0, 2).ignoreVines().decorators(List.of(new BeehiveDecorator(1.00F))).build()));
//put("coral_tree", simplePlop(Feature.CORAL_TREE.configured(FeatureConfiguration.NONE)));
put("coral_tree", simplePlop(Feature.CORAL_TREE, FeatureConfiguration.NONE)); put("coral_tree", simplePlop(Feature.CORAL_TREE, FeatureConfiguration.NONE));
put("coral_claw", simplePlop(Feature.CORAL_CLAW, FeatureConfiguration.NONE)); put("coral_claw", simplePlop(Feature.CORAL_CLAW, FeatureConfiguration.NONE));
@@ -314,8 +251,7 @@ public class FeatureGenerator
PlacementUtils.inlinePlaced(Feature.CORAL_CLAW, FeatureConfiguration.NONE), PlacementUtils.inlinePlaced(Feature.CORAL_CLAW, FeatureConfiguration.NONE),
PlacementUtils.inlinePlaced(Feature.CORAL_MUSHROOM, FeatureConfiguration.NONE) PlacementUtils.inlinePlaced(Feature.CORAL_MUSHROOM, FeatureConfiguration.NONE)
)))); ))));
put("bastion_remnant_units", spawnCustomStructure( put("bastion_remnant_units", spawnCustomStructure(StructureFeature.BASTION_REMNANT.configured(
StructureFeature.BASTION_REMNANT,
new JigsawConfiguration(Holder.direct(new StructureTemplatePool( new JigsawConfiguration(Holder.direct(new StructureTemplatePool(
new ResourceLocation("bastion/starts"), new ResourceLocation("bastion/starts"),
new ResourceLocation("empty"), new ResourceLocation("empty"),
@@ -324,10 +260,9 @@ public class FeatureGenerator
), ),
StructureTemplatePool.Projection.RIGID StructureTemplatePool.Projection.RIGID
)), 6), )), 6),
Biomes.NETHER_WASTES BiomeTags.HAS_BASTION_REMNANT)
)); ));
put("bastion_remnant_hoglin_stable", spawnCustomStructure( put("bastion_remnant_hoglin_stable", spawnCustomStructure(StructureFeature.BASTION_REMNANT.configured(
StructureFeature.BASTION_REMNANT,
new JigsawConfiguration(Holder.direct(new StructureTemplatePool( new JigsawConfiguration(Holder.direct(new StructureTemplatePool(
new ResourceLocation("bastion/starts"), new ResourceLocation("bastion/starts"),
new ResourceLocation("empty"), new ResourceLocation("empty"),
@@ -336,10 +271,9 @@ public class FeatureGenerator
), ),
StructureTemplatePool.Projection.RIGID StructureTemplatePool.Projection.RIGID
)), 6), )), 6),
Biomes.NETHER_WASTES BiomeTags.HAS_BASTION_REMNANT)
)); ));
put("bastion_remnant_treasure", spawnCustomStructure( put("bastion_remnant_treasure", spawnCustomStructure(StructureFeature.BASTION_REMNANT.configured(
StructureFeature.BASTION_REMNANT,
new JigsawConfiguration(Holder.direct(new StructureTemplatePool( new JigsawConfiguration(Holder.direct(new StructureTemplatePool(
new ResourceLocation("bastion/starts"), new ResourceLocation("bastion/starts"),
new ResourceLocation("empty"), new ResourceLocation("empty"),
@@ -348,10 +282,9 @@ public class FeatureGenerator
), ),
StructureTemplatePool.Projection.RIGID StructureTemplatePool.Projection.RIGID
)), 6), )), 6),
Biomes.NETHER_WASTES BiomeTags.HAS_BASTION_REMNANT)
)); ));
put("bastion_remnant_bridge", spawnCustomStructure( put("bastion_remnant_bridge", spawnCustomStructure(StructureFeature.BASTION_REMNANT.configured(
StructureFeature.BASTION_REMNANT,
new JigsawConfiguration(Holder.direct(new StructureTemplatePool( new JigsawConfiguration(Holder.direct(new StructureTemplatePool(
new ResourceLocation("bastion/starts"), new ResourceLocation("bastion/starts"),
new ResourceLocation("empty"), new ResourceLocation("empty"),
@@ -360,8 +293,66 @@ public class FeatureGenerator
), ),
StructureTemplatePool.Projection.RIGID StructureTemplatePool.Projection.RIGID
)), 6), )), 6),
Biomes.NETHER_WASTES BiomeTags.HAS_BASTION_REMNANT)
)); ));
}}; }};
public static boolean plopAnywhere(ConfiguredStructureFeature<?, ?> structure, ServerLevel world, BlockPos pos, ChunkGenerator generator, boolean wireOnly)
{
if (world.isClientSide())
return false;
CarpetSettings.skipGenerationChecks.set(true);
try
{
StructureStart start = structure.generate(world.registryAccess(), generator, generator.getBiomeSource(), world.getStructureManager(), world.getSeed(), new ChunkPos(pos), 0, world, b -> true );
if (start == StructureStart.INVALID_START)
{
return false;
}
Random rand = new Random(world.getRandom().nextInt());
int j = pos.getX() >> 4;
int k = pos.getZ() >> 4;
long chId = ChunkPos.asLong(j, k);
world.getChunk(j, k).addReferenceForFeature(structure, chId);
BoundingBox box = start.getBoundingBox();
if (!wireOnly)
{
Registry<ConfiguredStructureFeature<?, ?>> registry3 = world.registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
world.setCurrentlyGenerating(() -> {
Objects.requireNonNull(structure);
return registry3.getResourceKey(structure).map(Object::toString).orElseGet(structure::toString);
});
start.placeInChunk(world, world.structureFeatureManager(), generator, rand, box, new ChunkPos(j, k));
}
//structurestart.notifyPostProcessAt(new ChunkPos(j, k));
int i = Math.max(box.getXSpan(),box.getZSpan())/16+1;
//int i = getRadius();
for (int k1 = j - i; k1 <= j + i; ++k1)
{
for (int l1 = k - i; l1 <= k + i; ++l1)
{
if (k1 == j && l1 == k) continue;
if (box.intersects(k1<<4, l1<<4, (k1<<4) + 15, (l1<<4) + 15))
{
world.getChunk(k1, l1).addReferenceForFeature(structure, chId);
}
}
}
}
catch (Exception booboo)
{
CarpetSettings.LOG.error("Unknown Exception while plopping structure: "+booboo, booboo);
return false;
}
finally
{
CarpetSettings.skipGenerationChecks.set(false);
}
return true;
}
} }
@@ -0,0 +1,73 @@
package carpet.mixins;
import carpet.CarpetSettings;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.core.Holder;
import net.minecraft.data.worldgen.StructureFeatures;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
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.CallbackInfoReturnable;
import net.minecraft.core.BlockPos;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.chunk.ChunkGenerator;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Iterator;
import java.util.Map;
@Mixin(ChunkGenerator.class)
public abstract class ChunkGenerator_customMobSpawnsMixin
{
@Shadow protected abstract void ensureGenerated();
private static final WeightedRandomList<MobSpawnSettings.SpawnerData> PYRAMID_SPAWNS = WeightedRandomList.create(new MobSpawnSettings.SpawnerData(EntityType.HUSK, 1, 1, 1));
private static final WeightedRandomList<MobSpawnSettings.SpawnerData> SHULKER_SPAWNS = WeightedRandomList.create(new MobSpawnSettings.SpawnerData(EntityType.SHULKER, 10, 4, 4));
private static final WeightedRandomList<MobSpawnSettings.SpawnerData> BASTION_SPAWNS = WeightedRandomList.create(
new MobSpawnSettings.SpawnerData(EntityType.PIGLIN_BRUTE, 5, 1, 2),
new MobSpawnSettings.SpawnerData(EntityType.PIGLIN, 10, 2, 4),
new MobSpawnSettings.SpawnerData(EntityType.HOGLIN, 2, 1, 2)
);
@Inject(
method = "getMobsAt", locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(
value = "INVOKE",
target = "Ljava/util/Map$Entry;getKey()Ljava/lang/Object;"
), cancellable = true)
private void isInsidePyramid(Holder<Biome> holder, StructureFeatureManager structureFeatureManager, MobCategory mobCategory, BlockPos blockPos,
CallbackInfoReturnable<WeightedRandomList<MobSpawnSettings.SpawnerData>> cir,
Map<ConfiguredStructureFeature<?, ?>, LongSet> map, Iterator<?> var6, Map.Entry<ConfiguredStructureFeature<?, ?>, LongSet> entry)
{
if (mobCategory == MobCategory.MONSTER)
{
ConfiguredStructureFeature<?, ?> str = entry.getKey();
if (CarpetSettings.huskSpawningInTemples
&& str.feature == StructureFeatures.DESERT_PYRAMID.value().feature
&& structureFeatureManager.getStructureAt(blockPos, StructureFeatures.DESERT_PYRAMID.value()).isValid()) {
cir.setReturnValue(PYRAMID_SPAWNS);
return;
}
if (CarpetSettings.shulkerSpawningInEndCities
&& str.feature == StructureFeatures.END_CITY.value().feature
&& structureFeatureManager.getStructureAt(blockPos, StructureFeatures.END_CITY.value()).isValid()) {
cir.setReturnValue(SHULKER_SPAWNS);
return;
}
if (CarpetSettings.piglinsSpawningInBastions
&& str.feature == StructureFeatures.BASTION_REMNANT.value().feature
&& structureFeatureManager.getStructureAt(blockPos, StructureFeatures.BASTION_REMNANT.value()).isValid()) {
cir.setReturnValue(BASTION_SPAWNS);
}
}
}
}
@@ -1,25 +1,30 @@
package carpet.mixins; package carpet.mixins;
import carpet.fakes.ChunkGeneratorInterface; import carpet.fakes.ChunkGeneratorInterface;
import net.minecraft.world.level.biome.Biome; import net.minecraft.core.Holder;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import java.util.List;
@Mixin(ChunkGenerator.class) @Mixin(ChunkGenerator.class)
public abstract class ChunkGenerator_scarpetMixin implements ChunkGeneratorInterface public abstract class ChunkGenerator_scarpetMixin implements ChunkGeneratorInterface
{ {
//@Shadow protected abstract void generateStrongholds(); // postInit @Shadow protected abstract void ensureGenerated();
//@Shadow private static boolean validStrongholdBiome(Biome biome) { return true;}
// @Override @Shadow protected abstract List<StructurePlacement> getPlacementsForFeature(Holder<ConfiguredStructureFeature<?, ?>> holder);
//public void initStrongholds()
//{
// generateStrongholds();
//}
//@Override @Override
//public boolean canPlaceStrongholdInBiomeCM(Biome biome) { public void initStrongholds()
// return validStrongholdBiome(biome); {
//} ensureGenerated();
}
@Override
public List<StructurePlacement> getPlacementsForFeatureCM(ConfiguredStructureFeature<?, ?> structure) {
return getPlacementsForFeature(Holder.direct(structure));
}
} }
@@ -1,36 +1,23 @@
package carpet.mixins; package carpet.mixins;
import carpet.CarpetSettings; import net.minecraft.core.HolderSet;
import carpet.helpers.CustomSpawnLists;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature; import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.feature.NetherFortressFeature;
import net.minecraft.world.level.levelgen.feature.OceanMonumentFeature;
import net.minecraft.world.level.levelgen.feature.PillagerOutpostFeature;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.feature.SwamplandHutFeature;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.core.BlockPos;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.StructureSettings;
import java.util.Optional;
@Mixin(FlatLevelSource.class) @Mixin(FlatLevelSource.class)
public abstract class FlatLevelSource_structuresMixin extends ChunkGenerator public abstract class FlatLevelSource_structuresMixin extends ChunkGenerator
{ {
public FlatLevelSource_structuresMixin(Registry<ConfiguredStructureFeature<?, ?>> registry, BiomeSource biomeSource, StructureSettings structureSettings) public FlatLevelSource_structuresMixin(Registry<StructureSet> registry, Optional<HolderSet<StructureSet>> optional, BiomeSource biomeSource) {
{ super(registry, optional, biomeSource);
super(registry, biomeSource, structureSettings);
} }
/*
@Override @Override
public WeightedRandomList<MobSpawnSettings.SpawnerData> getMobsAt(Holder<Biome> biome, StructureFeatureManager accessor, MobCategory group, BlockPos pos) public WeightedRandomList<MobSpawnSettings.SpawnerData> getMobsAt(Holder<Biome> biome, StructureFeatureManager accessor, MobCategory group, BlockPos pos)
{ {
@@ -91,4 +78,6 @@ public abstract class FlatLevelSource_structuresMixin extends ChunkGenerator
} }
*/
} }
@@ -2,10 +2,10 @@ package carpet.mixins;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.data.worldgen.StructureFeatures;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.monster.Husk; import net.minecraft.world.entity.monster.Husk;
import net.minecraft.world.level.ServerLevelAccessor; import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
@@ -17,6 +17,6 @@ public class Husk_templesMixin
private static boolean isSkylightOrTempleVisible(ServerLevelAccessor serverWorldAccess, BlockPos pos) private static boolean isSkylightOrTempleVisible(ServerLevelAccessor serverWorldAccess, BlockPos pos)
{ {
return serverWorldAccess.canSeeSky(pos) || return serverWorldAccess.canSeeSky(pos) ||
(CarpetSettings.huskSpawningInTemples && (((ServerLevel)serverWorldAccess).structureFeatureManager().getStructureAt(pos, StructureFeature.DESERT_PYRAMID).isValid())); (CarpetSettings.huskSpawningInTemples && (((ServerLevel)serverWorldAccess).structureFeatureManager().getStructureAt(pos, StructureFeatures.DESERT_PYRAMID.value()).isValid()));
} }
} }
@@ -1,63 +0,0 @@
package carpet.mixins;
import carpet.CarpetSettings;
import carpet.helpers.CustomSpawnLists;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
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.core.BlockPos;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.StructureSettings;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
@Mixin(NoiseBasedChunkGenerator.class)
public abstract class NoiseBasedChunkGenerator_husksSpawnMixin extends ChunkGenerator
{
public NoiseBasedChunkGenerator_husksSpawnMixin(Registry<ConfiguredStructureFeature<?, ?>> registry, BiomeSource biomeSource, StructureSettings structureSettings) {
super(registry, biomeSource, structureSettings);
}
@Inject(method = "getMobsAt", at = @At("HEAD"), cancellable = true)
private void isInsidePyramid(Holder<Biome> holder, StructureFeatureManager structureFeatureManager, MobCategory mobCategory, BlockPos blockPos, CallbackInfoReturnable<WeightedRandomList<MobSpawnSettings.SpawnerData>> cir)
{
if (mobCategory == MobCategory.MONSTER)
{
if (CarpetSettings.huskSpawningInTemples)
{
if (structureFeatureManager.getStructureAt(blockPos, StructureFeature.DESERT_PYRAMID).isValid())
{
cir.setReturnValue(CustomSpawnLists.PYRAMID_SPAWNS);
return;
}
}
if (CarpetSettings.shulkerSpawningInEndCities)
{
if (structureFeatureManager.getStructureAt(blockPos, StructureFeature.END_CITY).isValid())
{
cir.setReturnValue(CustomSpawnLists.SHULKER_SPAWNS);
return;
}
}
if (CarpetSettings.piglinsSpawningInBastions)
{
if (structureFeatureManager.getStructureAt(blockPos, StructureFeature.BASTION_REMNANT).isValid())
{
cir.setReturnValue(CustomSpawnLists.BASTION_SPAWNS);
}
}
}
}
}
@@ -1,130 +0,0 @@
package carpet.mixins;
import carpet.CarpetSettings;
import carpet.fakes.StructureFeatureInterface;
import com.google.common.collect.ImmutableMultimap;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.function.Predicate;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.QuartPos;
import net.minecraft.core.Registry;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.RandomSupport;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.levelgen.structure.pieces.PieceGenerator;
import net.minecraft.world.level.levelgen.structure.pieces.PieceGeneratorSupplier;
import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder;
@Mixin(StructureFeature.class)
public abstract class StructureFeatureMixin<C extends FeatureConfiguration> implements StructureFeatureInterface<C>
{
@Shadow @Final private PieceGeneratorSupplier<C> pieceGenerator;
@Override
public boolean plopAnywhere(ServerLevel world, BlockPos pos, ChunkGenerator generator, boolean wireOnly, Biome biome, C config)
{
if (world.isClientSide())
return false;
CarpetSettings.skipGenerationChecks.set(true);
try
{
Random rand = new Random(world.getRandom().nextInt());
int j = pos.getX() >> 4;
int k = pos.getZ() >> 4;
long chId = ChunkPos.asLong(j, k);
StructureStart<C> structurestart = forceStructureStart(world, generator, rand, chId, biome, config);
if (structurestart == StructureStart.INVALID_START)
{
return false;
}
StructureFeature<C> thiss = (StructureFeature<C>) (Object)this;
world.getChunk(j, k).addReferenceForFeature(thiss, chId);
BoundingBox box = structurestart.getBoundingBox();
if (!wireOnly)
{
Registry<StructureFeature<?>> registry3 = world.registryAccess().registryOrThrow(Registry.STRUCTURE_FEATURE_REGISTRY);
world.setCurrentlyGenerating(() -> {
Objects.requireNonNull(thiss);
return registry3.getResourceKey(thiss).map(Object::toString).orElseGet(thiss::toString);
});
structurestart.placeInChunk(world, world.structureFeatureManager(), generator, rand, box, new ChunkPos(j, k));
}
//structurestart.notifyPostProcessAt(new ChunkPos(j, k));
int i = Math.max(box.getXSpan(),box.getZSpan())/16+1;
//int i = getRadius();
for (int k1 = j - i; k1 <= j + i; ++k1)
{
for (int l1 = k - i; l1 <= k + i; ++l1)
{
if (k1 == j && l1 == k) continue;
long nbchkid = ChunkPos.asLong(k1, l1);
if (box.intersects(k1<<4, l1<<4, (k1<<4) + 15, (l1<<4) + 15))
{
world.getChunk(k1, l1).addReferenceForFeature(thiss, chId);
}
}
}
}
catch (Exception booboo)
{
CarpetSettings.LOG.error("Unknown Exception while plopping structure: "+booboo, booboo);
return false;
}
finally
{
CarpetSettings.skipGenerationChecks.set(false);
}
return true;
}
private StructureStart<C> forceStructureStart(ServerLevel worldIn, ChunkGenerator generator, Random rand, long packedChunkPos, Biome biome, C config)
{
ChunkPos chunkpos = new ChunkPos(packedChunkPos);
StructureFeature<C> thiss= (StructureFeature<C>)(Object)this;
ChunkAccess ichunk = worldIn.getChunk(chunkpos.x, chunkpos.z, ChunkStatus.STRUCTURE_STARTS, false);
if (ichunk != null)
{
StructureStart<?> structurestartt = ichunk.getStartForFeature(thiss);
if (structurestartt != null && structurestartt != StructureStart.INVALID_START)
{
return (StructureStart<C>) structurestartt;
}
}
Optional<PieceGenerator<C>> optional = pieceGenerator.createGenerator(new PieceGeneratorSupplier.Context<>(generator, generator.getBiomeSource(), worldIn.getSeed(), chunkpos, config, worldIn, b -> true, worldIn.getStructureManager(), worldIn.registryAccess()));
if (optional.isEmpty()) return (StructureStart<C>) StructureStart.INVALID_START;
StructurePiecesBuilder lv = new StructurePiecesBuilder();
optional.get().generatePieces(lv, new PieceGenerator.Context<C>(config, generator, worldIn.getStructureManager(), chunkpos, worldIn, Util.make(new WorldgenRandom(new LegacyRandomSource(RandomSupport.seedUniquifier())), (chunkRandomx) -> {
chunkRandomx.setLargeFeatureSeed(worldIn.getSeed(), chunkpos.x, chunkpos.z);
}), worldIn.getSeed()));
StructureStart<C> structurestart1 = new StructureStart<>(thiss, chunkpos, 0, lv.build());
if (structurestart1.isValid())
{
worldIn.getChunk(chunkpos.x, chunkpos.z).setStartForFeature(thiss, structurestart1);
}
return structurestart1;
}
}
@@ -794,7 +794,7 @@ public class Auxiliary {
if (res == null) if (res == null)
return; return;
if (what.equalsIgnoreCase("boulder")) // there might be more of those if (what.equalsIgnoreCase("forest_rock")) // there might be more of those
WorldTools.forceChunkUpdate(locator.block.getPos(), ((CarpetContext) c).s.getLevel()); WorldTools.forceChunkUpdate(locator.block.getPos(), ((CarpetContext) c).s.getLevel());
result[0] = BooleanValue.of(res); result[0] = BooleanValue.of(res);
}); });
@@ -4,7 +4,6 @@ import carpet.CarpetServer;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import carpet.fakes.ChunkGeneratorInterface; import carpet.fakes.ChunkGeneratorInterface;
import carpet.fakes.ChunkTicketManagerInterface; import carpet.fakes.ChunkTicketManagerInterface;
import carpet.fakes.NoiseColumnSamplerInterface;
import carpet.fakes.ServerChunkManagerInterface; import carpet.fakes.ServerChunkManagerInterface;
import carpet.fakes.ServerWorldInterface; import carpet.fakes.ServerWorldInterface;
import carpet.fakes.SpawnHelperInnerInterface; import carpet.fakes.SpawnHelperInnerInterface;
@@ -31,7 +30,6 @@ import carpet.script.value.EntityValue;
import carpet.script.value.ListValue; import carpet.script.value.ListValue;
import carpet.script.value.MapValue; import carpet.script.value.MapValue;
import carpet.script.value.NBTSerializableValue; import carpet.script.value.NBTSerializableValue;
import carpet.script.value.NullValue;
import carpet.script.value.NumericValue; import carpet.script.value.NumericValue;
import carpet.script.value.StringValue; import carpet.script.value.StringValue;
import carpet.script.value.Value; import carpet.script.value.Value;
@@ -241,10 +239,10 @@ public class WorldAccess {
private static void BooYah(ChunkGenerator generator) private static void BooYah(ChunkGenerator generator)
{ {
//synchronized (generator) synchronized (generator)
//{ {
// ((ChunkGeneratorInterface)generator).initStrongholds(); ((ChunkGeneratorInterface)generator).initStrongholds();
//} }
} }
public static void apply(Expression expression) public static void apply(Expression expression)
@@ -1287,16 +1285,15 @@ public class WorldAccess {
BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockArgument locator = BlockArgument.findIn(cc, lv, 0);
ServerLevel world = cc.s.getLevel(); ServerLevel world = cc.s.getLevel();
BlockPos pos = locator.block.getPos(); BlockPos pos = locator.block.getPos();
Map<StructureFeature<?>, LongSet> references = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences(); Map<ConfiguredStructureFeature<?,?>, LongSet> references = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences();
Registry<ConfiguredStructureFeature<?, ?>> reg = cc.s.getServer().registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
if (lv.size() == locator.offset) if (lv.size() == locator.offset)
return ListValue.wrap(references.entrySet().stream(). return ListValue.wrap(references.entrySet().stream().
filter(e -> e.getValue()!= null && !e.getValue().isEmpty()). filter(e -> e.getValue()!= null && !e.getValue().isEmpty()).
map(e -> new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_FEATURE.getKey(e.getKey())))).collect(Collectors.toList()) map(e -> new StringValue(NBTSerializableValue.nameFromRegistryId(reg.getKey(e.getKey())))).collect(Collectors.toList())
); );
String simpleStructureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); String simpleStructureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT);
//CarpetSettings.LOG.error(FeatureGenerator.featureToStructure.keySet().stream().collect(Collectors.joining(","))); ConfiguredStructureFeature<?,?> structureName = reg.get(InputValidator.identifierOf(simpleStructureName));
//CarpetSettings.LOG.error(FeatureGenerator.featureToStructure.values().stream().collect(Collectors.joining(",")));
StructureFeature<?> structureName = Registry.STRUCTURE_FEATURE.get(InputValidator.identifierOf(simpleStructureName));
if (structureName == null) return Value.NULL; if (structureName == null) return Value.NULL;
LongSet structureReferences = references.get(structureName); LongSet structureReferences = references.get(structureName);
if (structureReferences == null || structureReferences.isEmpty()) return ListValue.of(); if (structureReferences == null || structureReferences.isEmpty()) return ListValue.of();
@@ -1317,46 +1314,73 @@ public class WorldAccess {
BooYah(world.getChunkSource().getGenerator()); BooYah(world.getChunkSource().getGenerator());
BlockPos pos = locator.block.getPos(); BlockPos pos = locator.block.getPos();
StructureFeature<?> structure = null; final List<ConfiguredStructureFeature<?, ?>> structure = new ArrayList<>();
boolean needSize = false; boolean needSize = false;
boolean singleOutput = false;
Registry<ConfiguredStructureFeature<?, ?>> reg = cc.s.getServer().registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
if (lv.size() > locator.offset) if (lv.size() > locator.offset)
{ {
Value requested = lv.get(locator.offset+0); Value requested = lv.get(locator.offset+0);
if (!requested.isNull()) if (!requested.isNull())
{ {
String reqString = requested.getString(); String reqString = requested.getString();
structure = Registry.STRUCTURE_FEATURE.getOptional(InputValidator.identifierOf(reqString)) var id = InputValidator.identifierOf(reqString);
.orElseThrow(() -> new ThrowStatement(reqString, Throwables.UNKNOWN_STRUCTURE)); ConfiguredStructureFeature<?, ?> requestedStructure = reg.get(id);
if (requestedStructure != null)
{
singleOutput = true;
structure.add(requestedStructure);
}
else
{
Registry<StructureFeature<?>> reg1 = cc.s.getServer().registryAccess().registryOrThrow(Registry.STRUCTURE_FEATURE_REGISTRY);
StructureFeature<?> sss = reg1.get(id);
// bad
reg.entrySet().stream().filter(e -> e.getValue().feature==sss).forEach(e -> structure.add(e.getValue()));
}
if (structure.isEmpty())
{
throw new ThrowStatement(reqString, Throwables.UNKNOWN_STRUCTURE);
}
}
else
{
structure.addAll(reg.entrySet().stream().map(Map.Entry::getValue).toList());
} }
if (lv.size() > locator.offset+1) if (lv.size() > locator.offset+1)
{ {
needSize = lv.get(locator.offset+1).getBoolean(); needSize = lv.get(locator.offset+1).getBoolean();
} }
} }
if (structure != null) else
{ {
StructureStart<?> start = FeatureGenerator.shouldStructureStartAt(world, pos, structure, needSize); structure.addAll(reg.entrySet().stream().map(Map.Entry::getValue).toList());
}
if (singleOutput)
{
StructureStart start = FeatureGenerator.shouldStructureStartAt(world, pos, structure.get(0), needSize);
if (start == null) return Value.NULL; if (start == null) return Value.NULL;
if (!needSize) return Value.TRUE; if (!needSize) return Value.TRUE;
return ValueConversions.of(start); return ValueConversions.of(start);
} }
Map<Value, Value> ret = new HashMap<>(); Map<Value, Value> ret = new HashMap<>();
for(StructureFeature<?> str : StructureFeature.STRUCTURES_REGISTRY.values()) for(ConfiguredStructureFeature<?, ?> str: structure)
{ {
StructureStart<?> start; StructureStart start;
try try
{ {
start = FeatureGenerator.shouldStructureStartAt(world, pos, str, needSize); start = FeatureGenerator.shouldStructureStartAt(world, pos, str, needSize);
} }
catch (NullPointerException npe) catch (NullPointerException npe)
{ {
CarpetSettings.LOG.error("Failed to detect structure: "+str.getFeatureName()); CarpetSettings.LOG.error("Failed to detect structure: "+ reg.getKey(str));
start = null; start = null;
} }
if (start == null) continue; if (start == null) continue;
Value key = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_FEATURE.getKey(str))); Value key = new StringValue(NBTSerializableValue.nameFromRegistryId(reg.getKey(str)));
ret.put(key, (!needSize)?Value.NULL: ValueConversions.of(start)); ret.put(key, (!needSize)?Value.NULL: ValueConversions.of(start));
} }
return MapValue.wrap(ret); return MapValue.wrap(ret);
@@ -1368,25 +1392,26 @@ public class WorldAccess {
ServerLevel world = cc.s.getLevel(); ServerLevel world = cc.s.getLevel();
BlockPos pos = locator.block.getPos(); BlockPos pos = locator.block.getPos();
Map<StructureFeature<?>, StructureStart<?>> structures = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_STARTS).getAllStarts(); Map<ConfiguredStructureFeature<?,?>, StructureStart> structures = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_STARTS).getAllStarts();
Registry<ConfiguredStructureFeature<?, ?>> reg = cc.s.getServer().registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
if (lv.size() == locator.offset) if (lv.size() == locator.offset)
{ {
Map<Value, Value> structureList = new HashMap<>(); Map<Value, Value> structureList = new HashMap<>();
for (Map.Entry<StructureFeature<?>, StructureStart<?>> entry : structures.entrySet()) for (Map.Entry<ConfiguredStructureFeature<?, ?>, StructureStart> entry : structures.entrySet())
{ {
StructureStart<?> start = entry.getValue(); StructureStart start = entry.getValue();
if (start == StructureStart.INVALID_START) if (start == StructureStart.INVALID_START)
continue; continue;
BoundingBox box = start.getBoundingBox(); BoundingBox box = start.getBoundingBox();
structureList.put( structureList.put(
new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_FEATURE.getKey(entry.getKey()))), new StringValue(NBTSerializableValue.nameFromRegistryId(reg.getKey(entry.getKey()))),
ListValue.of(ListValue.fromTriple(box.minX(), box.minY(), box.minZ()), ListValue.fromTriple(box.maxX(), box.maxY(), box.maxZ())) ListValue.of(ListValue.fromTriple(box.minX(), box.minY(), box.minZ()), ListValue.fromTriple(box.maxX(), box.maxY(), box.maxZ()))
); );
} }
return MapValue.wrap(structureList); return MapValue.wrap(structureList);
} }
String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT);
return ValueConversions.of(structures.get(Registry.STRUCTURE_FEATURE.get(InputValidator.identifierOf(structureName)))); return ValueConversions.of(structures.get(reg.get(InputValidator.identifierOf(structureName))));
}); });
expression.addContextFunction("set_structure", -1, (c, t, lv) -> expression.addContextFunction("set_structure", -1, (c, t, lv) ->
@@ -1407,11 +1432,10 @@ public class WorldAccess {
// technically a world modification. Even if we could let it slide, we will still park it // technically a world modification. Even if we could let it slide, we will still park it
((CarpetContext) c).s.getServer().executeBlocking(() -> ((CarpetContext) c).s.getServer().executeBlocking(() ->
{ {
Map<StructureFeature<?>, StructureStart<?>> structures = world.getChunk(pos).getAllStarts(); Map<ConfiguredStructureFeature<?, ?>, StructureStart> structures = world.getChunk(pos).getAllStarts();
if (lv.size() == locator.offset + 1) if (lv.size() == locator.offset + 1)
{ {
Boolean res = FeatureGenerator.plopGrid(configuredStructure, ((CarpetContext) c).s.getLevel(), locator.block.getPos()); Boolean res = FeatureGenerator.plopGrid(configuredStructure, ((CarpetContext) c).s.getLevel(), locator.block.getPos());
//Boolean res = FeatureGenerator.gridStructure(structureName, ((CarpetContext) c).s.getWorld(), locator.block.getPos());
if (res == null) return; if (res == null) return;
result[0] = res?Value.TRUE:Value.FALSE; result[0] = res?Value.TRUE:Value.FALSE;
return; return;
@@ -1419,13 +1443,13 @@ public class WorldAccess {
Value newValue = lv.get(locator.offset+1); Value newValue = lv.get(locator.offset+1);
if (newValue.isNull()) // remove structure if (newValue.isNull()) // remove structure
{ {
StructureFeature<?> structure = configuredStructure.feature; ConfiguredStructureFeature<?,?> structure = configuredStructure;
if (!structures.containsKey(structure)) if (!structures.containsKey(structure))
{ {
return; return;
} }
StructureStart<?> start = structures.get(structure); StructureStart start = structures.get(structure);
ChunkPos structureChunkPos = start.getChunkPos(); // new ChunkPos(start.getChunkX(), start.getChunkZ()); ChunkPos structureChunkPos = start.getChunkPos();
BoundingBox box = start.getBoundingBox(); BoundingBox box = start.getBoundingBox();
for (int chx = box.minX() / 16; chx <= box.maxX() / 16; chx++) // minx maxx for (int chx = box.minX() / 16; chx <= box.maxX() / 16; chx++) // minx maxx
{ {
@@ -1433,7 +1457,7 @@ public class WorldAccess {
{ {
ChunkPos chpos = new ChunkPos(chx, chz); ChunkPos chpos = new ChunkPos(chx, chz);
// getting a chunk will convert it to full, allowing to modify references // getting a chunk will convert it to full, allowing to modify references
Map<StructureFeature<?>, LongSet> references = Map<ConfiguredStructureFeature<?,?>, LongSet> references =
world.getChunk(chpos.getWorldPosition()).getAllReferences(); world.getChunk(chpos.getWorldPosition()).getAllReferences();
if (references.containsKey(structure) && references.get(structure) != null) if (references.containsKey(structure) && references.get(structure) != null)
references.get(structure).remove(structureChunkPos.toLong()); references.get(structure).remove(structureChunkPos.toLong());
@@ -16,6 +16,7 @@ import carpet.script.value.StringValue;
import carpet.script.value.Value; import carpet.script.value.Value;
import carpet.script.value.ValueConversions; import carpet.script.value.ValueConversions;
import carpet.utils.CarpetProfiler; import carpet.utils.CarpetProfiler;
import com.mojang.datafixers.util.Either;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
@@ -72,6 +73,7 @@ import net.minecraft.commands.arguments.ObjectiveCriteriaArgument;
import net.minecraft.commands.arguments.ParticleArgument; import net.minecraft.commands.arguments.ParticleArgument;
import net.minecraft.commands.arguments.RangeArgument; import net.minecraft.commands.arguments.RangeArgument;
import net.minecraft.commands.arguments.ResourceLocationArgument; import net.minecraft.commands.arguments.ResourceLocationArgument;
import net.minecraft.commands.arguments.ResourceOrTagLocationArgument;
import net.minecraft.commands.arguments.ScoreHolderArgument; import net.minecraft.commands.arguments.ScoreHolderArgument;
import net.minecraft.commands.arguments.ScoreboardSlotArgument; import net.minecraft.commands.arguments.ScoreboardSlotArgument;
import net.minecraft.commands.arguments.TeamArgument; import net.minecraft.commands.arguments.TeamArgument;
@@ -91,9 +93,12 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.commands.BossBarCommands; import net.minecraft.server.commands.BossBarCommands;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec2;
import net.minecraft.world.scores.Scoreboard; import net.minecraft.world.scores.Scoreboard;
@@ -209,8 +214,20 @@ public abstract class CommandArgument
new VanillaUnconfigurableArgument("boss", ResourceLocationArgument::id, new VanillaUnconfigurableArgument("boss", ResourceLocationArgument::id,
(c, p) -> ValueConversions.of( ResourceLocationArgument.getId(c, p)), BossBarCommands.SUGGEST_BOSS_BAR (c, p) -> ValueConversions.of( ResourceLocationArgument.getId(c, p)), BossBarCommands.SUGGEST_BOSS_BAR
), ),
new VanillaUnconfigurableArgument("biome", ResourceLocationArgument::id, new VanillaUnconfigurableArgument("biome", () -> ResourceOrTagLocationArgument.resourceOrTag(Registry.BIOME_REGISTRY),
(c, p) -> ValueConversions.of( ResourceLocationArgument.getId(c, p)), SuggestionProviders.AVAILABLE_BIOMES (c, p) -> {
ResourceOrTagLocationArgument.Result<Biome> result = ResourceOrTagLocationArgument.getBiome(c, p);
Either<ResourceKey<Biome>, TagKey<Biome>> res = result.unwrap();
if (res.left().isPresent())
{
return ValueConversions.of(res.left().get());
}
if (res.right().isPresent())
{
return ValueConversions.of(res.right().get());
}
return Value.NULL;
}, (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).keySet(), builder)
), ),
new VanillaUnconfigurableArgument("sound", ResourceLocationArgument::id, new VanillaUnconfigurableArgument("sound", ResourceLocationArgument::id,
(c, p) -> ValueConversions.of( ResourceLocationArgument.getId(c, p)), SuggestionProviders.AVAILABLE_SOUNDS (c, p) -> ValueConversions.of( ResourceLocationArgument.getId(c, p)), SuggestionProviders.AVAILABLE_SOUNDS
@@ -115,8 +115,8 @@ public class WorldTools
//}); //});
chunkGenerator2 = new NoiseBasedChunkGenerator( chunkGenerator2 = new NoiseBasedChunkGenerator(
server.registryAccess().registryOrThrow(Registry.STRUCTURE_SET_REGISTRY),
server.registryAccess().registryOrThrow(Registry.NOISE_REGISTRY), server.registryAccess().registryOrThrow(Registry.NOISE_REGISTRY),
server.registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY),
MultiNoiseBiomeSource.Preset.OVERWORLD.biomeSource(server.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY)), seed, MultiNoiseBiomeSource.Preset.OVERWORLD.biomeSource(server.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY)), seed,
Holder.direct(server.registryAccess().registryOrThrow(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY).getOrThrow(NoiseGeneratorSettings.OVERWORLD)) Holder.direct(server.registryAccess().registryOrThrow(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY).getOrThrow(NoiseGeneratorSettings.OVERWORLD))
); );
@@ -314,7 +314,7 @@ public class ValueConversions
); );
} }
public static Value of(StructureStart<?> structure) public static Value of(StructureStart structure)
{ {
if (structure == null || structure == StructureStart.INVALID_START) return Value.NULL; if (structure == null || structure == StructureStart.INVALID_START) return Value.NULL;
BoundingBox boundingBox = structure.getBoundingBox(); BoundingBox boundingBox = structure.getBoundingBox();
@@ -44,7 +44,7 @@ __config() ->
'clear' -> 'clear', 'clear' -> 'clear',
}, },
'arguments' -> { 'arguments' -> {
'structure' -> {'type' -> 'term', 'suggest' -> plop():'structures' }, 'structure' -> {'type' -> 'term', 'suggest' -> plop():'configured_structures' },
'radius' -> {'type' -> 'int', 'min' -> 0, 'max' -> 1024, 'suggest' -> [128, 24, 32]}, 'radius' -> {'type' -> 'int', 'min' -> 0, 'max' -> 1024, 'suggest' -> [128, 24, 32]},
'shape' -> {'type' -> 'term', 'options' -> keys(global_shapes) }, 'shape' -> {'type' -> 'term', 'options' -> keys(global_shapes) },
'color' -> {'type' -> 'teamcolor'} 'color' -> {'type' -> 'teamcolor'}
+1 -2
View File
@@ -81,7 +81,6 @@
"LiquidBlock_renewableBlackstoneMixin", "LiquidBlock_renewableBlackstoneMixin",
"LiquidBlock_renewableDeepslateMixin", "LiquidBlock_renewableDeepslateMixin",
"LavaFluid_renewableDeepslateMixin", "LavaFluid_renewableDeepslateMixin",
"StructureFeatureMixin",
"Level_scarpetPlopMixin", "Level_scarpetPlopMixin",
"WorldGenRegion_scarpetPlopMixin", "WorldGenRegion_scarpetPlopMixin",
"StructurePiece_scarpetPlopMixin", "StructurePiece_scarpetPlopMixin",
@@ -96,7 +95,7 @@
"ChunkGenerator_scarpetMixin", "ChunkGenerator_scarpetMixin",
"Guardian_renewableSpongesMixin", "Guardian_renewableSpongesMixin",
"Husk_templesMixin", "Husk_templesMixin",
"NoiseBasedChunkGenerator_husksSpawnMixin", "ChunkGenerator_customMobSpawnsMixin",
"ServerChunkCacheMixin", "ServerChunkCacheMixin",
"NaturalSpawnerMixin", "NaturalSpawnerMixin",