# Круг Объединение игроков: основать свой Круг, вступить в чужой, выйти; роли главы и участника. Это этап 7 плана. Территория Круга — крепость, казна, гарнизон — будет на этапе 8, поверх этого модуля. - **Сборка:** `Bogatyri.Circle` (без Unity — когда появится сервер, список Кругов и состав будут приходить с него). - **Папка:** `Assets/Scripts/Modules/Circle`. - **Зависит от:** ядра. ## Контракт `ICircle` | Член | Что делает | | --- | --- | | `Current` | Круг игрока (`CircleInfo`: id, название, участники); `null` — игрок не в Круге. | | `IsInCircle`, `IsLeader` | В Круге ли игрок и глава ли он. | | `MaxMembers` | Мест в Круге — 30. | | `GetCircles()` | Все Круги, в которые можно вступить. | | `TryCreate(name, out error)` | Основать Круг; создатель становится главой. | | `TryJoin(circleId, out error)` | Вступить участником. | | `Leave()` | Выйти. | Получить: `GameServices.Get()`. Регистрирует `App/GameModules`. ## Правила | Ситуация | Что происходит | | --- | --- | | Основать или вступить, уже состоя в Круге | Нельзя: сначала нужно выйти. Игрок состоит только в одном Круге. | | Название Круга | От 3 до 24 символов, без `\|`, `<`, `>` и переводов строки. Название не должно повторять существующее, регистр не важен. | | Круг полон (30 из 30) | Вступить нельзя. | | Выходит глава, в Круге есть другие | Главой становится старейший участник. | | Выходит единственный участник | Круг распускается. | ## События **Публикует:** - `CircleJoinedEvent` — игрок вступил (`Created = false`) или основал Круг (`Created = true`); - `CircleLeftEvent` — игрок вышел (`Disbanded = true` — Круг распущен). **Слушает:** ничего. На события Круга подписан модуль Чата: канал «Круг» становится перепиской текущего Круга игрока. ## Сохранение Секция `"circle"`. Модуль без Unity, поэтому это не JSON, а простые строки: ``` joined= created=|<название>|<роль игрока: Leader или Member> ``` Демо-Круги не сохраняются: они одинаковые при каждом запуске. Сброс сохранений (`ResetState`): игрок ни в каком Круге, его собственные Круги распущены. ## Интерфейс (слой приложения) `Assets/Scripts/Social/CircleWindow.cs` — окно на `UIKit`. Открывается кнопкой «Круг» внизу карты мира. **Игрок не в Круге:** - пояснение и кнопка «Основать свой Круг» — спрашивает название; - список Кругов: герб, название, глава, «участников N / 30», кнопка «Вступить» или «Мест нет». **Игрок в Круге:** - название и роль игрока; - состав: каждый участник с ролью, сам игрок выделен; - кнопка «Покинуть Круг» с подтверждением; в подтверждении сказано, станет ли кто-то главой или Круг будет распущен. ## Файлы | Файл | Что это | | --- | --- | | `Modules/Circle/CircleService.cs` | Реализация `ICircle` и `ISaveParticipant`, демо-Круги. | | `Modules/Core/Contracts/ModuleContracts.cs` | `ICircle`, `CircleInfo`, `CircleMember`, `CircleRole`. | | `Modules/Core/Events/GameEvents.cs` | `CircleJoinedEvent`, `CircleLeftEvent`. | | `Social/CircleWindow.cs` (слой приложения) | Окно Круга. | ## Решения и план - **Сейчас других игроков нет.** 10 Кругов из рейтинга заполнены выдуманными участниками (от 6 до 30), один Круг полный — чтобы было видно «Мест нет». - **Этап 8 — территория Круга:** - совместный штурм крепости; - казна и восстановление (500 дерева, 300 камня, 100 металла, 50 золота, 300 еды для T1); - гарнизон и рабочие от участников; - добыча в казну, уровни крепости, содержание. - **Рейтинг Кругов** пока на своих демо-данных (`RatingService`). Его нужно перевести на `ICircle`, чтобы в нём появлялся и Круг игрока. - **Роли.** Пока только глава и участник. Заместители, приглашения, исключение участника и заявки на вступление — после сервера. - **Сервер (этап 10):** сетевая реализация `ICircle`. ## Журнал изменений | Дата | Кто | Что | | --- | --- | --- | | 19.10.2026 | Claude | Модуль создан: `ICircle` (основать, вступить, выйти, роли), события `CircleJoinedEvent` / `CircleLeftEvent`, секция сохранения `"circle"`, сброс, демо-Круги, окно «Круг» на карте мира, тесты. |