Docs: README (project map), AUDIT (review 03.09), BOTS/DEBUG/BOTBRAIN/INSTALL updated for SPP 3

This commit is contained in:
2026-09-03 20:43:30 +02:00
parent 165820c041
commit 97ce6ae2af
7 changed files with 124 additions and 11 deletions
+37
View File
@@ -0,0 +1,37 @@
# Ревизия проекта (03.09.2026)
## Копии исходников и что с ними стало
| Копия | Состояние на момент ревизии | Решение |
|---|---|---|
| `src_mobius/mobius/L2J_Mobius_CT_0_Interlude` | Источник истины после слияния 26.08 (мозг + чат) | Оставлен, теперь под git |
| `server/` | Развёрнутый сервер; в нём были **более новые** `FakePlayerProgression.xml` и `spp_clan_seed.sql` (новые ники из чата «Генерация ников»), jar собран из `src_mobius` | Ники забраны в `src_mobius`; `server/` вне git, наполняется деплоем |
| `patches/` | Мост между двумя копиями (26.08), содержимое старее `src_mobius` | Устарел, игнорируется |
| `src_mobius_interlude.zip` (26.08 13:59) | Снимок до слияния мозга; единственное отличие от дерева — отсутствие `FakePlayerBrain`/`CombatData` | Устарел |
| `ziAuQ8He`, `ziVsvreY` (26.08 00:16 и 01:47) | Ранние снимки чата (до Idiolect/HeardManager) | Устарели |
| `src/`, `l2j-lisvus/` | Заброшенная попытка на L2J Lisvus (C4) | Игнорируются |
Ванильная база найдена точно: java-дерево совпадает с Mobius `9be7adbe5a` (25.08.2026) везде, кроме наших файлов. Наш патч поверх ванили: `GameServer.java`, `AttackableAI.java`, `Attackable.java`, `Npc.java`, `Player.java`, `RequestJoinParty.java`, `FakePlayerInfo.java`, `FakePlayersConfig.java` + все `FakePlayer*.java` в `managers` + `FakePlayerNameGenerator.java`; в датапаке — `FakePlayers.ini`, `General.ini` (GridsAlwaysOn), `FakePlayers.xml` (спавн Evi выключен), `FakePlayerChatData.xml`, `ChatGeneral.java`, `ChatWhisper.java`, все `FakePlayer*.xml`/xsd, `dashboard.html`, `fpc_trader_00.xml`, `spp_*.sql`.
## Найденные проблемы
1. **Чат-движок был подключён не к тому населению.** Мир работает в режиме «только headless» (`FakePlayerProgression = False`, 500 headless). Весь чат из сессии «Изучение швов» — `understand()` с памятью позиций, молчанием на первое сообщение, реакцией на капс, зеркалированием стиля, фактами `asker` — жил только в `FakePlayerChatManager` и принимал `Npc`. Headless-боты (реальное население) отвечали через свой урезанный `understand()` без всего этого. Исправлено: общий `FakePlayerUnderstanding` + `FakePlayerBotRef` для обоих видов ботов.
2. **Боевой цикл душил социальный.** В `handle()` мозг возвращал `true`, как только видел моба или был в бою, и код ниже (ганг, ПКК, помощь, клан-вары, пати, бытовой чат, лут) не выполнялся почти никогда — в зоне фарма моб есть всегда. Исправлено: социальный слой (`FakePlayerSocial`) идёт до мозга и гейтится кулдаунами, лут перенесён в мозг.
3. **Боты не разговаривали друг с другом.** Единственный канал — «подхват» через `HeardManager` с 10% шансом и глобальным троттлом 8 с на весь сервер. Добавлены диалоги: приветствия при встрече, вопросы-открытия (`bot_talk`), ответы через тот же разбор интентов, что и для игрока, сплетни, поздравления; троттл сделан per-listener.
4. **Данные умели больше, чем код.** Факты `asker=clanmate|enemy_war`, слоты `{enemyclan} {mob} {town} {crowd} {drop}` были в XML, но код их не подавал — строки с ними никогда не выпадали. Теперь подаются (`FakePlayerBotContext.setSlot`).
5. **Зоны фарма не соответствовали уровням мобов.** Таблица зон была «сеткой» по регионам без сверки с мобами: Wasteland (мобы 3035) значился как 1524, Cruma Marshlands (2835) как 1524, Tanor Canyon (4350) как 3544 и т.д. Для NPC-ботов (статы из шаблонов) это не бросалось в глаза, для headless-игроков — гибель пачками. Таблица пересчитана по реальным спавнам датапака (`tools/fix_zones.py`): 96 зон с узкими полосами уровней, плюс 8 новых зон на 1322 (Ruins of Agony/Despair, Abandoned Camp, Windmill Hill, Swampland, Dark Forest, Spider Nest, Abandoned Coal Mines).
6. **Боты не давали сдачи** мобам не своего уровня, не носили бижу, не имели бафов, потом зелья использовались через `useEquippableItem` (ошибка «Unknown body slot NONE» в логе). Исправлено.
7. **Класс 34 в `FakePlayerCombat.xml` был подписан как Spellhowler** (34 — Bladedancer, Spellhowler — 40): БД получал роль «маг». Профили были на 13 классов из 43 в сиде; теперь на все 43, id скиллов проверены по деревьям скиллов (`tools/check_data.py`).
8. **Лавка после закрытия оставляла бота в городе** — он «фармил» Гиран до конца жизни. Теперь после лавки — покупка расходников и возврат на спот.
9. **Ложные срабатывания интентов**: «молодая» ≈ «соло» → дуэль, «думаешь» ≈ «дурак» → оскорбление, «стоишь» ≈ «стоит» → цена, «слышь» удовлетворяло обе группы «что нового». Опечатко-устойчивость ограничена (основа ≥ 5 букв, длина слова близка), добавлена пометка `=основа` (только точный префикс), одно слово не закрывает две группы.
10. **NPC-режим ботов сломан**: шаблонов `fpc_spp_00..07.xml` (1600 NPC) в `server/` нет, `FakePlayerProgression = True` спавнить нечего. Не чинил — мир headless.
11. `FakePlayerLlmChat = True` при недоступной Ollama: каждый ответ ждёт таймаут/отказ и только потом шаблон. Добавлен `FakePlayerLlmPriority = seams` — шаблоны первыми, LLM только для фраз без интента.
12. Мелочи: XML без XSD печатали ошибки валидации при старте (добавлены разрешающие xsd); `reset-bots.ps1` чистит гербы 9000–9999 при диапазоне 9500–9668 — ок; `data.rar`/`html.rar` в `server/game/data` — 154 МБ мусора.
## Что не проверено вживую с клиентом
Все проверки — в песочнице (MariaDB + login + game, 120 ботов, ~2 мин на прогон) и оффлайн-харнессом. Не проверялось глазами из клиента: окно приглашения в пати от бота (`do=invite`), отрисовка бота, кастующего печать на артефакте, общий вид осады. Осада запускалась форсом (`do=siege&arg=Giran`): регистрация кланов, телепорт, крики, атака ворот — в логе есть, до печати за 45 секунд наблюдения дело не доходило.
## Смертность
После правок боты гибнут заметно реже (в песочнице без геодаты ~18/мин на 120 ботов в первую минуту после спавна, с геодатой ~10/мин; до правок — 20–24), но всё ещё много: маги гибнут от равных мобов, спавн попадает в центр стай. Дальнейшие ручки: `pickPrey` (сейчас цель не выше уровня+1 и подальше от стаи), пороги отдыха (охота только при HP ≥ 60%), сквады соклановцев (формируются сами и держатся лидера).
+1 -1
View File
@@ -81,7 +81,7 @@
**Не проверено вживую**: песочница в этот раз убивала процессы, поэтому сборка чистая (BUILD SUCCESSFUL), но запуск с ботами не прогнан. Первым делом посмотри `logs -f game` на строку `FakePlayerCombatData: Loaded combat profiles for 13 classes.` **Не проверено вживую**: песочница в этот раз убивала процессы, поэтому сборка чистая (BUILD SUCCESSFUL), но запуск с ботами не прогнан. Первым делом посмотри `logs -f game` на строку `FakePlayerCombatData: Loaded combat profiles for 13 classes.`
**Следующий заход**: роли танка и спойлера, покупка расходников у НПС, бегство к стражам от ПК, смена профессии на 20/40. **Заход 03.09 (SPP 3)** — сделано: спойлер (спойл + свип), покупка расходников и продажа хлама (`FakePlayerEconomy`), смена профессии на 20/40/76, бижа и городские бафы, ответный удар нападающему, поводок к споту, выбор одиночного моба не выше уровня+1, отдых при HP < 60 %, зелья через обработчик предметов, лут в мозге. Не сделано: роль танка (агро-скиллы), бегство к стражам от ПК.
## Лицензии ## Лицензии
+24
View File
@@ -1,5 +1,29 @@
# Боты: что сделано и как этим пользоваться # Боты: что сделано и как этим пользоваться
## SPP 3 (03.09.2026): боты реально играют
Население — headless-игроки (настоящие `Player` без клиента). Сборка живёт в git (`README.md`), деплой — `build.ps1`. Что делает каждый бот в течение дня, и как это проверить:
**Гринд.** Спот по своему уровню (96 зон, полосы уровней посчитаны по реальным спавнам датапака, `tools/fix_zones.py`), цель — моб не выше уровня+1 и подальше от стаи, автошоты своего грейда, скиллы по профилю класса (`FakePlayerCombat.xml`, 43 класса), самобафы и «городские» бафы (WW/Shield/Might/Empower/Acumen…, обновляются, когда спали), бижа своего грейда, зелья при HP < 45 %, отдых сидя при HP < 60 % / MP < 25 %, ответный удар любому, кто напал, бегство от моба на 7+ уровней выше, поводок к споту (1500 — идёт назад, 7000 — телепорт). Дварфы спойлят и свипают. Смерть — 15 с лежит, встаёт в ближайшем городе, продаёт хлам, докупает расходники, через 20–60 с возвращается на спот.
**Прокачка настоящая**: опыт с реальных убийств, левел-ап реальный, профы на 20/40/76 (`FakePlayerProfessionChange`) — бот берёт следующий класс своей ветки, получает скиллы, говорит об этом; при переходе тира прощается, идёт в город (продажа, покупки, бафы) и телепортируется в зону нового уровня.
**Экономика настоящая**: свой инвентарь, своя адена. Хлам (дешевле 1500 или стопки) продаётся НПС за полцены, дорогой дроп идёт в **лавку** (реальный `PrivateStoreType.SELL`, купить можно) в городе своего уровня; после лавки — покупка сосок/стрел/банок на заработанное и возврат на спот. Стартовый набор шотов — подарок один раз, дальше только за своё.
**Осады** (`FakePlayerSieges`). По расписанию `SiegeSchedule.xml` бот-кланы с ≥3 членами 40+ онлайн регистрируются атакующими на замки бот-кланов (по 2 клана на замок, `FakePlayerSiegeAttackerClans`; на замки игроков — только при `FakePlayerSiegeAttackPlayerCastles = True`). Лидеры кланов подгружаются в мир заранее. В начале осады атакующие собираются за внешними воротами, защитники — у артефакта. Атакующие бьют врагов, ломают ворота, идут к артефакту, лидер клана кастует Печать Правителя (3 минуты, остальные прикрывают) — замок переходит настоящей механикой движка. Крики в крик-чат: начало, ворота, печать, победа/поражение. Форс: `do=siege&arg=Giran`, `do=siegeend`, `do=siegeinfo`.
**Пати.** Соклановцы одного уровня стартуют на одном споте и собираются в настоящие пати (до 6), держатся лидера, ассистят его цель, хилеры лечат. С игроком: «го пати» → бот **приглашает сам** (обычное окно приглашения), инвайт игроку бот принимает.
**Чат — один движок на всех.** Шёпот и общий чат идут через `FakePlayerUnderstanding`: интенты с опечатками, память (кто убивал/помогал/соклановец/враг по кв), позиция на 15 минут (второй раз «я ж сказал: …»), молчание на первое сообщение незнакомца, реакция на капс, зеркалирование стиля, идиолект (свой смех, паразит, сленг, мат у трети), факты контекста (план: фарм/торговля/осада/переезд, событие: ап, ганг, профа, конец осады) и слоты (`{zone} {level} {mob} {town} {crowd} {drop} {clan} {enemyclan} {castle}`). Боты **разговаривают друг с другом**, когда рядом есть живой игрок: здороваются при встрече, задают вопросы (`bot_talk`: «как фарм», «дроп есть?», «какой лвл», «го в пати», «пк ходят?», «клан есть?»…), отвечают через тот же разбор интентов (до 3 реплик в цепочке), подхватывают жалобы и вопросы, поздравляют с лвлом, сплетничают. Зов на помощь при проигрываемом пвп — соклановцы в радиусе 1500 подтягиваются. LLM (Ollama) по умолчанию только для фраз без интента (`FakePlayerLlmPriority = seams`), `llm` — наоборот.
**Проверка, что они это делают, а не делают вид**: `do=stats` (сумма по населению), `do=stats&name=Ник` (один бот: убийства, опыт, лут, продано/куплено/адена, лавки, касты, отдыхи, реплики, пати, переезды, профы, осады, последнее действие), `/api/stats` (JSON), строка `FakePlayerTelemetry: last N min -> kills=+… exp=+… loot=+…` в логе раз в `FakePlayerStatsLogMinutes`, `FakePlayerChatLog = True` — каждая реплика в лог с каналом и швом. Оффлайн: `tools/run_harness.sh` (движок чата на реальных XML), `python tools/check_data.py` (пулы, слоты, швы, скиллы профилей).
Настройки — секция «SPP additions» в `game\config\Custom\FakePlayers.ini`: `FakePlayerLlmPriority`, `FakePlayerBotDialogues`, `FakePlayerEconomy`, `FakePlayerProfessionChange`, `FakePlayerSieges`, `FakePlayerSiegeAttackerClans`, `FakePlayerSiegeAttackPlayerCastles`, `FakePlayerStatsLogMinutes`, `FakePlayerChatLog`.
Ограничения: NPC-режим ботов (`FakePlayerProgression = True`) не поддерживается — шаблонов `fpc_spp_*` в сервере нет; смертность у магов и на спавне в центре стай выше, чем у живых (см. `AUDIT.md`).
---
Сборка от 2026-08-25 (пак `server_interlude.zip`). Население 1–76 с настоящей прокачкой, всё включено по умолчанию. Сборка от 2026-08-25 (пак `server_interlude.zip`). Население 1–76 с настоящей прокачкой, всё включено по умолчанию.
## Что в паке ## Что в паке
+18
View File
@@ -5,6 +5,24 @@
Формат: `http://127.0.0.1:7780/api/cmd?do=КОМАНДА&name=НИК_БОТА&arg=АРГУМЕНТ` Формат: `http://127.0.0.1:7780/api/cmd?do=КОМАНДА&name=НИК_БОТА&arg=АРГУМЕНТ`
`name` пустой — берётся случайный живой бот. В дашборде клик по боту в списке подставляет его ник автоматически. `name` пустой — берётся случайный живой бот. В дашборде клик по боту в списке подставляет его ник автоматически.
## Телеметрия и экономика (SPP 3)
| Команда | Что делает |
|---|---|
| `do=stats` | счётчики по всему населению: kills, exp, loot, itemsSold, adenaEarned/Spent, stores, skillsCast, rests, lines, replies, parties, migrations, professions, sieges + сколько сейчас в бою/сидит/торгует/в пати/на осаде |
| `do=stats&name=Ник` | то же для одного бота + последнее действие, шоты, инвентарь, HP |
| `do=list` | 25 ботов: класс, характер, зона, HP, убийства/смерти, последнее действие |
| `do=brain&name=Ник` | роль, скиллы профиля (+/-), цель и её HP, бьёт/кастует/сидит, оружие, шоты, число бафов, атака/защита |
| `do=town` | бот делает «поход в город» прямо на месте: продаёт хлам, докупает шоты/банки, бафается; ответ — сколько продано/куплено и адена |
| `do=trade` | лавка в городе своего уровня (если продавать нечего — выдаётся образец товара) |
| `do=profession` | попытка взять следующую профу (сообщит, если не положена по уровню) |
| `do=talk&name=Бот&arg=ТвойНик` | два бота телепортируются к тебе и начинают диалог (вопрос → ответ через разбор интентов) |
| `do=invite&arg=ТвойНик` | бот прыгает к тебе и **приглашает в пати** (окно приглашения у тебя) |
| `do=siege&arg=Giran` | форс-осада: регистрирует бот-кланы атакующими и запускает осаду движка; `do=siegeend&arg=Giran` — закончить; `do=siegeinfo` — расписание, зарегистрированные кланы, сколько ботов в бою |
| `do=online&arg=charId` | подгрузить конкретного сид-персонажа в мир (так осадный менеджер подтягивает лидеров кланов) |
`/api/stats` — то же, что `do=stats`, в JSON; `/api/sieges` — как `do=siegeinfo`.
## Уровень и переезд ## Уровень и переезд
| Команда | Что делает | | Команда | Что делает |
+9 -1
View File
@@ -86,4 +86,12 @@ mysql -uroot -p l2jmobiusinterlude -e "UPDATE accounts SET accessLevel=100 WHERE
## Боты ## Боты
Всё включено из коробки: 200 персонажей 1–76 с настоящей прокачкой, LLM-чат (нужна Ollama + `ollama pull gemma3`, иначе шаблонные фразы). Настройки — `game\config\Custom\FakePlayers.ini`, детали — `BOTS.md`. Всё включено из коробки: 500 headless-игроков 1–76 с настоящей прокачкой, экономикой, осадами и чатом (Ollama опциональна: `ollama pull gemma3`, иначе шаблонный движок — он и так основной). Настройки — `game\config\Custom\FakePlayers.ini`, детали — `BOTS.md`, команды проверки — `DEBUG.md`.
## Пересборка после правок
```
powershell -ExecutionPolicy Bypass -File build.ps1
```
Соберёт `GameServer.jar` (нужны JDK 25 + Ant в PATH), разложит оверлей из `src_mobius\...\dist` в `server\` и перезапустит контейнер `game`. Только данные без сборки: `build.ps1 -DeployOnly`.
+29
View File
@@ -0,0 +1,29 @@
# L2 Interlude SPP — карта проекта
Сервер L2J Mobius CT_0 Interlude с населением из headless-игроков (настоящие `Player` без клиента): фарм, торговля, кланы, войны, осады, чат с характером и памятью. Подробности по ботам — `BOTS.md`, дебаг — `DEBUG.md`, установка — `INSTALL.md`, ревизия от 03.09 — `AUDIT.md`.
## Что где лежит
| Путь | Что это |
|---|---|
| `src_mobius/mobius/L2J_Mobius_CT_0_Interlude/java` | **Исходники сервера** (ванильный Mobius + наши правки). Всё по ботам: `gameserver/managers/FakePlayer*.java` |
| `src_mobius/mobius/L2J_Mobius_CT_0_Interlude/dist` | **Оверлей датапака**: только наши файлы — данные ботов (`game/data/FakePlayer*.xml`), конфиги (`game/config`), чат-хендлеры (`game/data/scripts/handlers/chat`), SQL-сиды (`db_installer/sql/spp_*.sql`) |
| `server/` | **Развёрнутый сервер** (ванильный датапак + оверлей + jar + geodata). Не в git. Docker монтирует эту папку |
| `tools/` | Сборка/деплой (`build.sh`, `deploy.sh`), проверки данных (`check_data.py`), оффлайн-тест чата (`run_harness.sh` + `harness/ChatHarness.java`), пересчёт зон по спавнам (`fix_zones.py`) |
| `build.ps1` | Windows: `ant jar` + деплой оверлея и jar в `server\` + `docker compose restart game` |
| `docker/` | Dockerfile, compose, entrypoint (копия лежит в `server/docker`) |
| `nickgen.py`, `nickgen.html`, `import-crests.py` | Генератор ников, импорт гербов |
| `start.ps1`, `reset-bots.ps1`, `cleanup-docker.ps1` | Запуск, пересид ботов, чистка докера |
Устаревшее (в `.gitignore`, можно удалить): `patches/` (временный мост между копиями, всё влито), `src_mobius_interlude.zip`, `ziAuQ8He`, `ziVsvreY` (снимки исходников до слияния), `src/` и `l2j-lisvus/` (заброшенная попытка на L2J Lisvus), `server/game/data/data.rar`, `server/game/data/html.rar` (154 МБ мусора), `server/backup/*.jar.pre-*` (старые сборки).
## Git
История: `f520c66` — ванильный Mobius (коммит 9be7adbe5a от 25.08.2026, `https://gitlab.com/MobiusDevelopment/L2J_Mobius`), дальше — наши изменения. `git diff f520c66 -- src_mobius` показывает весь наш патч поверх ванили; обновление на новый Mobius — это `git diff` ванильных ревизий и перенос.
## Рабочий цикл
1. Правки — в `src_mobius/...` (java или `dist`-оверлей).
2. `powershell -ExecutionPolicy Bypass -File build.ps1` — соберёт jar, разложит оверлей в `server\`, перезапустит `game`. `-DeployOnly` — если менялись только XML/конфиги, `-NoRestart` — без рестарта.
3. Проверки без сервера: `python tools/check_data.py` (данные), `tools/run_harness.sh` (движок чата на реальных XML; нужен JDK 25).
4. Живьём: `http://127.0.0.1:7780/api/cmd?do=stats` — счётчики того, что боты реально делают (убийства, лут, продажи, покупки, осады, реплики); `FakePlayerChatLog = True` в `FakePlayers.ini` — все реплики ботов в лог.
+6 -9
View File
@@ -1,14 +1,11 @@
# src_mobius — рабочие исходники сервера # src_mobius — рабочие исходники сервера
Рабочая копия исходников L2J Mobius CT_0 Interlude. **Все правки кода и данных ботов делаются здесь** — это источник истины. Рабочая копия исходников L2J Mobius CT_0 Interlude под git (корень репозитория — `I:\coding\l2sp`). **Все правки кода и данных ботов делаются здесь** — это источник истины.
Структура (только то, что нужно для разработки): - `mobius/L2J_Mobius_CT_0_Interlude/java/` — полные исходники сервера. Всё по ботам: `java/org/l2jmobius/gameserver/managers/FakePlayer*.java`
- `mobius/L2J_Mobius_CT_0_Interlude/dist/` — оверлей датапака: только наши файлы (данные ботов и xsd в `game/data`, конфиги в `game/config`, чат-хендлеры в `game/data/scripts`, сиды в `db_installer/sql`), плюс `libs/` — jar-зависимости сборки
- `mobius/L2J_Mobius_CT_0_Interlude/build.xml` — ant-сборка (JDK 25); результат в `mobius/build/dist/libs/` (не в git)
- `mobius/L2J_Mobius_CT_0_Interlude/java/` — полные исходники сервера (1630 файлов). Всё по фейк-игрокам: `java/org/l2jmobius/gameserver/managers/FakePlayer*.java` Сборка и деплой: `build.ps1` в корне (Windows) или `tools/build.sh` + `tools/deploy.sh`. Деплой копирует оверлей поверх `../server/` и jar в `../server/libs/`.
- `mobius/L2J_Mobius_CT_0_Interlude/dist/game/data/` — данные чат-системы: `FakePlayerChatLines.xml` (швы+правила), `FakePlayerPools.xml` (рекурсивные пулы), `FakePlayerIntents.xml` (лексикон понимания), xsd
- `mobius/L2J_Mobius_CT_0_Interlude/dist/libs/` — jar-зависимости для сборки
- `build.xml` — ant-сборка (Java 25)
Деплой: собранный `GameServer.jar``../server/libs/`, XML-данные → `../server/game/data/`. Бэкапы jar лежат в `../server/backup/`. Ванильная база — Mobius `9be7adbe5a` (первый коммит репозитория); `git diff f520c66 -- src_mobius` показывает весь наш патч.
`../src_mobius_interlude.zip` — замороженный архив (состояние на момент переезда сюда), больше не обновляется. Полный датапак (config, скрипты и т.д.) при необходимости достаётся из него.