100 lines
2.9 KiB
Java

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<Biome> 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<? extends MobEntity> 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;
}
}