Files
my-world/World/map_loader.gd
T
aibrashandClaude Sonnet 5.5 97fafe6a30 Карта Backrooms, порталы, комнаты по картам и зрение камня
- Backrooms на готовой модели (CC-BY, VTX): отдельный пакет backrooms.pck,
  качается при первом входе в портал (World/map_loader.gd), навмеш запечён заранее.
- Порталы между картами (World/portal.gd); выход из Backrooms возвращает в мир.
- Мультиплеер: игроки и общий камень делятся на комнаты по картам (Net/net.gd).
- Камень видит игрока только вблизи или в поле зрения, может потерять и бродит
  по навмешу (sight_limited); в мире и в Backrooms включено.
- Экспорт: пресет Backrooms для пакета карты, основной пресет без неё.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 16:15:00 +05:00

124 lines
4.6 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends Node
# Подгружает карту отдельным пакетом при первом входе в портал: в вебе её не качают при старте игры.
# Пакет (например backrooms.pck) лежит рядом с index.html. Если сцена уже есть в проекте
# (редактор, десктоп-запуск) — качать нечего, переходим сразу.
signal enter_failed
const PACK_URL_ARG := "--pack-url=" # Для тестов на десктопе: --pack-url=http://127.0.0.1:8000/
var _loaded := {} # имя пакета -> true, чтобы не качать и не монтировать дважды
var _busy := false
var _layer: CanvasLayer
var _label: Label
var _bar: ProgressBar
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
func enter(map: String, scene_path: String, pack_name: String, title: String) -> void:
if _busy:
return
if pack_name != "" and not _loaded.has(pack_name) and not ResourceLoader.exists(scene_path):
_busy = true
var ok := await _download_and_mount(pack_name, title)
_busy = false
if not ok:
enter_failed.emit()
return
Net.go_to_map(map, scene_path)
func _download_and_mount(pack_name: String, title: String) -> bool:
_show("Загрузка: %s…" % title)
get_tree().paused = true # Пока качаем, мир стоит (камень не должен убить игрока на экране загрузки)
var http := HTTPRequest.new()
http.process_mode = Node.PROCESS_MODE_ALWAYS
http.download_file = "user://" + pack_name
add_child(http)
var state := {"done": false, "result": -1, "code": 0}
http.request_completed.connect(func(result: int, code: int, _h, _b):
state.result = result
state.code = code
state.done = true)
var ok := false
# no-cache: браузер сверяет файл с сервером (после обновления пакета не подсунет старый из кэша)
if http.request(_pack_url(pack_name), ["Cache-Control: no-cache"]) == OK:
while not state.done:
_update_progress(http, title)
await get_tree().process_frame
if state.result == HTTPRequest.RESULT_SUCCESS and state.code == 200:
ok = ProjectSettings.load_resource_pack("user://" + pack_name, false) # false: файлы основной игры в приоритете
http.queue_free()
if ok:
_loaded[pack_name] = true
_hide()
else:
_label.text = "Не удалось загрузить карту"
_bar.visible = false
await get_tree().create_timer(2.5).timeout
_hide()
get_tree().paused = false
return ok
func _pack_url(pack_name: String) -> String:
for arg in OS.get_cmdline_user_args():
if arg.begins_with(PACK_URL_ARG):
return arg.substr(PACK_URL_ARG.length()) + pack_name
if OS.has_feature("web"):
return str(JavaScriptBridge.eval("new URL('%s', window.location.href).href" % pack_name))
return "http://127.0.0.1:8000/" + pack_name
# ---------- Экран загрузки ----------
func _show(text: String) -> void:
_layer = CanvasLayer.new()
_layer.layer = 100
add_child(_layer)
var bg := ColorRect.new()
bg.color = Color(0, 0, 0, 0.88)
bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
_layer.add_child(bg)
bg.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
_label = Label.new()
_label.text = text
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
_label.add_theme_font_size_override("font_size", 40)
bg.add_child(_label)
_label.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
_bar = ProgressBar.new()
_bar.custom_minimum_size = Vector2(420, 14)
_bar.show_percentage = false
_bar.indeterminate = true
var track := StyleBoxFlat.new()
track.bg_color = Color(1, 1, 1, 0.15)
var fill := StyleBoxFlat.new()
fill.bg_color = Color(1.0, 0.85, 0.25)
_bar.add_theme_stylebox_override("background", track)
_bar.add_theme_stylebox_override("fill", fill)
bg.add_child(_bar)
_bar.set_anchors_and_offsets_preset(Control.PRESET_CENTER_BOTTOM, Control.PRESET_MODE_KEEP_SIZE)
_bar.position.y -= 120
func _update_progress(http: HTTPRequest, title: String) -> void:
var got := http.get_downloaded_bytes()
var total := http.get_body_size() # -1, если сервер не прислал Content-Length (например, gzip)
if total > 0:
_bar.indeterminate = false
_bar.max_value = total
_bar.value = got
_label.text = "Загрузка: %s\n%.1f / %.1f МБ" % [title, got / 1048576.0, total / 1048576.0]
else:
_label.text = "Загрузка: %s\n%.1f МБ" % [title, got / 1048576.0]
func _hide() -> void:
if _layer:
_layer.queue_free()
_layer = null