# editor/pokeapi_client.gd @tool class_name PokeApiClient extends Node signal progress(done : int, total : int) const API := "https://pokeapi.co/api/v2/" var _in_flight : int = 0 var _done : int = 0 var _total : int = 0 func get_bytes(url : String) -> PackedByteArray: for attempt in 3: var http := HTTPRequest.new() add_child(http) if http.request(url) != OK: http.queue_free() await get_tree().create_timer(1.0).timeout continue var res : Array = await http.request_completed http.queue_free() if res[0] == HTTPRequest.RESULT_SUCCESS and res[1] == 200: return res[3] if res[1] == 404: break await get_tree().create_timer(1.0).timeout return PackedByteArray() func get_json(url : String) -> Variant: var bytes := await get_bytes(url) if bytes.is_empty(): return null return JSON.parse_string(bytes.get_string_from_utf8()) ## Télécharge une URL vers un fichier. Retourne le chemin, ou "" en cas d'échec. func download_file(url : Variant, path : String) -> String: if url == null: return "" var bytes := await get_bytes(String(url)) if bytes.is_empty(): return "" var f := FileAccess.open(path, FileAccess.WRITE) if f == null: return "" f.store_buffer(bytes) f.close() return path ## Lance worker(item) pour chaque élément, avec un nombre limité de tâches simultanées. func run_parallel(items : Array, worker : Callable) -> void: _done = 0 _total = items.size() progress.emit(0, _total) for item in items: while _in_flight >= PokeApiSettings.max_concurrent(): await get_tree().process_frame _in_flight += 1 _run_task(worker, item) while _in_flight > 0: await get_tree().process_frame func _run_task(worker : Callable, item : Variant) -> void: await worker.call(item) _in_flight -= 1 _done += 1 progress.emit(_done, _total)