SpawnUtil.java

net.minecraft.util.SpawnUtil

信息

  • 全限定名:net.minecraft.util.SpawnUtil
  • 类型:public class
  • 包:net.minecraft.util
  • 源码路径:src/main/java/net/minecraft/util/SpawnUtil.java
  • 起始行号:L18
  • 职责:

    TODO

字段/常量

内部类/嵌套类型

  • net.minecraft.util.SpawnUtil.Strategy
    • 类型: interface
    • 修饰符: public
    • 源码定位: L75
    • 说明:

      TODO

构造器

方法

下面的方法块按源码顺序生成。

public static <T extends Mob> Optional<T> trySpawnMob(EntityType<T> entityType, EntitySpawnReason spawnReason, ServerLevel level, BlockPos start, int spawnAttempts, int spawnRangeXZ, int spawnRangeY, SpawnUtil.Strategy strategy, boolean checkCollisions) @ L19

  • 方法名:trySpawnMob
  • 源码定位:L19
  • 返回类型: Optional
  • 修饰符:public static

参数:

  • entityType: EntityType
  • spawnReason: EntitySpawnReason
  • level: ServerLevel
  • start: BlockPos
  • spawnAttempts: int
  • spawnRangeXZ: int
  • spawnRangeY: int
  • strategy: SpawnUtil.Strategy
  • checkCollisions: boolean

说明:

TODO

private static boolean moveToPossibleSpawnPosition(ServerLevel level, int spawnRangeY, BlockPos.MutableBlockPos searchPos, SpawnUtil.Strategy strategy) @ L56

  • 方法名:moveToPossibleSpawnPosition
  • 源码定位:L56
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • level: ServerLevel
  • spawnRangeY: int
  • searchPos: BlockPos.MutableBlockPos
  • strategy: SpawnUtil.Strategy

说明:

TODO

代码

public class SpawnUtil {
    public static <T extends Mob> Optional<T> trySpawnMob(
        EntityType<T> entityType,
        EntitySpawnReason spawnReason,
        ServerLevel level,
        BlockPos start,
        int spawnAttempts,
        int spawnRangeXZ,
        int spawnRangeY,
        SpawnUtil.Strategy strategy,
        boolean checkCollisions
    ) {
        BlockPos.MutableBlockPos searchPos = start.mutable();
        RandomSource random = level.getRandom();
 
        for (int i = 0; i < spawnAttempts; i++) {
            int dx = Mth.randomBetweenInclusive(random, -spawnRangeXZ, spawnRangeXZ);
            int dz = Mth.randomBetweenInclusive(random, -spawnRangeXZ, spawnRangeXZ);
            searchPos.setWithOffset(start, dx, spawnRangeY, dz);
            if (level.getWorldBorder().isWithinBounds(searchPos)
                && moveToPossibleSpawnPosition(level, spawnRangeY, searchPos, strategy)
                && (!checkCollisions || level.noCollision(entityType.getSpawnAABB(searchPos.getX() + 0.5, searchPos.getY(), searchPos.getZ() + 0.5)))) {
                T mob = (T)entityType.create(level, null, searchPos, spawnReason, false, false);
                if (mob != null) {
                    if (mob.checkSpawnRules(level, spawnReason) && mob.checkSpawnObstruction(level)) {
                        level.addFreshEntityWithPassengers(mob);
                        mob.playAmbientSound();
                        return Optional.of(mob);
                    }
 
                    mob.discard();
                }
            }
        }
 
        return Optional.empty();
    }
 
    private static boolean moveToPossibleSpawnPosition(ServerLevel level, int spawnRangeY, BlockPos.MutableBlockPos searchPos, SpawnUtil.Strategy strategy) {
        BlockPos.MutableBlockPos abovePos = new BlockPos.MutableBlockPos().set(searchPos);
        BlockState aboveState = level.getBlockState(abovePos);
 
        for (int y = spawnRangeY; y >= -spawnRangeY; y--) {
            searchPos.move(Direction.DOWN);
            abovePos.setWithOffset(searchPos, Direction.UP);
            BlockState currentState = level.getBlockState(searchPos);
            if (strategy.canSpawnOn(level, searchPos, currentState, abovePos, aboveState)) {
                searchPos.move(Direction.UP);
                return true;
            }
 
            aboveState = currentState;
        }
 
        return false;
    }
 
    public interface Strategy {
        @Deprecated
        SpawnUtil.Strategy LEGACY_IRON_GOLEM = (level, pos, blockState, abovePos, aboveState) -> !blockState.is(Blocks.COBWEB)
                && !blockState.is(Blocks.CACTUS)
                && !blockState.is(Blocks.GLASS_PANE)
                && !(blockState.getBlock() instanceof StainedGlassPaneBlock)
                && !(blockState.getBlock() instanceof StainedGlassBlock)
                && !(blockState.getBlock() instanceof LeavesBlock)
                && !blockState.is(Blocks.CONDUIT)
                && !blockState.is(Blocks.ICE)
                && !blockState.is(Blocks.TNT)
                && !blockState.is(Blocks.GLOWSTONE)
                && !blockState.is(Blocks.BEACON)
                && !blockState.is(Blocks.SEA_LANTERN)
                && !blockState.is(Blocks.FROSTED_ICE)
                && !blockState.is(Blocks.TINTED_GLASS)
                && !blockState.is(Blocks.GLASS)
            ? (aboveState.isAir() || aboveState.liquid()) && (blockState.isSolid() || blockState.is(Blocks.POWDER_SNOW))
            : false;
        SpawnUtil.Strategy ON_TOP_OF_COLLIDER = (level, pos, blockState, abovePos, aboveState) -> aboveState.getCollisionShape(level, abovePos).isEmpty()
            && Block.isFaceFull(blockState.getCollisionShape(level, pos), Direction.UP);
        SpawnUtil.Strategy ON_TOP_OF_COLLIDER_NO_LEAVES = (level, pos, blockState, abovePos, aboveState) -> aboveState.getCollisionShape(level, abovePos)
                .isEmpty()
            && !blockState.is(BlockTags.LEAVES)
            && Block.isFaceFull(blockState.getCollisionShape(level, pos), Direction.UP);
 
        boolean canSpawnOn(ServerLevel level, BlockPos pos, BlockState blockState, BlockPos abovePos, BlockState aboveState);
    }
}

引用的其他类

  • BlockPos

    • 引用位置: 参数/方法调用/构造调用
    • 关联成员: BlockPos.MutableBlockPos(), MutableBlockPos()
  • ServerLevel

    • 引用位置: 参数
  • Mth

    • 引用位置: 方法调用
    • 关联成员: Mth.randomBetweenInclusive()
  • EntitySpawnReason

    • 引用位置: 参数
  • EntityType

    • 引用位置: 参数
  • Mob

    • 引用位置: 返回值
  • Block

    • 引用位置: 方法调用
    • 关联成员: Block.isFaceFull()