Files

267 lines
14 KiB
Markdown
Raw Permalink 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.
# 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 отдельно. (Можно [тут](https://git.poisonflower.ru/poison-flower/l2-h5-geodata/src/branch/main))
Распакуй все `.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="..."` в
корневом теге `<gameserver>`. Это 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
<?xml version="1.0" encoding="UTF-8"?>
<gameserver address="192.168.1.207" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../data/xsd/ipconfig.xsd">
</gameserver>
```
### 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: <Name>`
Если видишь `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`.