Jump to content

1.8.1 How to get blocks from chunk


yeetsche420

Recommended Posts

I'm trying to check the blocks of nearby chunks in the spawn predicate of a mob I'm making. Currently, the predicate looks something like this:

 public static boolean checkMyMobSpawnRules(EntityType<? extends MyMob> entityType, ServerLevelAccessor serverLevelAccessor, MobSpawnType mobSpawnType, BlockPos blockPos, Random random) {
   ServerLevel level = serverLevelAccessor.getLevel();
   LevelChunk chunkAtPos = level.getChunkAt(blockPos);
   List<Block> blocks = chunkAtPos.getBlockEntities().values().stream().map(entity -> entity.getBlockState().getBlock()).toList();
   // Do stuff with blocks
 }

When I debug this code, I I noticed that chunkAtPos.getBlockEntities() returns a List with size 0. Since my predicate involves checking nearby blocks, this causes my predicate to always return false. Is there a better way to get the blocks in a chunk?

Link to comment
Share on other sites

It's in a subclass of Monster. I pass a reference to this method to SpawnPlacements.register, which gets called in an event subscriber like the following:

@Mod.EventBusSubscriber(modid = Main.MOD_ID, bus = Bus.MOD)
public class ModEvents {
    private ModEvents() {
    }

    @SubscribeEvent
    public static void commonSetup(FMLCommonSetupEvent event) {
        event.enqueueWork(() -> SpawnPlacements.register(ModEntities.MY_MOB.get(), SpawnPlacements.Type.ON_GROUND, Heightmap.Types.WORLD_SURFACE, MyMob::checkMyMobSpawnRules));
    }
}

 

Link to comment
Share on other sites

I figure I may as well give the whole spawn predicate:

public static boolean checkMyMobSpawnRules(EntityType<? extends MyMob> entityType, ServerLevelAccessor serverLevelAccessor, MobSpawnType mobSpawnType, BlockPos blockPos, Random random) {
        ServerLevel level = serverLevelAccessor.getLevel();
        LevelChunk chunkAtPos = level.getChunkAt(blockPos);

	// check 5x5 grid of chunks for crops, centered at chunkAtPos
        boolean nearbyChunkHasCrop = Stream.of(
                Utils.getBlocksFromChunk(chunkAtPos),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.east(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.west(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.north(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.south(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.east(16).north(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.east(16).south(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.west(16).north(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.west(16).south(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.north(32))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.north(32).east(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.north(32).east(32))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.north(32).west(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.north(32).west(32))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.south(32))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.south(32).east(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.south(32).east(32))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.south(32).west(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.south(32).west(32))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.east(32))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.east(32).north(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.east(32).south(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.west(32))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.west(32).north(16))),
                Utils.getBlocksFromChunk(level.getChunkAt(blockPos.west(32).south(16)))
        ).flatMap(stream -> stream).anyMatch(block -> block instanceof CropBlock);

        boolean notUndergroundOrIndoors = true;
        for (int y = blockPos.getY() + 1; y < 320; ++y) {
            BlockEntity blockEntity = chunkAtPos.getBlockEntity(new BlockPos(blockPos.getX(), y, blockPos.getZ()));
            if (blockEntity != null) {
                Block block = blockEntity.getBlockState().getBlock();
                if (!(block instanceof AirBlock || block instanceof LeavesBlock)) {
                    notUndergroundOrIndoors = false;
                    break;
                }
            }
        }

        return Monster.checkAnyLightMonsterSpawnRules(entityType, serverLevelAccessor, mobSpawnType, blockPos, random) && notUndergroundOrIndoors && nearbyChunkHasCrop;
    }

The Utils function that gets called is the following:

public static Stream<Block> getBlocksFromChunk(LevelChunk chunk) {
        return chunk.getBlockEntities().values().stream().map(entity -> entity.getBlockState().getBlock());
    }

 

Edited by yeetsche420
Link to comment
Share on other sites

I figured it out. I'll post what I did in case anyone else is doing something similar to what I'm doing. My predicate code is the same with the exception that chunks are retrieved with serverLevelAccessor.getChunk instead of level.getChunkAt. My utility function for getting the blocks from a chunk is the following:

public static Stream<Block> getBlocksFromChunk(ChunkAccess chunk) {
    if (chunk instanceof LevelChunk levelChunk) {
      List<Block> blocks = new ArrayList<>();
      Arrays.stream(levelChunk.getSections()).forEach(section -> section.getStates().getAll(blockState -> blocks.add(blockState.getBlock())));
      return blocks.stream();
    }
    else {
      return Stream.empty();
    }
}

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.