Merge branch 'clamp-structure-height' into '1.8.0'

Allow Slippy to define a range in which the structure will spawn

See merge request cable-mc/cobblemon!2185
This commit is contained in:
Polymeta
2026-03-25 23:20:08 +00:00
2 changed files with 40 additions and 26 deletions
+1
View File
@@ -19,6 +19,7 @@
### Fixes
- Fixed rare Pokémon being far too likely to spawn multiple times in a single spawn cycle. The dev told me that the exact bug is too complicated to explain.
- Resolved the niche issue where Structures would spawn in an incorrect location, creating very funky world gen.
### Developer
- Tweaked the spawning selector interface to take a bucket function rather than a bucket directly.
@@ -24,6 +24,7 @@ import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.StructurePiece;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.apache.commons.lang3.IntegerRange;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@@ -32,36 +33,48 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
@Mixin(Structure.class)
public abstract class StructureMixin {
// Define a set of structures that should not spawn below Sea Level
@Unique
private static final Set<ResourceLocation> RESTRICTED_STRUCTURES = new HashSet<>(Arrays.asList(
CobblemonStructureIDs.STONJOURNER_HENGE,
CobblemonStructureIDs.LUNA_HENGE,
CobblemonStructureIDs.SOL_HENGE
));
// Define a set of structures that should not spawn below Sea Level
@Unique
private static final Map<ResourceLocation, IntegerRange> RESTRICTED_STRUCTURES = Map.of(
// The IntegerRange values are calculated FROM Sea Level. (Sealevel + VALUE)
CobblemonStructureIDs.STONJOURNER_HENGE, IntegerRange.of(0, 50),
CobblemonStructureIDs.LUNA_HENGE, IntegerRange.of(0, 50),
CobblemonStructureIDs.SOL_HENGE, IntegerRange.of(0, 50)
);
@Inject(method = "generate", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/structure/StructureStart;isValid()Z"),
cancellable = true)
public void cobblemon$isValid(RegistryAccess registryAccess, ChunkGenerator chunkGenerator, BiomeSource biomeSource,
RandomState randomState, StructureTemplateManager structureTemplateManager, long seed,
ChunkPos chunkPos, int references, LevelHeightAccessor heightAccessor,
Predicate<Holder<Biome>> validBiome,
CallbackInfoReturnable<StructureStart> cir,
@Local StructureStart structureStart) {
ResourceLocation structureKey = registryAccess.registryOrThrow(Registries.STRUCTURE).getKey((Structure) (Object) this);
if(!RESTRICTED_STRUCTURES.contains(structureKey)) {
return;
}
for (StructurePiece piece : structureStart.getPieces()) {
if (piece.getBoundingBox().minY() < chunkGenerator.getSeaLevel()) {
cir.setReturnValue(StructureStart.INVALID_START);
return;
}
}
}
@Inject(method = "generate", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/structure/StructureStart;isValid()Z"),
cancellable = true)
public void cobblemon$isValid(RegistryAccess registryAccess, ChunkGenerator chunkGenerator, BiomeSource biomeSource,
RandomState randomState, StructureTemplateManager structureTemplateManager, long seed,
ChunkPos chunkPos, int references, LevelHeightAccessor heightAccessor,
Predicate<Holder<Biome>> validBiome,
CallbackInfoReturnable<StructureStart> cir,
@Local StructureStart structureStart) {
ResourceLocation structureKey = registryAccess.registryOrThrow(Registries.STRUCTURE).getKey((Structure) (Object) this);
if (!RESTRICTED_STRUCTURES.containsKey(structureKey)) {
return;
}
int sealevel = chunkGenerator.getSeaLevel();
IntegerRange range = RESTRICTED_STRUCTURES.get(structureKey);
if (range != null) {
int minY = sealevel + range.getMinimum();
int maxY = sealevel + range.getMaximum();
for (StructurePiece piece : structureStart.getPieces()) {
int pieceMinY = piece.getBoundingBox().minY();
if (pieceMinY < minY || pieceMinY > maxY) {
cir.setReturnValue(StructureStart.INVALID_START);
return;
}
}
}
}
}