# editor/pokemon_importer.gd @tool class_name PokeApiPokemonImporter extends RefCounted signal message(text : String) var _client : PokeApiClient var _fs : EditorFileSystem var _overwrite : bool var _languages : PackedStringArray var _pending : Array = [] # pokémon récupérés, en attente de sauvegarde func _init(client : PokeApiClient, fs : EditorFileSystem, overwrite : bool) -> void: _client = client _fs = fs _overwrite = overwrite _languages = PokeApiSettings.languages() func run(tokens : Array) -> void: DirAccess.make_dir_recursive_absolute(PokeApiSettings.pokemon_dir()) DirAccess.make_dir_recursive_absolute(PokeApiSettings.sprites_dir()) if !DirAccess.dir_exists_absolute(PokeApiSettings.moves_dir()): message.emit("[color=orange]Aucune capacité importée : les learnsets seront vides.[/color]") _pending.clear() await _client.run_parallel(tokens, _fetch_pokemon) # phase 1 : téléchargement await _save_all() # phase 2 : sprites + .tres _pending.clear() message.emit("Pokémon terminés.") func _fetch_pokemon(token : Variant) -> void: var j = await _client.get_json(PokeApiClient.API + "pokemon/" + str(token)) if j == null: message.emit("[color=red]Introuvable : %s[/color]" % str(token)) return var poke_name : String = j["name"] var stem := PokeApiSettings.pokemon_stem(int(j["id"]), poke_name) var path : String = PokeApiSettings.pokemon_dir() + stem + ".tres" if !_overwrite and FileAccess.file_exists(path): message.emit("Déjà présent : %s" % poke_name) return var species = await _client.get_json(j["species"]["url"]) var d := PokemonData.new() d.id = j["id"] d.api_name = poke_name d.height = j["height"] / 10.0 d.weight = j["weight"] / 10.0 for t in j["types"]: d.types.append(t["type"]["name"]) for a in j["abilities"]: d.abilities.append(a["ability"]["name"]) for s in j["stats"]: d.base_stats[s["stat"]["name"]] = s["base_stat"] d.names = {"en": poke_name.capitalize()} # repli si l'espèce est indisponible if species != null: d.names = PokeApiText.names(species["names"], _languages) d.descriptions = PokeApiText.flavors(species["flavor_text_entries"], _languages) var sprites : Dictionary = j["sprites"] var art : Dictionary = sprites.get("other", {}).get("official-artwork", {}) var sprite_url = art.get("front_default", sprites.get("front_default")) var shiny_url = art.get("front_shiny", sprites.get("front_shiny")) var dir := PokeApiSettings.sprites_dir() _pending.append({ "data": d, "path": path, "moves": j["moves"], "png": await _client.download_file(sprite_url, dir + stem + ".png"), "shiny_png": await _client.download_file(shiny_url, dir + stem + "_shiny.png"), }) func _save_all() -> void: var pngs := PackedStringArray() for p in _pending: for key in ["png", "shiny_png"]: if p[key] != "": pngs.append(p[key]) if !pngs.is_empty(): _fs.scan() while _fs.is_scanning(): await _client.get_tree().process_frame _fs.reimport_files(pngs) for p in _pending: var d : PokemonData = p["data"] d.menu_sprite = _load_texture(p["png"]) d.shiny_menu_sprite = _load_texture(p["shiny_png"]) _link_models(d) d.learnset = _build_learnset(p["moves"]) ResourceSaver.save(d, p["path"]) message.emit("OK : %s (%d capacités)" % [d.get_display_name(), d.learnset.size()]) _fs.scan() func _load_texture(path : String) -> Texture2D: if path.is_empty(): return null return ResourceLoader.load(path, "Texture2D", ResourceLoader.CACHE_MODE_REPLACE) as Texture2D func _link_models(d : PokemonData) -> void: var dir := PokeApiSettings.models_dir() if dir.is_empty(): return var model_path := "%s/%s.glb" % [dir, d.api_name] if ResourceLoader.exists(model_path): d.model_scene = load(model_path) as PackedScene var tex_path := "%s/%s_shiny.png" % [dir, d.api_name] if ResourceLoader.exists(tex_path): d.shiny_albedo = load(tex_path) as Texture2D func _build_learnset(raw_moves : Array) -> Array[LearnedMove]: var result : Array[LearnedMove] = [] for m in raw_moves: var move_path : String = PokeApiSettings.moves_dir() + String(m["move"]["name"]) + ".tres" if !FileAccess.file_exists(move_path): continue var details : Array = m["version_group_details"] var last : Dictionary = details[details.size() - 1] # jeu le plus récent var lm := LearnedMove.new() lm.move = load(move_path) as MoveData lm.level = last["level_learned_at"] lm.method = last["move_learn_method"]["name"] result.append(lm) result.sort_custom(func(a : LearnedMove, b : LearnedMove) -> bool: return a.level < b.level) return result