# L2J Mobius High Five — Docker L2J Mobius (хроники High Five, `L2J_Mobius_CT_2.6_HighFive`) в Docker Compose. Три контейнера: `mysql`, `loginserver`, `gameserver`. Исходники сервера лежат прямо в этом репозитории (`src/`) и собираются локально через Ant — без внешних зависимостей от GitLab при каждой пересборке. ## Структура проекта ``` l2j-docker/ ├── src/ # Исходники L2J Mobius (java/, build.xml, dist/, launcher/) — редактируешь напрямую ├── Dockerfile.build # Собирает src/ через Ant, кладёт результат в /out ├── scripts/ │ ├── collect-dist.sh # Нормализует результат сборки в /out/login, /out/game, /out/sql │ └── extract-reference.sh # Выгружает /out на хост в reference/ для просмотра ├── login/ │ ├── Dockerfile # Runtime-образ login-сервера (JRE) │ └── entrypoint.sh # Ждёт mysql, применяет config_override, стартует jar ├── game/ │ ├── Dockerfile # Runtime-образ game-сервера (JDK — нужен для скриптового движка) │ └── entrypoint.sh # Ждёт mysql+login, применяет config_override, стартует jar ├── mysql/ │ ├── Dockerfile # MySQL 8.0 + автоимпорт SQL-схем при первом старте │ └── init/ ├── config/ │ ├── login/config/ # Override-конфиги login (применяются при каждом старте контейнера) │ └── game/config/ # Override-конфиги game ├── reference/ # Сгенерированный полный дефолтный дистрибутив (не в git, см. ниже) ├── geodata/ # .l2j файлы геодаты (не входят в репозиторий, кладутся руками) ├── docker-compose.yml ├── .env # Пароли, порты — реальные значения, не в git └── .env.example # Шаблон .env с плейсхолдерами ``` ## Как это работает 1. **`Dockerfile.build`** копирует `src/` в builder-образ и собирает его через `ant -f build.xml`. Результат — `LoginServer.jar`, `GameServer.jar` и SQL-схемы. 2. **`scripts/collect-dist.sh`** раскладывает собранный архив в `/out/login`, `/out/game`, `/out/sql` — единую структуру для runtime-образов. 3. **`login/Dockerfile`** и **`game/Dockerfile`** берут готовый `/out/*` из builder-образа и кладут в финальный контейнер с JRE/JDK. 4. **`config/login/config/`** и **`config/game/config/`** — это **единственное место, где нужно редактировать конфиги**. При каждом старте контейнера `entrypoint.sh` копирует всё из этой папки поверх дефолтных файлов внутри контейнера. Правки здесь переживают любой `docker compose build` / `--force-recreate`. Редактировать конфиги внутри уже запущенного контейнера (`docker exec`) — не сохранится после пересборки. ## Запуск с нуля ### 1. Собрать builder-образ ```bash docker build -f Dockerfile.build -t l2j-build:latest . ``` ### 2. Геодата Скачай геодату для High Five отдельно (она не входит в репозиторий Mobius и не входит в этот проект — файлы `*.l2j`, обычно раздаются на форумах/трекерах). Распакуй все `.l2j` файлы (и `geo_index.txt`) прямо в `./geodata/`, без вложенных подпапок. ### 3. Настроить `.env` ```bash cp .env.example .env # если только клонировал репозиторий nano .env ``` Задай `MYSQL_ROOT_PASSWORD` и остальные значения. **Важно**: пароль здесь должен совпадать с паролем в `config/login/config/Database.ini` и `config/game/config/Database.ini` (см. ниже). ### ⚠️ Обязательно смени перед первым запуском Репозиторий содержит рабочие сетевые настройки (`mysql`, `loginserver` вместо `localhost`), но **пароль и IP — от конкретной машины, на которой это разворачивалось изначально**. Смени их в трёх местах, иначе: подключение к БД будет использовать чужой пароль, а клиенты будут пытаться попасть на чужой IP. 1. **`config/login/config/Database.ini`** и **`config/game/config/Database.ini`** — строка `Password = ...`. Должна совпадать с `MYSQL_ROOT_PASSWORD` в `.env`. 2. **`config/game/config/ipconfig.xml`** — атрибут `address="..."` в корневом теге ``. Это IP/домен, который сервер сообщает клиенту после выбора сервера в списке (свой локальный/публичный IP, не `192.168.1.207` — это чужая машина). Всё остальное (`mysql`, `loginserver`, `0.0.0.0` в `Server.ini`) — универсальные значения, менять не нужно, они завязаны на имена сервисов в `docker-compose.yml`, а не на конкретный хост. ### 4. Настроить сетевые конфиги Login и game сервера по умолчанию слушают/подключаются на `localhost` — внутри Docker-сети это не работает, контейнеры видят друг друга по именам сервисов (`mysql`, `loginserver`, `gameserver`). Уже настроено в `config/*/config/Database.ini` и `config/login/config/Server.ini`: - `Database.ini` (оба сервера): `URL = jdbc:mysql://mysql/l2jmobiush5?...` - `login/config/Server.ini`: `LoginHostname = 0.0.0.0`, `LoginHostname` для приёма game-сервера — `LoginHost = 0.0.0.0` (не `127.0.0.1`, иначе gameserver не сможет подключиться из своего контейнера) - `game/config/Server.ini`: `LoginHost = loginserver` (имя сервиса, не IP) ### 5. ipconfig.xml — адрес для клиентов `config/game/config/ipconfig.xml` определяет, какой IP-адрес game-сервер сообщает клиенту после выбора сервера в списке. Если клиент подключается: - **с этого же сервера** — оставь `127.0.0.1` - **из локальной сети** — укажи локальный IP сервера (например, `192.168.1.207`) - **из интернета** — укажи публичный IP или домен Пример минимального конфига: ```xml ``` ### 6. Собрать и запустить ```bash docker compose build docker compose up -d docker compose logs -f mysql loginserver gameserver ``` Ожидаемая последовательность в логах: 1. `mysql` — выполняет SQL-схемы, проходит healthcheck 2. `loginserver` — `LoginServer: Login client listener started on 0.0.0.0:2106` 3. `gameserver` — `LoginServerThread: Registered on login as Server N: ` Если видишь `Registered on login as Server` — стек полностью поднят. ## Просмотр полного дистрибутива сервера (reference) `/out` внутри builder-образа (`login/`, `game/`, `sql/` с jar-файлами, конфигами и data/) существует только как промежуточный слой между стадиями Docker-сборки — на хосте его не видно напрямую. Чтобы удобно читать дефолтные файлы сервера (посмотреть, что там есть, прежде чем что-то копировать в override), используй скрипт `scripts/extract-reference.sh`: ```bash ./scripts/extract-reference.sh ``` Это выгружает полный `/out` из свежего `l2j-build:latest` образа в `./reference/` — обычную папку на диске: ``` reference/login/config/... reference/game/config/... reference/game/data/... reference/login/libs/... ``` Дальше — смотришь нужный файл и копируешь **только его** в override: ```bash cat reference/game/config/Rates.ini cp reference/game/config/Rates.ini config/game/config/Rates.ini nano config/game/config/Rates.ini docker compose up -d --force-recreate gameserver ``` `reference/` — сгенерированные файлы, не нужно коммитить их в git (см. `.gitignore`). После пересборки Java-кода (`docker build -f Dockerfile.build ...`) перезапусти скрипт, чтобы `reference/` отражал актуальную сборку: ```bash docker build -f Dockerfile.build -t l2j-build:latest . && ./scripts/extract-reference.sh ``` ## Редактирование конфигов Все дефолтные конфиги обоих серверов уже скопированы в `config/login/config/` и `config/game/config/`. Правь их прямо здесь: ```bash nano config/game/config/Rates.ini # рейты экспы/дропа nano config/game/config/NPC.ini # агрессия, respawn nano config/game/config/Player.ini # лимиты персонажей ``` После правки — пересоздать нужный контейнер (без пересборки образа, если менялся только конфиг, а не код): ```bash docker compose up -d --force-recreate gameserver ``` **Важно — не копируй `reference/` в `config/` массово поверх уже настроенных файлов.** `config/login/config/Database.ini`, `config/game/config/Database.ini`, `config/game/config/Server.ini` и `config/game/config/ipconfig.xml` содержат критичные сетевые правки (`mysql`/`loginserver` вместо `localhost`/`127.0.0.1`) — если их затереть дефолтными значениями из `reference/`, game-сервер перестанет находить MySQL или login-сервер (`Connection refused`, `LoginServer not available`). Копируй в override только конкретные файлы, которые собираешься менять, не весь каталог целиком. ## Изменение кода сервера Исходники лежат в `src/java/`. После правки: ```bash docker build -f Dockerfile.build -t l2j-build:latest . docker compose build docker compose up -d ``` Первая команда пересобирает Java-код через Ant, вторая — пересобирает runtime-образы login/game с новыми jar-файлами, третья — перезапускает стек. ## Память JVM Размер кучи для game-сервера задан в `game/entrypoint.sh`: ```bash exec java -Xms1g -Xmx4g -Dfile.encoding=UTF-8 -cp "$CLASSPATH" -jar libs/GameServer.jar ``` Полная геодата High Five (203 региона) требует заметного объёма памяти при загрузке — при `OutOfMemoryError` на этапе `[ Geodata ]` увеличь `-Xmx`. После правки: ```bash docker compose build gameserver docker compose up -d --force-recreate gameserver ``` ## Резервное копирование Образы и контейнеры полностью воспроизводимы из этого репозитория — бэкапить нужно только: 1. **Сам репозиторий** (`src/`, конфиги, override) — обычный git. 2. **Данные MySQL** (аккаунты, персонажи) — они живут в Docker-volume `mysql_data`, не в файлах проекта. Дамп: ```bash docker exec l2j-mysql mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" l2jmobiush5 > backup_$(date +%Y%m%d_%H%M%S).sql ``` Восстановление: ```bash docker exec -i l2j-mysql mysql -u root -p"$MYSQL_ROOT_PASSWORD" l2jmobiush5 < backup_ФАЙЛ.sql ``` ## Порты | Сервис | Порт | Назначение | |---|---|---| | loginserver | 2106 | Подключение клиента (экран логина) | | gameserver | 7777 | Подключение клиента (после выбора сервера) | | gameserver → loginserver | 9014 | Внутренний auth-обмен между серверами | | mysql | 3306 | БД (не публикуется наружу по умолчанию) | Меняются в `.env`.