Skip to content

WorldScanner ​

com.jsmacrosce.jsmacros.client.api.classes.worldscanner.WorldScanner

Since1.6.5

Scans chunks and block-coordinate regions for blocks matching optional block and state filters.
Filter results are cached per block state and reused by later scans on the same scanner. Scans skip chunks unavailable to the client and do not request them from the server.

There are three kinds of search and they differ in the units they take. The chunk searches take a centre in chunk coordinates, the area searches take block coordinates, and the reach searches take a point and a distance. A chunk coordinate is the block coordinate divided by sixteen, and the parameter names say which of the two a method is expecting.

js
// reuse a scanner so matching states already evaluated are not tested again
const scanner = World.getWorldScanner(
 JavaWrapper.methodToJava(function (block) {
   return block.getId() === "minecraft:diamond_ore";  
 }),  
 null
);  
if (scanner !== null) {
 // every position in the nine chunks around the player
 const found = scanner.scanAroundPlayer(1);  
 Chat.log(`${found.size()} diamond ore, from ${scanner.getCachedAmount()} states tested`);  

 // the same scanner, asking for counts rather than positions
 const counts = scanner.getBlocksInChunks(0, 0, 0, true);  
 Chat.log(`${counts.size()} kinds of block in the chunk at the origin`);  
}

Constructors ​

new WorldScanner ​

new WorldScanner(Level world, Function<BlockHelper, Boolean> blockFilter, Function<BlockStateHelper, Boolean> stateFilter)#
Constructs a scanner for world. Non-null block and state filters are both applied; the block filter runs first, and either may be null to omit that test. With both null, every encountered state matches. Scans may use parallel streams unless a wrapped script filter's context is not multithreaded; this choice is made when the scanner is constructed.
// naming the parameter type is what tells the wrapper what it is being
// handed. The two are stages: a block is kept when the block filter and
// the state filter both accept it
const scanner = World.getWorldScanner(
  JavaWrapper.methodToJava(function (block: BlockHelper) {
    return block.getId() !== "minecraft:dirt";
  }),
  JavaWrapper.methodToJava(function (state: BlockStateHelper) {
    return state.isSolid();
  })
);
if (scanner !== null) {
  Chat.log(`${scanner.scanAroundPlayer(2).size()} blocks matched`);
}

Parameters:

  • world: the world to scan
  • blockFilter: a filter method for the blocks, or null to keep all of them
  • stateFilter: a filter method for the block states, or null to keep all of those

Methods ​

getBlocksInChunk ​

getBlocksInChunk(int chunkX, int chunkZ, boolean ignoreState): Map<String, Integer>#
Gets the amount of all blocks matching the criteria inside the chunk. Keys are Minecraft block/state strings: ignoreState uses the block string, while false uses the state string including its properties. Counts cover the chunk's full height. Chunks not available to the client are skipped.
// a count of the ores in one chunk. The centre here is a chunk
// coordinate, not a block one, so 0 is the chunk at the origin rather
// than the block at 0, 0
const scanner = World.getWorldScanner(
  JavaWrapper.methodToJava(function (block: BlockHelper) {
    return block.getId().endsWith("_ore");
  }),
  null
);
if (scanner !== null) {
  const counts = scanner.getBlocksInChunk(0, 0, true);
  for (const key of counts.keySet()) {
    Chat.log(`${key}: ${counts.get(key)}`);
  }
}

Parameters:

  • chunkX: the x coordinate of the chunk to scan
  • chunkZ: the z coordinate of the chunk to scan
  • ignoreState: whether multiple states should be combined to a single block
Returns: a map of all blocks inside the specified chunk and their respective count.

getBlocksInChunks ​

getBlocksInChunks(int centerX, int centerZ, int chunkRange, boolean ignoreState): Map<String, Integer>#
Gets the amount of all blocks matching the criteria inside a square of chunks around the given centre chunk. Scans the square from centerX - chunkRange through centerX + chunkRange and likewise for Z. Keys follow getBlocksInChunk(int, int, boolean); counts from all available chunks are added together, and unavailable chunks are skipped.
// a count of the ores in the nine chunks around a chunk. The key
// comes from the block itself and has nothing to do with how the
// filter was built, so the filter's form is not what is shown here
const scanner = World.getWorldScanner(
  JavaWrapper.methodToJava(function (block: BlockHelper) {
    return block.getId().endsWith("_ore");
  }),
  null
);
if (scanner !== null) {
  const counts = scanner.getBlocksInChunks(0, 0, 1, true);
  Chat.log(`${counts.size()} kinds of ore in the nine chunks`);
}

Parameters:

  • centerX: the x coordinate of the center chunk to scan around
  • centerZ: the z coordinate of the center chunk to scan around
  • chunkRange: non-negative radius in chunks; zero scans only the center chunk
  • ignoreState: whether multiple states should be combined to a single block
Returns: a map of all blocks inside the specified chunks and their respective count.

getCachedAmount ​

getCachedAmount(): int#
Returns the number of distinct block states cached after filter evaluation. A state is evaluated at most once per scanner; this is not a count of scanned blocks.
Returns: the number of cached block states

getChunkRange ​

getChunkRange(int centerX, int centerZ, int chunkrange): List<ChunkPos>#
Returns the square of chunk positions centered on the given chunk coordinates, without checking whether those chunks are available. The side length is 2 * chunkrange + 1; positions are ordered by ascending X, then ascending Z.
// the nine chunks around a chunk, as chunk positions rather than
// block ones, which is what the scan methods take
const scanner = World.getWorldScanner(
  JavaWrapper.methodToJava(function (block: BlockHelper) { return true; }),
  null
);
if (scanner !== null) {
  const chunks = scanner.getChunkRange(0, 0, 1);
  Chat.log(`${chunks.size()} chunks`);
}

Parameters:

  • centerX: the x coordinate of the center chunk to scan around
  • centerZ: the z coordinate of the center chunk to scan around
  • chunkrange: the range to scan around the center chunk
Returns: a list of the chunk positions in the square, which is 2 * chunkrange + 1 squared entries

scanAroundPlayer ​

scanAroundPlayer(int chunkRange): List<Pos3D>#
Scans the square of chunks centered on the player's current chunk, returning matching block positions across each chunk's full height. The side length is 2 * chunkRange + 1; returns an empty list when there is no player. Unavailable chunks are skipped.

Parameters:

  • chunkRange: the range to scan around the center chunk
Returns: a list of all matching block positions.

scanChunkRange ​

scanChunkRange(int centerX, int centerZ, int chunkrange): List<Pos3D>#
Scans the square of chunks centered on the supplied chunk coordinates and returns matching positions across their full height. The side length is 2 * chunkrange + 1; unavailable chunks are skipped.

Parameters:

  • centerX: the x coordinate of the center chunk to scan around
  • centerZ: the z coordinate of the center chunk to scan around
  • chunkrange: the range to scan around the center chunk
Returns: a list of all matching block positions.

scanClosestReachable ​

scanClosestReachable(): Pos3DSince1.9.1#
Returns the nearest matching block within the player's block interaction range, measured from the player's eyes; obstructions are not considered. Uses the strict shape check and ranks candidates by distance to their block positions, not their centres.
// the nearest block of one kind the player could reach, or null when
// there is none, which is why the result is checked rather than read
const scanner = World.getWorldScanner(
  JavaWrapper.methodToJava(function (block: BlockHelper) {
    return block.getId() === "minecraft:chest";
  }),
  null
);
if (scanner !== null) {
  const nearest = scanner.scanClosestReachable();
  if (nearest !== null) {
    Chat.log(`nearest chest at ${nearest.getX()}, ${nearest.getY()}, ${nearest.getZ()}`);
  } else {
    Chat.log("no chest in reach");
  }
}
Returns: the nearest matching block within reach of the player's eyes, or null if there is none or there is no player
scanClosestReachable(boolean strict): Pos3DSince1.9.1#
Returns the nearest matching block within the player's block interaction range, measured from the player's eyes; obstructions are not considered. With strict false, reach and ranking use unit block boxes rather than block shapes.
// the nearest by bounding box rather than by shape, which is the
// looser of the two and so can name a block out of touch
const scanner = World.getWorldScanner(
  JavaWrapper.methodToJava(function (block: BlockHelper) {
    return block.getId() === "minecraft:torch";
  }),
  null
);
if (scanner !== null) {
  const nearest = scanner.scanClosestReachable(false);
  if (nearest !== null) {
    Chat.log(`nearest torch at ${nearest.getX()}, ${nearest.getY()}, ${nearest.getZ()}`);
  }
}

Parameters:

  • strict: whether reach should also be checked against the block's shape
Returns: the nearest matching block within reach of the player's eyes, or null if there is none or there is no player
scanClosestReachable(Pos3D pos, double reach, boolean strict): Pos3DSince1.9.1#
Returns the nearest matching block within reach of pos; obstructions are not considered. Reach is measured to unit block boxes, and with strict true the block's shape must also be within reach. Candidates are ranked by distance from pos shifted by (-0.5, -0.5, -0.5) to their block positions.
// the full form, from a fixed point with a reach of the script's own
// choosing and the shape check turned off
const scanner = World.getWorldScanner(
  JavaWrapper.methodToJava(function (block: BlockHelper) {
    return block.getId() === "minecraft:chest";
  }),
  null
);
if (scanner !== null) {
  const from = PositionCommon.createPos(0.5, 64, 0.5);
  const nearest = scanner.scanClosestReachable(from, 6.0, false);
  if (nearest !== null) {
    Chat.log(`nearest chest at ${nearest.getX()}, ${nearest.getY()}, ${nearest.getZ()}`);
  }
}

Parameters:

  • pos: the point to search from
  • reach: maximum distance in blocks from pos
  • strict: whether to require the block's shape to be within reach
Returns: the nearest matching block within reach of pos, or null if there is none

scanCubeArea ​

scanCubeArea(BlockPosHelper pos, int range): List<Pos3D>Since1.9.1#
Scans a block-coordinate cube centered on pos, including both ends on each axis. Its side length is 2 * range + 1; the Y bounds are clamped to world height, and a cube entirely outside that height is empty.
// the 3x3x3 cube around a block position, both ends counted
const scanner = World.getWorldScanner(
  JavaWrapper.methodToJava(function (block: BlockHelper) {
    return block.getId() === "minecraft:chest";
  }),
  null
);
if (scanner !== null) {
  const centre = PositionCommon.createBlockPos(100, 64, 100);
  const found = scanner.scanCubeArea(centre, 1);
  Chat.log(`${found.size()} chests in the cube`);
}

Parameters:

  • pos: the centre of the cube
  • range: how many blocks out from the centre to go on each axis
Returns: the positions of every matching block in the cube
scanCubeArea(int x, int y, int z, int range): List<Pos3D>Since1.9.1#
Scans a cube centred on the supplied block coordinates, including both ends on each axis. Its side length is 2 * range + 1; the y range is clamped to the world height.

Parameters:

  • x: the x coordinate of the centre of the cube
  • y: the y coordinate of the centre of the cube
  • z: the z coordinate of the centre of the cube
  • range: how many blocks out from the centre to go on each axis
Returns: the positions of every matching block in the cube
scanCubeArea(BlockPosHelper pos1, BlockPosHelper pos2): List<Pos3D>Since1.9.1#
Scans the box from the first position, inclusive, to the second, exclusive. An equal pair of coordinates on any axis makes the result empty; the y range is clamped to world height.

Parameters:

  • pos1: first pos, inclusive
  • pos2: second pos, exclusive
Returns: the positions of every matching block in the box, which is empty if any of the three axes has the same value at both ends
scanCubeArea(int x1, int y1, int z1, int x2, int y2, int z2): List<Pos3D>Since1.9.1#
Scans the box from the first coordinate triple, inclusive, to the second, exclusive. Equal coordinates on any axis make the result empty; the y range is clamped to world height.

Parameters:

  • x1: first x coordinate, inclusive
  • y1: first y coordinate, inclusive
  • z1: first z coordinate, inclusive
  • x2: second x coordinate, exclusive
  • y2: second y coordinate, exclusive
  • z2: second z coordinate, exclusive
Returns: the positions of every matching block in the box, which is empty if any of the three axes has the same value at both ends

scanCubeAreaInclusive ​

scanCubeAreaInclusive(BlockPosHelper pos1, BlockPosHelper pos2): List<Pos3D>Since1.9.1#
Scans the box including both positions on every axis. Equal coordinates describe one block; the y range is clamped to world height. Unlike scanCubeArea(BlockPosHelper, BlockPosHelper), the second position is included.

Parameters:

  • pos1: first pos, inclusive
  • pos2: second pos, inclusive
Returns: the positions of every matching block in the box
scanCubeAreaInclusive(int x1, int y1, int z1, int x2, int y2, int z2): List<Pos3D>Since1.9.1#
Scans the box including both coordinate triples on every axis; the y range is clamped to world height. Unlike scanCubeArea(int, int, int, int, int, int), the second triple is included.

Parameters:

  • x1: first x coordinate, inclusive
  • y1: first y coordinate, inclusive
  • z1: first z coordinate, inclusive
  • x2: second x coordinate, inclusive
  • y2: second y coordinate, inclusive
  • z2: second z coordinate, inclusive
Returns: the positions of every matching block in the box

scanReachable ​

scanReachable(): List<Pos3D>Since1.9.1#
Scans from the player's eye position using the client's block-interaction reach and the strict shape check. Obstructions are not considered; with no player, returns an empty list.
Returns: matching block positions, or an empty list when there is no player
scanReachable(boolean strict): List<Pos3D>Since1.9.1#
Scans from the player's eye position using the client's block-interaction reach. Obstructions are not considered; with no player, returns an empty list. With strict true, the block's shape must be within reach; otherwise its unit block box is tested instead.

Parameters:

  • strict: whether to require the block's shape to be within reach; false tests its unit block box
Returns: matching block positions, or an empty list when there is no player
scanReachable(Pos3D pos): List<Pos3D>Since1.9.1#
Scans from pos using the player's block-interaction reach (4.5 when there is no player) and the strict shape check. Obstructions are not considered.

Parameters:

  • pos: the point to search from
Returns: matching positions whose unit block boxes, and in strict mode shapes, are within reach of pos
scanReachable(Pos3D pos, double reach): List<Pos3D>Since1.9.1#
Scans from pos using the supplied reach and strict shape check. Obstructions are not considered; unlike scanReachable(Pos3D), this overload does not obtain reach from the player.

Parameters:

  • pos: the point to search from
  • reach: how far out from pos to go
Returns: matching positions whose unit block boxes and shapes are within reach of pos
scanReachable(Pos3D pos, double reach, boolean strict): List<Pos3D>Since1.9.1#
Scans from pos using reach; obstructions are not considered. Distance is measured to each unit block box, and when strict is true the block's shape must also be within reach. A negative reach throws IllegalArgumentException.

Parameters:

  • pos: the point to search from
  • reach: the maximum distance in blocks
  • strict: whether to require the block's shape to be within reach; false tests its unit block box
Returns: matching positions whose unit block boxes, and in strict mode shapes, are within reach

scanSphereArea ​

scanSphereArea(Pos3D pos, double radius): List<Pos3D>Since1.9.1#
Scans for matching block positions within radius of (pos.x - 0.5, pos.y - 0.5, pos.z - 0.5). Distance is measured to each candidate's integer block position, not its center; the y range is clamped to world height.

Parameters:

  • pos: supplies x, y, and z; distance uses each coordinate minus 0.5
  • radius: how far out to go
Returns: the positions of matching blocks whose block positions are within the radius
scanSphereArea(double x, double y, double z, double radius): List<Pos3D>Since1.9.1#
Scans for matching block positions within radius of (x - 0.5, y - 0.5, z - 0.5). Distance is measured to each candidate's integer block position, not its center; the y range is clamped to world height. This uses the same distance convention as scanSphereArea(Pos3D, double).
// the same sphere written as three numbers and a radius
const scanner = World.getWorldScanner(
  JavaWrapper.methodToJava(function (block: BlockHelper) {
    return block.getId() === "minecraft:coal_ore";
  }),
  null
);
if (scanner !== null) {
  const found = scanner.scanSphereArea(0.5, 64, 0.5, 20);
  Chat.log(`${found.size()} coal ore within 20 blocks`);
}

Parameters:

  • x: x coordinate; the distance origin uses x - 0.5
  • y: y coordinate; the distance origin uses y - 0.5
  • z: z coordinate; the distance origin uses z - 0.5
  • radius: how far out to go
Returns: the positions of matching blocks whose block positions are within the radius