package net.Chipperfluff.chipi.entity; import net.fabricmc.fabric.api.biome.v1.BiomeModifications; import net.fabricmc.fabric.api.biome.v1.BiomeSelectors; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.EntityType; import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.SpawnReason; import net.minecraft.entity.SpawnRestriction; import net.minecraft.entity.mob.MobEntity; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKeys; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.random.Random; import net.minecraft.world.Heightmap; import net.minecraft.world.ServerWorldAccess; import net.minecraft.world.biome.Biome; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.Box; public final class SpawnLogic { private static final int MAX_MEPS = 60; private static final int SPAWN_RADIUS = 150; private static final RegistryKey VOID_BIOME = RegistryKey.of(RegistryKeys.BIOME, new Identifier("chipi", "void")); private SpawnLogic() { } public static void register() { BiomeModifications.addSpawn( BiomeSelectors.includeByKey(VOID_BIOME), SpawnGroup.MONSTER, ModEntities.MEP, 1, 1, 4 ); SpawnRestriction.register( ModEntities.MEP, SpawnRestriction.Location.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, SpawnLogic::canSpawn ); } private static boolean canSpawn( EntityType type, ServerWorldAccess world, SpawnReason reason, BlockPos pos, Random random ) { // --- HEIGHT & Z RULES --- int y = pos.getY(); if (y < 87 || y > 90) return false; if (pos.getZ() < 18) return false; // --- BLOCK CHECK --- BlockState below = world.getBlockState(pos.down()); if (!below.isOf(Blocks.POLISHED_BLACKSTONE_BRICKS)) return false; // --- GLOBAL CAP (DENY SPAWN, DO NOT DESPAWN) --- int mepCount = world.getEntitiesByClass( MepEntity.class, new Box( pos.getX() - 512, pos.getY() - 512, pos.getZ() - 512, pos.getX() + 512, pos.getY() + 512, pos.getZ() + 512 ), e -> true ).size(); if (mepCount >= MAX_MEPS) return false; // --- PLAYER PROXIMITY --- double maxSq = SPAWN_RADIUS * SPAWN_RADIUS; for (PlayerEntity player : world.getPlayers()) { if (player.squaredDistanceTo( pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5 ) <= maxSq) { return true; // ✔ valid spawn } } // No nearby player → no spawn return false; } }