Skip to content

Instantly share code, notes, and snippets.

@foxfirecodes
Last active November 26, 2024 14:45
Show Gist options
  • Save foxfirecodes/3225db7a5d5aeb813e85ab66709674d7 to your computer and use it in GitHub Desktop.
Save foxfirecodes/3225db7a5d5aeb813e85ab66709674d7 to your computer and use it in GitHub Desktop.
Search for blocks in a Minecraft world

search_blocks

a small Python script that uses amulet-core to search for specific blocks in a Minecraft world

this was created out of my need to find the exceptionally rare Osmium Ore in the Not Too Complicated 2 modpack

call it cheating if you like, but this is my 3rd playthrough of the pack and quite frankly i have much better things to do than fuck around trying to find a single goddamn vein of this shit.

if you want to use it, the general setup goes like this:

  • install Python 3.10+
  • set up & activate a virtual environment
  • install the required libraries with pip install amulet-core
    • there was a bug with the latest version on Python 3.10 at the time of creating this, so you may instead wish to do pip install git+https://github.com/Amulet-Team/Amulet-Core.git or use the precise version i used with pip install git+https://github.com/Amulet-Team/Amulet-Core.git@e455036b75d82ad255aa2a5bf678680fb67c165c
  • save the above script somewhere
  • copy your world folder to the same folder as the script and rename it to just be world
  • tweak the constants at the top of the file if desired to search in a different dimension or for a different block(s)
  • open your powershell/terminal in said folder and run the script with python search_blocks.py
    • if you want to save the output, you can do python search_blocks.py > found_blocks.txt

feel free to join my discord server if shit doesn't work :)

# Requires: pip install amulet-core
import logging
import sys
from typing import List, Tuple, TypeVar
import amulet
T = TypeVar("T")
WORLD_PATH = "world"
DESIRED_BLOCKS = ["emendatusenigmatica:osmium_end_stone_ore"]
TARGET_DIMENSION = "minecraft:the_end"
def chunk_list(list: List[T], interval=10) -> List[List[T]]:
"""Splits a list into a list of lists, each containing `interval` items"""
return [list[i : i + interval] for i in range(0, len(list), interval)]
def safe_load_chunk(
world: amulet.api.level.World,
dim: amulet.api.data_types.Dimension,
cx: int,
cy: int,
):
"""Attempts to load a chunk from the world, and returns None if it fails"""
try:
return world.get_chunk(cx, cy, dim)
except amulet.api.errors.ChunkLoadError:
pass
def safe_load_chunks(
world: amulet.api.level.World,
dim: amulet.api.data_types.Dimension,
coords: List[Tuple[int, int]],
):
"""Safely loads the chunks with the specified coordinates"""
chunks = [safe_load_chunk(world, dim, cx, cy) for cx, cy in coords]
successful_chunks = [c for c in chunks if c is not None]
return (successful_chunks, len(coords), len(successful_chunks))
def get_non_air_blocks(chunk: amulet.api.chunk.Chunk, height=256):
"""Returns the position & block reference for each position inside a chunk"""
return (
((chunk.cx * 16 + x, y, chunk.cz * 16 + z), chunk.get_block(x, y, z))
for x in range(0, 16)
for y in range(0, height)
for z in range(0, 16)
if chunk.get_block(x, y, z).namespaced_name != "universal_minecraft:air"
)
def search_for_blocks(
world: amulet.api.level.World,
dimension: amulet.api.data_types.Dimension,
target_blocks: List[str],
):
coords = list(world.chunks.all_chunk_coords(dimension))
total_attempted = 0
total_succeeded = 0
for coords_batch in chunk_list(coords, 16):
(chunks, attempted, succeeded) = safe_load_chunks(
world, dimension, coords_batch
)
total_attempted += attempted
blocks = [(p, b) for c in chunks for (p, b) in get_non_air_blocks(c)]
found_blocks = [
(p, b) for (p, b) in blocks if b.namespaced_name in target_blocks
]
if len(found_blocks) != 0:
print("Found {} blocks".format(len(found_blocks)))
print(
"\n".join(
["{} - {}".format(b.namespaced_name, p) for (p, b) in found_blocks]
)
)
total_succeeded += succeeded
print(
"Loaded batch with {}/{} chunks ({}/{})".format(
succeeded,
attempted,
total_succeeded,
total_attempted,
),
file=sys.stderr,
)
print(
"Finished with {}/{} chunks".format(total_succeeded, total_attempted),
file=sys.stderr,
)
# These spam a bunch of warnings/errors about modded content. Comment out if you need to debug.
for l in [
"PyMCTranslate.py3.api.version.translators.base",
"PyMCTranslate.py3.api.version.translators.biome",
"amulet.api.wrapper.format_wrapper",
]:
logging.getLogger(l).disabled = True
search_for_blocks(
amulet.load_level(WORLD_PATH),
TARGET_DIMENSION,
DESIRED_BLOCKS,
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment