From 53080bea06daddef5d1776be08568ef20770c838 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 26 Nov 2021 16:22:32 +0100 Subject: [PATCH] new `SpawnAPI` --- src/main/java/ru/bclib/api/SpawnAPI.java | 126 +++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 src/main/java/ru/bclib/api/SpawnAPI.java diff --git a/src/main/java/ru/bclib/api/SpawnAPI.java b/src/main/java/ru/bclib/api/SpawnAPI.java new file mode 100644 index 00000000..dff43bdb --- /dev/null +++ b/src/main/java/ru/bclib/api/SpawnAPI.java @@ -0,0 +1,126 @@ +package ru.bclib.api; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.Difficulty; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import ru.bclib.util.BlocksHelper; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + + +public class SpawnAPI { + @FunctionalInterface + public interface SpawnRule { + boolean test(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random); + } + + public interface IsBlock{ + boolean is(BlockState state); + } + + private Class entityClass; + public SpawnAPI(Class entityClass){ + this.entityClass = entityClass; + } + + ArrayList> rules = new ArrayList<>(); + + public SpawnAPI notPeaceful() { + rules.add((type, world, spawnReason, pos, random) -> world.getDifficulty() != Difficulty.PEACEFUL); + return this; + } + + public SpawnAPI notPeacefulBelowBrightness() { + return notPeacefulBelowBrightness(7); + } + + public SpawnAPI notPeacefulBelowBrightness(int bright) { + rules.add((type, world, spawnReason, pos, random) -> world.getDifficulty() != Difficulty.PEACEFUL && world.getMaxLocalRawBrightness(pos) <= bright); + return this; + } + + public SpawnAPI belowBrightness() { + return belowBrightness(7); + } + + public SpawnAPI belowBrightness(int bright) { + rules.add((type, world, spawnReason, pos, random) -> world.getMaxLocalRawBrightness(pos) <= bright); + return this; + } + + public SpawnAPI belowMinHeight() { + rules.add((type, world, spawnReason, pos, random) -> pos.getY() < world.dimensionType().minY()); + return this; + } + + public SpawnAPI maxAlive(){ + return maxAlive(4, 256); + } + + public SpawnAPI maxAlive(int count){ + return maxAlive(count, 256); + } + + public SpawnAPI maxAlive(int count, int size){ + rules.add((type, world, spawnReason, pos, random) -> { + try { + final AABB box = new AABB(pos).inflate(size, 256, size); + final List list = world.getEntitiesOfClass(entityClass, box, (entity) -> true); + return list.size() < count; + } + catch (Exception e) { + return true; + } + }); + return this; + } + + public SpawnAPI maxHeight(int height) { + rules.add((type, world, spawnReason, pos, random) -> { + int h = BlocksHelper.downRay(world, pos, height+1); + return h<=height; + }); + return this; + } + + public SpawnAPI notAboveBlock(IsBlock blockTest, int height) { + rules.add((type, world, spawnReason, pos, random) -> { + int h = BlocksHelper.downRay(world, pos, height+1); + if (h>height) return false; + + for (int i = 1; i <= h; i++) + if (blockTest.is(world.getBlockState(pos.below(i)))) + return false; + + return true; + }); + return this; + } + + public SpawnAPI aboveBlock(IsBlock blockTest, int height) { + rules.add((type, world, spawnReason, pos, random) -> { + int h = BlocksHelper.downRay(world, pos, height+1); + if (h>height) return false; + + for (int i = 1; i <= h; i++) + if (blockTest.is(world.getBlockState(pos.below(i)))) + return true; + + return false; + }); + return this; + } + + public boolean canSpawn(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { + return rules.stream() + .map(r -> r.test(type, world, spawnReason, pos, random)) + .reduce(true, (p, c) -> p && c); + } +}