Фикс загрузки карты в вебе: gzip и запись пакета

HTTPRequest в браузере пытался второй раз распаковать уже распакованный gzip
(код 8), а download_file в вебе не создаёт файл. Теперь accept_gzip=false, тело
берём в память и пишем в user:// сами; в сообщении об ошибке показываем причину.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 16:33:44 +05:00
co-authored by Claude Sonnet 5.5
parent 97fafe6a30
commit 75aa525cb8
+29 -5
View File
@@ -34,35 +34,59 @@ func _download_and_mount(pack_name: String, title: String) -> bool:
var http := HTTPRequest.new() var http := HTTPRequest.new()
http.process_mode = Node.PROCESS_MODE_ALWAYS http.process_mode = Node.PROCESS_MODE_ALWAYS
http.download_file = "user://" + pack_name # Если сервер сжимает пакет gzip, браузер распаковывает его сам; вторая распаковка в движке ломает загрузку
http.accept_gzip = false
add_child(http) add_child(http)
var state := {"done": false, "result": -1, "code": 0} # Тело берём в память и пишем в user:// сами: в вебе download_file файл не создаёт
http.request_completed.connect(func(result: int, code: int, _h, _b): var state := {"done": false, "result": -1, "code": 0, "body": PackedByteArray()}
http.request_completed.connect(func(result: int, code: int, _h, body: PackedByteArray):
state.result = result state.result = result
state.code = code state.code = code
state.body = body
state.done = true) state.done = true)
var ok := false var ok := false
var detail := "запрос не отправлен"
# no-cache: браузер сверяет файл с сервером (после обновления пакета не подсунет старый из кэша) # no-cache: браузер сверяет файл с сервером (после обновления пакета не подсунет старый из кэша)
if http.request(_pack_url(pack_name), ["Cache-Control: no-cache"]) == OK: if http.request(_pack_url(pack_name), ["Cache-Control: no-cache"]) == OK:
while not state.done: while not state.done:
_update_progress(http, title) _update_progress(http, title)
await get_tree().process_frame await get_tree().process_frame
if state.result == HTTPRequest.RESULT_SUCCESS and state.code == 200: if state.result == HTTPRequest.RESULT_SUCCESS and state.code == 200:
ok = ProjectSettings.load_resource_pack("user://" + pack_name, false) # false: файлы основной игры в приоритете var path := "user://" + pack_name
var file := FileAccess.open(path, FileAccess.WRITE)
if file == null:
detail = "не удалось сохранить пакет, код %d" % FileAccess.get_open_error()
else:
file.store_buffer(state.body)
file.close()
state.body = PackedByteArray() # Освобождаем память: пакет уже на диске
ok = ProjectSettings.load_resource_pack(path, false) # false: файлы основной игры в приоритете
detail = "пакет скачан, но не подключился (%s)" % _describe_file(path)
else:
detail = "HTTP %d, код загрузки %d" % [state.code, state.result]
http.queue_free() http.queue_free()
if ok: if ok:
_loaded[pack_name] = true _loaded[pack_name] = true
_hide() _hide()
else: else:
_label.text = "Не удалось загрузить карту" printerr("MapLoader: не удалось загрузить %s: %s" % [pack_name, detail])
_label.text = "Не удалось загрузить карту\n%s" % detail
_bar.visible = false _bar.visible = false
await get_tree().create_timer(2.5).timeout await get_tree().create_timer(2.5).timeout
_hide() _hide()
get_tree().paused = false get_tree().paused = false
return ok return ok
# Для сообщения об ошибке: размер и первые байты скачанного файла
func _describe_file(path: String) -> String:
var f := FileAccess.open(path, FileAccess.READ)
if f == null:
return "файл не открывается, код %d" % FileAccess.get_open_error()
var head := f.get_buffer(4)
return "%d байт, начало %s" % [f.get_length(), head.hex_encode()]
func _pack_url(pack_name: String) -> String: func _pack_url(pack_name: String) -> String:
for arg in OS.get_cmdline_user_args(): for arg in OS.get_cmdline_user_args():
if arg.begins_with(PACK_URL_ARG): if arg.begins_with(PACK_URL_ARG):