def get_latest_iter() -> Generator[float, None, JavaResourcePack]:
    """Download the latest resource pack if required.

    :return: The loaded Java resource pack.
    :raises:
        Exception: If the
    """
    vanilla_rp_path = os.path.join(RESOURCE_PACK_DIR, "java_vanilla")
    try:
        if INCLUDE_SNAPSHOT:
            new_version = get_launcher_manifest()["latest"]["snapshot"]
        else:
            new_version = get_launcher_manifest()["latest"]["release"]
    except Exception as e:
        if os.path.isdir(vanilla_rp_path):
            log.error(
                "Could not download the launcher manifest. The resource pack seems to be present so using that."
            )
        else:
            raise e
    else:
        has_new_pack = False
        if os.path.isfile(os.path.join(vanilla_rp_path, "version")):
            with open(os.path.join(vanilla_rp_path, "version")) as f:
                old_version = f.read()
            has_new_pack = old_version == new_version

        if not has_new_pack:
            yield from _remove_and_download_iter(vanilla_rp_path, new_version)
    return JavaResourcePack(vanilla_rp_path)
def get_latest_iter() -> Generator[float, None, JavaResourcePack]:
    vanilla_rp_path = os.path.join(RESOURCE_PACK_DIR, "java_vanilla")
    new_version = launcher_manifest["latest"]["release"]
    if new_version is None:
        if os.path.isdir(vanilla_rp_path):
            log.error(
                "Could not download the launcher manifest. The resource pack seems to be present so using that."
            )
        else:
            log.error(
                "Could not download the launcher manifest. The resource pack is not present, blocks may not be rendered correctly."
            )
    else:
        if os.path.isdir(vanilla_rp_path):
            if os.path.isfile(os.path.join(vanilla_rp_path, "version")):
                with open(os.path.join(vanilla_rp_path, "version")) as f:
                    old_version = f.read()
                if old_version != new_version:
                    yield from _remove_and_download_iter(
                        vanilla_rp_path, new_version)
            else:
                yield from _remove_and_download_iter(vanilla_rp_path,
                                                     new_version)
        else:
            yield from _remove_and_download_iter(vanilla_rp_path, new_version)
    return JavaResourcePack(vanilla_rp_path)
def download_resources_iter(path,
                            version,
                            chunk_size=4096) -> Generator[float, None, bool]:
    log.info(f"Downloading Java resource pack for version {version}")
    version_url = next(
        (v["url"]
         for v in launcher_manifest["versions"] if v["id"] == version), None)
    if version_url is None:
        log.error(f"Could not find Java resource pack for version {version}.")
        return False

    try:
        version_manifest = json.load(urlopen(version_url))
        version_client_url = version_manifest["downloads"]["client"]["url"]

        response = urlopen(version_client_url)
        data = []
        data_size = int(response.headers["content-length"].strip())
        index = 0
        chunk = b"hello"
        while chunk:
            chunk = response.read(chunk_size)
            data.append(chunk)
            index += 1
            yield min(1.0, (index * chunk_size) / (data_size * 2))

        client = zipfile.ZipFile(io.BytesIO(b"".join(data)))
        paths = [
            fpath for fpath in client.namelist() if fpath.startswith("assets/")
        ]
        path_count = len(paths)
        for path_index, fpath in enumerate(paths):
            if not path_index % 30:
                yield path_index / (path_count * 2) + 0.5
            client.extract(fpath, path)
        client.extract("pack.mcmeta", path)
        client.extract("pack.png", path)

    except:
        log.error(
            f"Failed to download and extract the Java resource pack for version {version}. Make sure you have a connection to the internet.",
            exc_info=True,
        )
        return False
    log.info(f"Finished downloading Java resource pack for version {version}")
    return True
def download_resources_iter(path,
                            version,
                            chunk_size=4096) -> Generator[float, None, None]:
    log.info(f"Downloading Java resource pack for version {version}")
    version_url = next(
        (v["url"]
         for v in get_launcher_manifest()["versions"] if v["id"] == version),
        None,
    )
    if version_url is None:
        raise Exception(
            f"Could not find Java resource pack for version {version}.")

    try:
        with urlopen(version_url, timeout=20) as vm:
            version_manifest = json.load(vm)
        version_client_url = version_manifest["downloads"]["client"]["url"]

        with urlopen(version_client_url, timeout=20) as response:
            data = []
            data_size = int(response.headers["content-length"].strip())
            index = 0
            chunk = b"hello"
            while chunk:
                chunk = response.read(chunk_size)
                data.append(chunk)
                index += 1
                yield min(1.0, (index * chunk_size) / (data_size * 2))

        client = zipfile.ZipFile(io.BytesIO(b"".join(data)))
        paths: List[str] = [
            fpath for fpath in client.namelist() if fpath.startswith("assets/")
        ]
        path_count = len(paths)
        for path_index, fpath in enumerate(paths):
            if not path_index % 30:
                yield path_index / (path_count * 2) + 0.5
            if fpath.endswith("/"):
                continue
            os.makedirs(
                os.path.dirname(os.path.abspath(os.path.join(path, fpath))),
                exist_ok=True,
            )
            client.extract(fpath, path)
        if "pack.mcmeta" in client.namelist():
            client.extract("pack.mcmeta", path)
        else:
            # TODO: work out proper version support for this
            with open(os.path.join(path, "pack.mcmeta"), "w") as f:
                f.write(
                    '{"pack": {"description": "The default data for Minecraft","pack_format": 7}}'
                )
        if "pack.png" in client.namelist():
            client.extract("pack.png", path)

    except Exception as e:
        log.error(
            f"Failed to download and extract the Java resource pack for version {version}.",
            exc_info=True,
        )
        raise e
    log.info(f"Finished downloading Java resource pack for version {version}")
    def _get_model(self, block: Block) -> BlockMesh:
        """Find the model paths for a given block state and load them."""
        if (block.namespace, block.base_name) in self._blockstate_files:
            blockstate: dict = self._blockstate_files[(block.namespace,
                                                       block.base_name)]
            if "variants" in blockstate:
                for variant in blockstate["variants"]:
                    if variant == "":
                        try:
                            return self._load_blockstate_model(
                                block, blockstate["variants"][variant])
                        except Exception as e:
                            log.error(
                                f"Failed to load block model for {blockstate['variants'][variant]}\n{e}"
                            )
                    else:
                        properties_match = Block.properties_regex.finditer(
                            f",{variant}")
                        if all(
                                block.properties.get(
                                    match.group("name"),
                                    amulet_nbt.TAG_String(match.group(
                                        "value")),
                                ).value == match.group("value")
                                for match in properties_match):
                            try:
                                return self._load_blockstate_model(
                                    block, blockstate["variants"][variant])
                            except Exception as e:
                                log.error(
                                    f"Failed to load block model for {blockstate['variants'][variant]}\n{e}"
                                )

            elif "multipart" in blockstate:
                models = []

                for case in blockstate["multipart"]:
                    try:
                        if "when" in case:
                            if "OR" in case["when"]:
                                if not any(
                                        all(
                                            block.properties.get(prop, None) in
                                            self.parse_state_val(val) for prop,
                                            val in prop_match.items())
                                        for prop_match in case["when"]["OR"]):
                                    continue
                            elif not all(
                                    block.properties.get(prop, None) in
                                    self.parse_state_val(val)
                                    for prop, val in case["when"].items()):
                                continue

                        if "apply" in case:
                            try:
                                models.append(
                                    self._load_blockstate_model(
                                        block, case["apply"]))

                            except:
                                pass
                    except:
                        pass
import minecraft_model_reader
from minecraft_model_reader import log
from minecraft_model_reader.api.resource_pack import JavaResourcePack

RESOURCE_PACK_DIR = os.path.join(minecraft_model_reader.path, "api",
                                 "resource_pack", "java", "resource_packs")

try:
    log.info("Downloading java launcher manifest file.")
    launcher_manifest = json.load(
        urlopen(
            "https://launchermeta.mojang.com/mc/game/version_manifest.json"))
except Exception as e:
    log.error(
        f'Failed to download the launcher manifest. "{e}" This may cause problems if you have not used the program before. Make sure you are connected to the internet and https://mojang.com is not blocked.'
    )
    launcher_manifest = {"latest": {"release": None}}


def generator_unpacker(gen: Generator):
    try:
        while True:
            next(gen)
    except StopIteration as e:
        return e.value


def get_latest() -> JavaResourcePack:
    return generator_unpacker(get_latest_iter())