private void updateBlocks(Location origin) { Location minimum = origin.clone().subtract(BLOCK_RANGE, BLOCK_RANGE, BLOCK_RANGE); Location maximum = origin.clone().add(BLOCK_RANGE, BLOCK_RANGE, BLOCK_RANGE); Map snapshotList = new HashMap<>(); for (int x = minimum.getBlockX(); x <= maximum.getBlockX() + 16; x+=16) { //The "loop in main" that you told me before, i guess for (int z = minimum.getBlockZ(); z <= maximum.getBlockZ() + 16; z+=16) { snapshotList.put(new ChunkPosition(x 16, z 16), origin.getWorld().getChunkAt(new Location(origin.getWorld(), x, 1, z)).getChunkSnapshot()); //gets all the blocks that have to be analyzed and put in a HashMap } } Vector originVector = origin.toVector(); //idk what a vector is for(ChunkPosition chunkPosition : snapshotList.keySet()) { //Divides the work in chunks ChunkSnapshot snapshot = snapshotList.get(chunkPosition); new Thread(() -> { for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { for (int y = (int) (origin.getY() - BLOCK_RANGE); y < origin.getY() + BLOCK_RANGE; y++) { //its gets every block in y and then it goes up by one block int realX = chunkPosition.getChunkX() 16 + x; int realZ = chunkPosition.getChunkZ() 16 + z; Vector position = new Vector(realX, y, realZ); //idk what a vector is if (position.distance(originVector) > BLOCK_RANGE) //what continue; Material type = snapshot.getBlockType(x % 0xF, y, z % 0xF); if(shouldBreak(type)) //what is it synchronized (blockList) { blockList.add(new Location(origin.getWorld(), chunkPosition.getChunkX() << 4 | x, y, chunkPosition.getChunkZ() << 4 | z)); //add the breakable block to an HashMap } } } } }).start(); } }