aibrashandClaude Sonnet 5.5 9a4142419d Стартовый хаб с порталами, песочница отдельным пакетом, присед
- World/Hub: маленькая стартовая комната (код, без ассетов) с порталами на карты;
  новые карты добавляются записью в PORTALS (влезает 6 порталов).
- Песочница (main.tscn) вынесена в world.pck и качается при входе в портал;
  основной пакет игры вместо 19.7 МБ стал 2.1 МБ. Выходы из карт ведут в хаб.
- Экспорт: три пресета (Web — движок и хаб, World, Backrooms).
- Присед: удерживать C (на бегу Shift+C по-прежнему подкат), скорость 3.5.

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

My World

Репо самого проекта Godot (все файлы проекта). Киберпанк-мир от первого лица с паркур-управлением и простым мультиплеером: игроки, зашедшие на сайт, бегают вместе и видят друг друга.

  • Движок: Godot 4.7.2, рендерер GL Compatibility (нужен для Web), физика Jolt
  • Платформа: Web (экспорт в WebAssembly), без потоков (variant/thread_support=false), поэтому заголовки COOP/COEP браузеру не требуются, но на сервере они всё равно стоят
  • Язык интерфейса и комментариев в коде: русский

Структура проекта

main.tscn            главная сцена (мир, окружение, свет, постройки, лес, птицы, игрок)
Player/              игрок от первого лица (CharacterBody3D) и всё паркур-управление
  character_body_3d.gd   ~800 строк: бег, рывок, слайд, бег по стенам, прыжки, подтягивание
World/               мир: forest.gd (лес на MultiMesh), birds.gd, levitate.gd, пол, небо (HDR), музыка
models/              .glb-модели: здания, башня, обелиск, деревья, Эмпайр-стейт, кибер-офис, скала
Net/                 мультиплеер (см. ниже)
  net.gd                 автолоад "Net": и клиент, и сервер (один скрипт)
  ghost.gd               чужой игрок: капсула, ник, сглаженное движение
  server.tscn            пустая сцена для запуска сервера
deploy/              примеры nginx-конфига, systemd-юнита, инструкция
export_presets.cfg   пресет «Web», экспорт в ../grid-world/index.html

Соседние папки на компьютере разработчика (/home/aibrash/Projects/My_World/): my-world (этот проект), grid-world (репо с готовым Web-экспортом, см. деплой), Blender models.

Управление (в игре)

WASD бег, Shift спринт, Пробел прыжок (держать у уступа — подтянуться), Q рывок, C слайд (на бегу, вместе с Shift), ЛКМ (зажать) зум, Esc отпускает мышь, клик по окну захватывает. Бег по стене — в воздухе у стены с зажатым W на скорости.

Мультиплеер

Архитектура: выделенный сервер на Godot (WebSocket), клиенты подключаются как WebSocketMultiplayerPeer. Сервер ничего не считает и не проверяет, только пересылает состояния игроков остальным. Мир, физика и управление работают локально у каждого. Игроки друг с другом не сталкиваются.

  • Net/net.gd — автолоад Net. Если DisplayServer.get_name() == "headless" — это сервер (порт 9080, plain ws://), иначе клиент. Клиент переподключается каждые 3 с.
  • Клиент шлёт 20 раз/с submit_state(pos, yaw, pitch, flags) (RPC на сервер, unreliable_ordered), сервер пересылает остальным recv_state(id, ...), при выходе — recv_left(id) (reliable).
  • Флаги состояния (Net.FLAG_*): подкат, бег по стене, рывок, подтягивание. Собираются в Player/character_body_3d.gd → get_net_flags(). Игрок находится в группе local_player.
  • Клиент-призрак: Net/ghost.gd — капсула с цветом от id, «визор» показывает направление взгляда, ник «Игрок N».
  • Адрес сервера в клиенте: в Web — из window.location (wss://<домен>/ws для https, ws://<домен>/ws для http); на десктопе — ws://127.0.0.1:9080 или аргумент godot -- --server-url=wss://....
  • RPC требуют одинаковый путь узла и скрипт на сервере и клиенте. Поэтому один скрипт net.gd в автолоаде. Менять сетевые сообщения нужно синхронно: клиент (экспорт) + сервер (/opt/my-world-server), иначе игроки не увидят друг друга.

Запуск локально

# сервер
godot --headless --path . res://Net/server.tscn
# клиент (можно запустить несколько окон)
godot --path . --windowed --resolution 960x540

Осторожность: pkill -f / pgrep -f с шаблоном godot --headless убивает и сам шелл, потому что шаблон встречается в его командной строке. Находить процесс лучше через ss -ltnp | grep 9080.

Инфраструктура и деплой

Браузер ──https/wss──▶ Nginx Proxy Manager (SSL, домен на duckdns) ──http──▶ контейнер 192.168.10.110
                                                                          nginx :80
                                                                            ├─ /    → /opt/grid-world (статика игры)
                                                                            └─ /ws  → 127.0.0.1:9080 (игровой сервер)

Сервер: root@192.168.10.110, Debian 12, контейнер LXC в Proxmox, 1 ядро, 1 ГБ RAM. Ключи ssh настроены. Нет curl, rsync, ufw; есть python3, perl. Домен и SSL на Nginx Proxy Manager выше по сети; в его proxy host должна быть включена опция Websockets Support (иначе /ws не работает; сейчас работает, проверено в браузере).

Обновить клиент (изменился мир, модель, игровой код)

cd ~/Projects/My_World/my-world
godot --headless --path . --export-release Web ../grid-world/index.html
cd ../grid-world && git add -A && git commit -m "..." && git push origin main

Gitea (git.ibrash.duckdns.org, репо aibrash/grid-world) по пушу в main запускает workflow .gitea/workflows/deploy.yml: заходит по ssh и делает git pull в /opt/grid-world. Экспорт при выходе печатает безвредную ошибку Parameter "singleton" is null.

Обновить игровой сервер (изменился Net/*)

Игровой сервер — отдельный минимальный проект в /opt/my-world-server/ (project.godot + Net/ + официальный бинарник Godot 4.7.2 linux x86_64, файл godot). Бинарник из Fedora на Debian не подходит, взят официальный из github.com/godotengine/godot-builds (релиз 4.7.2-stable). Сервис systemd: my-world.service (DynamicUser, StateDirectory=my-world, автозапуск, Restart=always).

scp Net/net.gd Net/ghost.gd Net/server.tscn root@192.168.10.110:/opt/my-world-server/Net/
ssh root@192.168.10.110 'systemctl restart my-world'
ssh root@192.168.10.110 'journalctl -u my-world -f'   # лог: «+ игрок …» / «- игрок …»

При правках модели/мира серверную часть трогать не нужно. Игровой сервер слушает порт 9080 на всех интерфейсах контейнера (наружу не проброшен). Можно сузить до 127.0.0.1 через create_server(port, "127.0.0.1").

nginx контейнера: /etc/nginx/sites-enabled/godot_game (резервная копия до правок: /root/godot_game.bak); в нём блок location /ws с заголовками Upgrade/Connection.

Git

  • Репо проекта: git@git.ibrash.duckdns.org:aibrash/my-world.git, ветка master (основная), используются коммиты на русском с трейлером Co-Authored-By. Для экспериментов создаётся ветка dev (была слита и удалена).
  • Пушить master и выкладывать на сайт — только по прямой просьбе владельца.

Что выяснено по ходу работы (полезно не повторять)

  • Окружение (main.tscn): в рендерере Compatibility объёмный туман не работает (ни кадр не меняется, ни память), поэтому он удалён. SSAO и glow работают: glow даёт неоновое свечение, SSAO — затемнение в стыках; оба оставлены. Отключение всех трёх экономило лишь около 4 МБ видеопамяти и убирало вид, поэтому это не причина высокой памяти.
  • Память: вкладка в браузере показывала около 1,6 ГБ, хотя на десктопе сцена занимает ~115 МБ (статика 83 МБ + видеопамять 30 МБ). Причина не найдена. Нужны данные из Chrome (Shift+Esc: память / память GPU / JS-память и растёт ли цифра со временем). Гипотезы: рост WASM-памяти и GPU-процесс Chrome, несжатые текстуры (для Web выключено vram_texture_compression/for_mobile), HDR-небо 2k, звук .ogg, распаковываемый целиком, dlink (extensions_support=true, index.side.wasm 44 МБ).
  • Пресет «Web» экспортирует в ../grid-world/index.html. Шаблоны экспорта лежат в ~/.local/share/godot/export_templates/4.7.2.stable/ (есть только Web; Linux-шаблонов нет, поэтому серверный бинарник — официальный редактор в режиме headless).

Идеи на потом

  • Скрипт deploy.sh: экспорт + пуш клиента + при необходимости обновление сервера одной командой.
  • Ники по выбору игрока, текстовый чат, анимации персонажа вместо капсулы.
  • Серверные проверки (антиспуфинг позиций), комнаты, если игроков станет много.
  • Разобраться с потреблением памяти в браузере (см. выше).
S
Description
No description provided
Readme
134 MiB
Languages
GDScript 87.6%
Python 8.8%
Shell 1.9%
GDShader 1.7%