Обсуждение участника:WikiHampter/Разработка:Структура базы данных
База данных Space Station 14 (DeadSpace)
Проект: Content.Server.Database
ORM: Entity Framework Core
Движок: PostgreSQL 16 (production) / SQLite (dev)
Соглашение об именах: Все имена таблиц, колонок, индексов и ограничений записываются в snake_case автоматически через кастомный конвеншен.
База данных — общая для игрового сервера и админ-панели. Всего 41 таблица, охватывающая игроков, персонажей, наказания, администрирование, логи и форковые расширения DeadSpace.
Список таблиц
- preference — Настройки игрока
- profile — Профиль персонажа
- job — Предпочтения по работе
- antag — Предпочтения по антагонистам
- trait — Черты характера
- profile_role_loadout — Экипировка по ролям
- profile_loadout_group — Группа экипировки
- profile_loadout — Конкретный предмет экипировки
- assigned_user_id — Привязка никнейма к UUID
- player — Зарегистрированные игроки
- whitelist — Вайтлист (допуск на сервер)
- blacklist — Блэклист (блокировка на сервер)
- admin — Администраторы
- admin_flag — Индивидуальные флаги прав админов
- admin_rank — Ранги/группы админов
- admin_rank_flag — Флаги прав, привязанные к рангу
- server — Игровые серверы
- round — Игровые раунды
- player_round — Связь игроков с раундами (M:N)
- admin_log — Логи действий администраторов
- admin_log_player — Привязка логов админов к игрокам
- ban — Баны (серверные и ролевые в одной таблице)
- ban_address — IP-адреса, попадающие под бан
- ban_hwid — HWID (железо), попадающие под бан
- ban_player — Игроки (по UserId), попадающие под бан
- ban_role — Роли, попадающие под ролевой бан
- ban_round — Привязка бана к раунду, в котором он выдан
- unban — Снятие бана (кто и когда снял)
- server_ban_exemption — Исключения из банов для конкретных игроков
- connection_log — История подключений к серверу
- server_ban_hit — Срабатывания бана (кто был заблокирован при попытке зайти)
- play_time — Наигранное время по ролям
- uploaded_resource_log — Аудит загрузки ресурсов на сервер
- admin_notes — Заметки администраторов на игроков
- admin_watchlists — Вотчлисты (список наблюдения)
- admin_messages — Сообщения администраторов игрокам
- role_whitelists — Вайтлист на конкретные роли
- ban_template — Шаблоны банов для админ-панели
- ipintel_cache — Кэш результатов IPIntel (определение VPN/прокси)
- bi_stats — Статистика раундов (форк DeadSpace)
- information_topics — Информационные страницы (форк DeadSpace)
1. preference
Таблица хранит настройки игрового профиля пользователя. Каждому зарегистрированному пользователю соответствует ровно одна запись. Создаётся автоматически при первом входе на сервер.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| preference_id | int | PK, автоинкремент | Уникальный идентификатор записи настроек |
| user_id | Guid | Unique | Уникальный идентификатор пользователя (SS14 Central). Связывает таблицу с внешними системами аутентификации |
| selected_character_slot | int | Номер выбранного слата персонажа (0-5). Определяет, какой персонаж будет загружен при входе в раунд | |
| admin_ooc_color | string | Цвет текста в OOC-чате для администраторов. Позволяет настроить отображение сообщений в чате | |
| construction_favorites | string[] | Список избранных конструкций (для быстрого строительства). Хранится как массив строк |
2. profile
Профиль персонажа игрока. Каждый пользователь может иметь до 6 персонажей (слоты 0-5). Содержит полную информацию о внешности, имени и настройках персонажа.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| profile_id | int | PK, автоинкремент | Уникальный идентификатор профиля |
| slot | int | Номер слота (0-5). Определяет позицию персонажа в списке выбора | |
| char_name | string | Имя персонажа, отображаемое в игре | |
| flavor_text | string | Описание внешности и характера персонажа. Видно другим игрокам при осмотре | |
| age | int | Возраст персонажа (игровая роль, не настоящий возраст игрока) | |
| sex | string | Пол персонажа (Male/Female) | |
| gender | string | Грамматический род (он/она/они) для корректного отображения в чате | |
| species | string | Раса персонажа (Human, IPC, Diona, Vox, Slime и т.д.) | |
| voice | string | Тип голоса для TTS (Text-To-Speech). Добавлено в форке Corvax | |
| markings | jsonb (PG) / blob (SQLite) | Nullable | Список татуировок, шрамов и других отметок на теле персонажа в JSON-формате |
| hair_name | string | Название причёски | |
| hair_color | string | Цвет волос (HEX-код) | |
| facial_hair_name | string | Название растительности на лице | |
| facial_hair_color | string | Цвет растительности на лице (HEX-код) | |
| eye_color | string | Цвет глаз (HEX-код) | |
| skin_color | string | Цвет кожи (HEX-код) | |
| spawn_priority | int | Default 0 | Приоритет появления. Определяет, какой персонаж будет загружен, если подходят несколько |
| pref_unavailable | int | 0=StayInLobby, 1=SpawnAsOverflow | Поведение, если любимая работа недоступна: остаться в лобби или зайти за overflow-роль |
| preference_id | int | FK → preference(preference_id) | Ссылка на запись настроек пользователя, которому принадлежит этот персонаж |
Уникальный индекс: (slot, preference_id) — гарантирует, что у одного пользователя не будет двух персонажей в одном слоте.
3. job
Предпочтения по работе (роли) для конкретного персонажа. Игрок указывает, кем хочет играть, и приоритет каждой роли.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| job_id | int | PK, автоинкремент | Уникальный идентификатор предпочтения |
| profile_id | int | FK → profile(profile_id) | Ссылка на профиль персонажа |
| job_name | string | Название работы (прототип: StationEngineer, MedicalDoctor, SecurityOfficer...) | |
| priority | int | 0=Never, 1=Low, 2=Medium, 3=High | Приоритет: Never — никогда не спауниться за эту роль, High — хочу больше всего |
Уникальный индекс: (profile_id, job_name) — у одного персонажа не может быть двух настроек для одной работы.
Фильтрованный индекс: IX_job_one_high_priority WHERE priority = 3 — гарантирует, что только одна работа может иметь приоритет High (чтобы SS14 мог автоматически определить "любимую" работу).
4. antag
Список антагонистов, которых игрок хочет (или не хочет) получать.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| antag_id | int | PK, автоинкремент | Уникальный идентификатор |
| profile_id | int | FK → profile(profile_id) | Ссылка на профиль персонажа |
| antag_name | string | Название антагониста (Traitor, Changeling, NukeOps и т.д.) |
Уникальный индекс: (profile_id, antag_name) — один персонаж не может иметь дублирующихся настроек по одному антагонисту. Отсутствие записи = настройка по умолчанию (разрешено).
5. trait
Черты характера персонажа. Позволяют добавить персонажу особые свойства (положительные или отрицательные), влияющие на геймплей.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| trait_id | int | PK, автоинкремент | Уникальный идентификатор |
| profile_id | int | FK → profile(profile_id) | Ссылка на профиль персонажа |
| trait_name | string | Название черты (LightweightDrunk, Paracusia, Liar, Spacer...) |
Уникальный индекс: (profile_id, trait_name) — персонаж не может взять одну черту дважды.
6. profile_role_loadout
Привязка набора экипировки (loadout) к конкретной роли для персонажа. Позволяет настроить, с какими предметами персонаж появляется, если зашёл за определённую роль.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| profile_role_loadout_id | int | PK, автоинкремент | Уникальный идентификатор |
| profile_id | int | FK → profile(profile_id) | Ссылка на профиль персонажа |
| role_name | string | Название роли, для которой применяется этот набор (например, JobStationEngineer) | |
| entity_name | string(256) | Nullable | Название предмета-прототипа, который будет выдан (например, ClothingBackpackDuffelEngineering) |
7. profile_loadout_group
Группа предметов внутри набора экипировки для роли. Позволяет разделить loadout на категории (например, "Рюкзаки", "Обувь", "Головные уборы").
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| profile_loadout_group_id | int | PK, автоинкремент | Уникальный идентификатор группы |
| profile_role_loadout_id | int | FK → profile_role_loadout(profile_role_loadout_id) | Ссылка на набор экипировки для роли |
| group_name | string | Название группы предметов (Backpack, Shoes, Head, Uniform...) |
8. profile_loadout
Конкретный предмет внутри группы экипировки.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| profile_loadout_id | int | PK, автоинкремент | Уникальный идентификатор |
| profile_loadout_group_id | int | FK → profile_loadout_group(profile_loadout_group_id) | Ссылка на группу экипировки |
| loadout_name | string | Название прототипа предмета (ClothingBackpackDuffelEngineering, ClothingHandsGlovesInsulated...) |
9. assigned_user_id
Сервисная таблица, которая хранит привязку никнейма игрока к его UUID (GUID пользователя в SS14 Central). Используется для быстрого поиска по имени и обратного поиска.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| assigned_user_id_id | int | PK, автоинкремент | Уникальный идентификатор |
| user_name | string | Unique | Имя пользователя (никнейм) |
| user_id | Guid | Unique | Уникальный идентификатор пользователя в SS14 Central |
10. player
Основная таблица игроков. Содержит запись о каждом игроке, который хотя бы раз подключался к серверу. Является центром связей: большинство других таблиц (баны, заметки, логи) ссылаются на player.user_id.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| player_id | int | PK, автоинкремент | Внутренний числовой идентификатор |
| user_id | Guid | Unique (Alternate Key) | Глобальный идентификатор игрока в SS14 Central. Используется как внешний ключ во всех связанных таблицах |
| first_seen_time | DateTime | Дата и время первого подключения игрока к серверу | |
| last_seen_user_name | string | Indexed | Последний известный никнейм игрока |
| last_seen_time | DateTime | Дата и время последнего подключения | |
| last_seen_address | inet (IPAddress) | Последний известный IP-адрес игрока | |
| last_seen_hwid | byte[] | Nullable, Owned | Последний известный HWID (аппаратный идентификатор) — часть TypedHwid |
| last_seen_hwid_type | int | Default=Legacy(0) | Тип HWID (для совместимости с разными методами снятия отпечатка) |
| last_read_rules | DateTime | Nullable | Дата, когда игрок последний раз прочитал правила сервера |
11. whitelist
Список игроков, допущенных на сервер (белый список). Если на сервере включён вайтлист, только пользователи из этой таблицы могут подключиться.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| user_id | Guid | PK | Уникальный идентификатор пользователя, допущенного на сервер |
12. blacklist
Список игроков, которым навсегда запрещён вход на сервер (чёрный список). Проверяется до вайтлиста — если игрок в блэклисте, он не сможет зайти, даже если он в вайтлисте.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| user_id | Guid | PK | Уникальный идентификатор заблокированного пользователя |
13. admin
Таблица администраторов сервера. Содержит учётные записи людей, имеющих доступ к админ-инструментам.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| user_id | Guid | PK | Уникальный идентификатор пользователя (должен совпадать с player.user_id) |
| title | string | Nullable | Должность/звание администратора (например, "Главный администратор", "Модератор") |
| deadminned | bool | Флаг временного снятия админ-прав. Если true — администратор не может использовать админ-инструменты до повторной активации | |
| suspended | bool | Флаг отстранения. Если true — администратор отстранён от должности вышестоящим админом | |
| admin_rank_id | int | Nullable, FK → admin_rank(admin_rank_id), ON DELETE SET NULL | Ссылка на ранг администратора. SET NULL при удалении ранга |
14. admin_flag
Индивидуальные флаги прав для конкретного администратора. Позволяют точечно выдавать или забирать права, не создавая отдельный ранг.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| admin_flag_id | int | PK, автоинкремент | Уникальный идентификатор |
| flag | string | Название флага (Admin, Ban, Notes, ServerControl, Debug...) | |
| negative | bool | Если true — флаг работает в отрицание (забирает право). Если false — добавляет право | |
| admin_id | Guid | FK → admin(user_id) | Ссылка на администратора |
Уникальный индекс: (flag, admin_id) — один флаг не может быть назначен админу дважды.
15. admin_rank
Ранги/группы администраторов. Позволяют группировать несколько флагов прав в одну роль (например, "Модератор", "Старший администратор", "Хост").
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| admin_rank_id | int | PK, автоинкремент | Уникальный идентификатор ранга |
| name | string | Название ранга (Moderator, SeniorAdmin, Host...) |
16. admin_rank_flag
Флаги прав, привязанные к рангу. Когда администратору назначается ранг, он автоматически получает все флаги этого ранга.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| admin_rank_flag_id | int | PK, автоинкремент | Уникальный идентификатор |
| flag | string | Название флага права | |
| admin_rank_id | int | FK → admin_rank(admin_rank_id) | Ссылка на ранг |
Уникальный индекс: (flag, admin_rank_id) — флаг не может быть назначен рангу дважды.
17. server
Справочная таблица игровых серверов. Позволяет одному игровому процессу (SS14) управлять несколькими серверами (например, "Основной", "Тестовый", "Событийный") и разграничивать данные между ними.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| server_id | int | PK, автоинкремент | Уникальный идентификатор сервера |
| name | string | Название сервера (DeadSpace, DeadSpace-Test, DeadSpace-Event...) |
18. round
Таблица игровых раундов. Каждый запуск новой игровой сессии создаёт новую запись в этой таблице. Раунд начинается, когда на сервере запускается новый раунд, и заканчивается при его завершении.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| round_id | int | PK, автоинкремент | Уникальный номер раунда |
| start_date | DateTime | Nullable, Indexed | Дата и время начала раунда |
| server_id | int | FK → server(server_id) | Сервер, на котором прошёл раунд |
19. player_round
Промежуточная таблица для связи "многие-ко-многим" между игроками и раундами. Показывает, какие игроки участвовали в каких раундах.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| players_id | int | Composite PK, FK → player(player_id) | Идентификатор игрока |
| rounds_id | int | Composite PK, FK → round(round_id) | Идентификатор раунда |
Составной первичный ключ: (players_id, rounds_id) — один игрок может быть отмечен в раунде только один раз.
20. admin_log
Журнал действий администраторов. Фиксирует все значимые действия: баны, кики, телепортации, спавн предметов и другие админ-команды.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| round_id | int | Composite PK, FK → round(round_id) | Номер раунда, в котором было совершено действие |
| admin_log_id | int | Composite PK | Номер лога в рамках раунда (нумерация своя для каждого раунда) |
| type | int | Indexed | Тип действия (103 типа: AdminMessage, Ban, Kick, Teleport, Spawn, Smoke...) |
| impact | sbyte | Степень воздействия на сервер/игроков (Extreme, High, Medium, Low) | |
| date | DateTime | Indexed | Дата и время действия |
| message | string | GIN index (tsvector) | Текстовое описание действия для полнотекстового поиска |
| json | jsonb | JSON-данные с деталями действия (сохраняет параметры команды) |
Составной PK: (round_id, admin_log_id). Каждый раунд начинает нумерацию логов с 1. Это сделано для того, чтобы логи оставались читаемыми даже при архивации старых раундов.
21. admin_log_player
Связывает логи администраторов с игроками, которых эти логи касаются. Позволяет найти все админ-действия по конкретному игроку.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| round_id | int | Composite PK | Номер раунда |
| log_id | int | Composite PK | Номер лога |
| player_user_id | Guid | Composite PK, FK → player(user_id) | Идентификатор игрока, которого касается это админ-действие |
Составной PK: (round_id, log_id, player_user_id)
Внешний ключ: (round_id, log_id) → admin_log(round_id, admin_log_id)
Внешний ключ: player_user_id → player(user_id)
22. ban
Основная таблица наказаний: баны и ролевые баны. Раньше было две отдельные таблицы (server_ban и server_role_ban), но их объединили в одну с полем-дискриминатором type.
Логика работы бана:
- Серверный бан (type=0) — запрещает вход на сервер полностью. Проверяется по трём критериям одновременно: IP, HWID, UserId (все три должны совпадать, чтобы бан считался "попаданием")
- Ролевой бан (type=1) — запрещает играть за конкретную роль (работу или антагониста). Не проверяет IP/HWID.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| ban_id | int | PK, автоинкремент | Уникальный идентификатор бана |
| type | byte | 0=Server, 1=Role | Тип бана: серверный или ролевой |
| playtime_at_note | TimeSpan | Наигранное время игрока на момент выдачи бана (для контекста) | |
| ban_time | DateTime | Дата и время выдачи бана | |
| expiration_time | DateTime | Nullable | Дата и время истечения бана. Если null — бан перманентный |
| reason | string | Причина бана, введённая администратором | |
| severity | int | Серьёзность нарушения (лёгкое, среднее, тяжёлое) | |
| banning_admin | Guid | Nullable, FK → player(user_id), ON DELETE SET NULL | Администратор, выдавший бан. SET NULL при удалении админа (GDPR) |
| last_edited_by_id | Guid | Nullable, FK → player(user_id), ON DELETE SET NULL | Кто последний раз редактировал бан |
| last_edited_at | DateTime | Nullable | Когда бан был последний раз отредактирован |
| exempt_flags | int | Флаги исключений, применённые к бану (например, игрок в датацентре) | |
| auto_delete | bool | Флаг автоматического удаления по истечении срока | |
| hidden | bool | Флаг скрытого бана (не показывается в публичных списках, виден только админам) |
Проверка: NoExemptOnRoleBan: type = 0 OR exempt_flags = 0 — для ролевых банов запрещено указывать флаги исключений.
23. ban_address
IP-адреса, которые попадают под бан. Когда админ банит игрока, текущий IP-адрес нарушителя сохраняется в эту таблицу. При попытке подключения сервер проверяет IP по этой таблице.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| ban_address_id | int | PK, автоинкремент | Уникальный идентификатор |
| address | inet (PG) / string (SQLite) | GiST index (PG) | IP-адрес или подсеть под баном (например: 192.168.1.5 или 192.168.0.0/16) |
| ban_id | int | FK → ban(ban_id) | Ссылка на бан |
Уникальный индекс: (address, ban_id) — один адрес не может быть дважды привязан к одному бану.
Проверка (PG): AddressNotIPv6MappedIPv4 — запрещает сохранение IPv4-адресов в формате IPv6-mapped (::ffff:192.168.1.1).
24. ban_hwid
Аппаратные идентификаторы (HWID), которые попадают под бан. HWID — это уникальный отпечаток железа игрока, позволяющий идентифицировать его даже при смене IP или аккаунта.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| ban_hwid_id | int | PK, автоинкремент | Уникальный идентификатор |
| hwid | byte[] | Owned (TypedHwid) | Массив байт — отпечаток аппаратного обеспечения |
| hwid_type | int | Owned, Default=Legacy(0) | Тип HWID (на будущее, для разных алгоритмов снятия отпечатка) |
| ban_id | int | FK → ban(ban_id) | Ссылка на бан |
Уникальный индекс: (hwid_type, hwid, ban_id) — один HWID не может быть дважды привязан к одному бану.
25. ban_player
Игроки (по UserId), которые попадают под бан. Это основной идентификатор для проверки бана — проверяется, находится ли UserId подключающегося игрока в этой таблице.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| ban_player_id | int | PK, автоинкремент | Уникальный идентификатор |
| user_id | Guid | Идентификатор забаненного игрока | |
| ban_id | int | FK → ban(ban_id) | Ссылка на бан |
Уникальный индекс: (user_id, ban_id) — один игрок не может быть дважды привязан к одному бану.
26. ban_role
Роли, которые попадают под ролевой бан (type=1). Например, бан на роль "Captain" запрещает игроку заходить за капитана.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| ban_role_id | int | PK, автоинкремент | Уникальный идентификатор |
| role_type | string | Тип роли: "Job" (работа) или "Antag" (антагонист) | |
| role_id | string | Идентификатор прототипа роли (например, "Captain", "Traitor", "Warden") | |
| ban_id | int | FK → ban(ban_id) | Ссылка на бан |
Уникальный индекс: (role_type, role_id, ban_id) — одна роль не может быть дважды привязана к одному бану.
27. ban_round
Связывает бан с раундом, в котором он был выдан. Носит информационный характер — позволяет понять, в каком раунде произошло нарушение.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| ban_round_id | int | PK, автоинкремент | Уникальный идентификатор |
| ban_id | int | FK → ban(ban_id) | Ссылка на бан |
| round_id | int | FK → round(round_id) | Ссылка на раунд |
Уникальный индекс: (round_id, ban_id) — бан не может быть привязан к одному раунду дважды.
28. unban
Запись о снятии бана. Когда администратор разбанивает игрока, создаётся запись в этой таблице, а сам бан помечается как снятый (через наличие unban-записи). Важно: бан физически не удаляется из БД, а лишь деактивируется.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| unban_id | int | PK, автоинкремент | Уникальный идентификатор снятия бана |
| ban_id | int | Unique, FK → ban(ban_id) | Ссылка на бан, который был снят (One-to-One: один бан может быть снят только один раз) |
| unbanning_admin | Guid | Nullable | Администратор, снявший бан. Null возможен, если бан истёк автоматически (auto_delete) |
| unban_time | DateTime | Дата и время снятия бана |
29. server_ban_exemption
Исключения из проверки банов для конкретных игроков. Позволяет игроку подключаться, даже если его IP или HWID попадает под автоматический бан (например, для датацентров или VPN).
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| user_id | Guid | PK | Игрок, которому выдано исключение |
| flags | int | Битовая маска флагов исключения: None=0, Datacenter=1, IP=2, BlacklistedRange=4, All=int.MaxValue |
Проверка: FlagsNotZero: flags != 0 — исключение должно иметь хотя бы один флаг (бессмысленная пустая запись запрещена).
30. connection_log
Журнал всех попыток подключения к серверу. Записывается каждая попытка войти на сервер — удачная или неудачная. Основной инструмент для расследования нарушений (поиск по IP, HWID, времени).
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| connection_log_id | int | PK, автоинкремент | Уникальный идентификатор подключения |
| user_id | Guid | Indexed | Идентификатор игрока, пытавшегося подключиться |
| user_name | string | Никнейм игрока на момент подключения | |
| time | DateTime | Indexed | Дата и время попытки подключения |
| address | inet (IPAddress) | IP-адрес, с которого подключался игрок | |
| hwid | byte[] | Nullable, Owned (TypedHwid) | HWID игрока (аппаратный отпечаток) |
| hwid_type | int | Default=Legacy(0) | Тип HWID |
| denied | byte | Nullable (ConnectionDenyReason) | Причина отказа, если подключение было отклонено: 0=Ban, 1=Whitelist, 2=Full, 3=Panic, 4=BabyJail, 5=IPChecks, 6=NoHwid |
| server_id | int | Default=0, FK → server(server_id), ON DELETE SET NULL | Сервер, на который пытались подключиться |
| trust | float | Уровень доверия к подключению (на основе IPIntel или других проверок). 0 = не доверяем (VPN), 1 = доверяем |
Проверка (PG): AddressNotIPv6MappedIPv4 — запрет IPv6-mapped формата.
31. server_ban_hit
Журнал "попаданий" бана. Когда игрок пытается подключиться, его данные проверяются по активным банам, и если найдено совпадение — запись об этом попадает сюда. Носит статистический характер.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| server_ban_hit_id | int | PK, автоинкремент | Уникальный идентификатор |
| ban_id | int | FK → ban(ban_id) | Бан, по которому было попадание |
| connection_id | int | FK → connection_log(connection_log_id) | Попытка подключения, которая вызвала срабатывание |
32. play_time
Наигранное время игрока по каждому трекеру (роли). Используется для систем, требующих минимального наигранного времени (например, ролевой вайтлист на капитана требует N часов за инженера).
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| play_time_id | int | PK, автоинкремент | Уникальный идентификатор |
| player_id | Guid | Идентификатор игрока | |
| tracker | string | Название трекера — роль или категория (например, "JobStationEngineer", "Overall", "Antag") | |
| time_spent | TimeSpan | Общее время, проведённое за эту роль |
Уникальный индекс: (player_id, tracker) — у одного игрока может быть только одна запись времени по каждому трекеру.
33. uploaded_resource_log
Журнал загрузки пользовательских ресурсов на сервер. Фиксирует, кто, когда и какой файл загрузил. Используется для модерации контента.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| uploaded_resource_log_id | int | PK, автоинкремент | Уникальный идентификатор |
| date | DateTime | Дата и время загрузки | |
| user_id | Guid | Идентификатор загрузившего игрока | |
| path | string | Путь к файлу на сервере | |
| data | byte[] | Содержимое загруженного файла (бинарные данные) |
34. admin_notes
Система заметок на игроков. Администраторы могут оставлять заметки о нарушениях, предупреждениях или любой другой информации, связанной с игроком. Поддерживает мягкое удаление (пометка deleted вместо физического удаления).
Отличия от бана: нота — это запись, которая не блокирует игрока. Она служит для информирования других администраторов.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| admin_notes_id | int | PK, автоинкремент | Уникальный идентификатор заметки |
| round_id | int | Nullable, FK → round(round_id) | Раунд, в котором была сделана заметка |
| player_user_id | Guid | Nullable, FK → player(user_id), CASCADE | Игрок, на которого написана заметка. CASCADE — удаление игрока удалит заметку |
| playtime_at_note | TimeSpan | Время игрока на момент создания заметки | |
| message | string(4096) | Текст заметки (до 4096 символов) | |
| severity | int | Серьёзность нарушения | |
| created_by_id | Guid | Nullable, FK → player(user_id), SET NULL | Администратор, создавший заметку |
| created_at | DateTime | Дата создания заметки | |
| last_edited_by_id | Guid | Nullable, FK → player(user_id), SET NULL | Кто последний раз редактировал |
| last_edited_at | DateTime | Дата последнего редактирования | |
| expiration_time | DateTime | Nullable | Дата автоматического удаления (null = бессрочно) |
| deleted | bool | Флаг мягкого удаления (true = заметка скрыта) | |
| deleted_by_id | Guid | Nullable, FK → player(user_id), SET NULL | Кто удалил заметку |
| deleted_at | DateTime | Nullable | Дата удаления |
| secret | bool | Флаг секретности: если true — заметка видна только администраторам с особыми правами |
Индекс: player_user_id — для быстрого поиска всех заметок по игроку.
35. admin_watchlists
Список наблюдения за игроками. Отличается от заметок тем, что вотчлист сигнализирует администраторам "обрати внимание на этого игрока" при его подключении или действиях.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| admin_watchlists_id | int | PK, автоинкремент | Уникальный идентификатор записи в вотчлисте |
| round_id | int | Nullable, FK → round(round_id) | Раунд, в котором игрок был добавлен в вотчлист |
| player_user_id | Guid | Nullable, FK → player(user_id), CASCADE | Игрок, за которым ведётся наблюдение |
| playtime_at_note | TimeSpan | Время игрока на момент добавления в список | |
| message | string(4096) | Причина наблюдения и что отслеживать | |
| created_by_id | Guid | Nullable, FK → player(user_id), SET NULL | Администратор, добавивший игрока |
| created_at | DateTime | Дата добавления в вотчлист | |
| last_edited_by_id | Guid | Nullable, FK → player(user_id), SET NULL | Кто последний раз редактировал запись |
| last_edited_at | DateTime | Дата последнего редактирования | |
| expiration_time | DateTime | Nullable | Дата истечения наблюдения |
| deleted | bool | Флаг мягкого удаления | |
| deleted_by_id | Guid | Nullable, FK → player(user_id), SET NULL | Кто убрал из списка наблюдения |
| deleted_at | DateTime | Nullable | Дата удаления |
Индекс: player_user_id
36. admin_messages
Сообщения от администраторов игрокам. Позволяет отправлять игрокам сообщения, которые они видят при следующем входе на сервер. В отличие от бана, сообщение не блокирует доступ — оно просто информирует.
Жизненный цикл сообщения:
- Администратор создаёт сообщение
- При подключении игрока сервер показывает сообщение
- Игрок помечает его как seen (просмотрено)
- Администратор может пометить сообщение как dismissed (закрыто)
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| admin_messages_id | int | PK, автоинкремент | Уникальный идентификатор сообщения |
| round_id | int | Nullable, FK → round(round_id) | Раунд, в котором было отправлено сообщение |
| player_user_id | Guid | Nullable, FK → player(user_id), CASCADE | Игрок-получатель сообщения |
| playtime_at_note | TimeSpan | Время игрока на момент отправки | |
| message | string(4096) | Текст сообщения | |
| created_by_id | Guid | Nullable, FK → player(user_id), SET NULL | Администратор, отправивший сообщение |
| created_at | DateTime | Дата отправки | |
| last_edited_by_id | Guid | Nullable, FK → player(user_id), SET NULL | Кто редактировал сообщение |
| last_edited_at | DateTime | Nullable | Дата редактирования |
| expiration_time | DateTime | Nullable | Дата истечения (сообщение автоматически скрывается) |
| deleted | bool | Флаг мягкого удаления | |
| deleted_by_id | Guid | Nullable, FK → player(user_id), SET NULL | Кто удалил сообщение |
| deleted_at | DateTime | Nullable | Дата удаления |
| seen | bool | Флаг: игрок прочитал сообщение | |
| dismissed | bool | Флаг: сообщение закрыто/архивировано |
Индекс: player_user_id
Проверка: NotDismissedAndSeen: NOT dismissed OR seen — нельзя закрыть сообщение, не прочитав его.
37. role_whitelists
Вайтлист на конкретные игровые роли. Позволяет ограничить доступ к определённым работам или антагонистам, выдавая разрешение только проверенным игрокам.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| player_user_id | Guid | Composite PK, FK → player(user_id) | Игрок, которому разрешена роль |
| role_id | string | Composite PK | Идентификатор роли (например, "Captain", "Warden", "HeadOfSecurity") |
Составной PK: (player_user_id, role_id) — игрок может иметь доступ к каждой роли только один раз.
38. ban_template
Шаблоны банов, предназначенные для использования в админ-панели. Позволяют администраторам быстро создавать баны, выбирая стандартную причину и длительность из предустановленного списка.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| ban_template_id | int | PK, автоинкремент | Уникальный идентификатор шаблона |
| title | string | Краткое название шаблона (например, "Гриферство", "Оскорбления", "Использование багов") | |
| length | TimeSpan | Длительность бана по умолчанию | |
| reason | string | Текст причины (будет подставлен в бан) | |
| exempt_flags | int | Флаги исключений по умолчанию | |
| severity | int | Серьёзность по умолчанию | |
| auto_delete | bool | Авто-удаление по умолчанию | |
| hidden | bool | Скрытый бан по умолчанию |
39. ipintel_cache
Кэш результатов IPIntel (сервис определения VPN/прокси). Позволяет не дёргать внешний API повторно при проверке одного и того же IP.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| ipintel_cache_id | int | PK, автоинкремент | Уникальный идентификатор |
| address | IPAddress | Unique | IP-адрес, который проверяли |
| time | DateTime | Время проверки | |
| score | float | Результат проверки: 0 — точно не прокси, 1 — точно прокси/VPN |
40. bi_stats
Форк DeadSpace. Таблица статистики раундов. Содержит информацию о режиме игры и победителе каждого раунда. Создана для BI-отчётности и дашбордов. Связь с round осуществляется по дате (±2 минуты), так как прямого внешнего ключа нет.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| bi_stats_id | int | PK, автоинкремент | Уникальный идентификатор |
| game_mode | string(128) | Indexed | Название игрового режима (Extended, Secret, Traitor, NukeOps, Revolution...) |
| winner | byte | 0=Crew, 1=Antagonist | Победитель раунда: экипаж станции или антагонисты |
| date | DateTime | Indexed | Дата и время окончания раунда |
41. information_topics
Форк DeadSpace. Таблица для создания и публикации информационных страниц прямо в игре и/или админ-панели. Позволяет создавать страницы правил, гайдов, объявлений и т.д.
| Колонка | Тип | Ограничения | Описание |
|---|---|---|---|
| information_topics_id | int | PK, автоинкремент | Уникальный идентификатор страницы |
| title | string(256) | Заголовок информационной страницы | |
| content_markdown | string | Содержимое страницы в формате Markdown (для редактирования) | |
| content_html | string | Содержимое страницы в формате HTML (сгенерировано из Markdown для отображения) | |
| author_id | Guid | Идентификатор автора | |
| author_name | string(128) | Имя автора (дублируется здесь для быстрого отображения без JOIN) | |
| created_at | DateTime | Indexed | Дата создания |
| updated_at | DateTime | Nullable | Дата последнего обновления |
| category | string(64) | Nullable, Indexed | Категория (например, "Правила", "Гайды", "Объявления") |
| is_pinned | bool | Indexed | Флаг закрепления (показывать вверху списка) |
| is_visible | bool | Default=true | Видимость страницы (false — черновик) |
| view_count | int | Default=0 | Счётчик просмотров |
Вспомогательный тип: TypedHwid
Embedded (owned) тип, используемый повторно в нескольких таблицах (player, connection_log, ban_hwid). Хранит HWID вместе с его типом для обратной совместимости.
| Поле | Тип | Описание |
|---|---|---|
| Hwid | byte[] | Аппаратный отпечаток (хэш компонентов ПК игрока) |
| Type | int | Тип HWID (сейчас только Legacy=0, зарезервировано под будущие форматы) |
Перечисляемые типы (Enum)
DbJobPriority
Приоритет работы в предпочтениях персонажа.
| Значение | Имя | Описание |
|---|---|---|
| 0 | Never | Никогда не спауниться за эту роль |
| 1 | Low | Низкий приоритет |
| 2 | Medium | Средний приоритет |
| 3 | High | Высокий приоритет (любимая работа) |
Поведение, если любимая работа недоступна.
| Значение | Имя | Описание |
|---|---|---|
| 0 | StayInLobby | Остаться в лобби и ждать |
| 1 | SpawnAsOverflow | Появиться на станции за assistant/overflow |
ConnectionDenyReason (byte)
Причина отклонения подключения к серверу.
| Значение | Имя | Описание |
|---|---|---|
| 0 | Ban | Забанен |
| 1 | Whitelist | Не в вайтлисте |
| 2 | Full | Сервер заполнен |
| 3 | Panic | Режим паники (сервер закрыт для всех) |
| 4 | BabyJail | Сервер для новичков (достигнут лимит по времени) |
| 5 | IPChecks | Провалена проверка IP (прокси/VPN) |
| 6 | NoHwid | Отсутствует HWID (подозрение на бота/читера) |
ServerBanExemptFlags (Flags)
Флаги исключений из банов. Битовая маска — можно комбинировать.
| Значение | Имя | Описание |
|---|---|---|
| 0 | None | Нет исключений |
| 1 | Datacenter | Исключение для датацентров (игроки с облачных IP не блокируются) |
| 2 | IP | Исключение по IP |
| 4 | BlacklistedRange | Исключение для заブラックлистованных диапазонов |
| int.MaxValue | All | Полное исключение от всех автоматических банов |
BanType (byte)
Тип бана (дискриминатор в таблице ban).
| Значение | Имя | Описание |
|---|---|---|
| 0 | Server | Серверный бан (полный запрет входа) |
| 1 | Role | Ролевой бан (запрет на конкретные роли) |
BiStatWinner (byte) — DeadSpace
Победитель раунда (форк DeadSpace).
| Значение | Имя | Описание |
|---|---|---|
| 0 | Crew | Победил экипаж станции |
| 1 | Antagonist | Победили антагонисты |
Схема связей (ERD)
Preference 1──* Profile 1──* Job
1──* Antag
1──* Trait
1──* ProfileRoleLoadout 1──* ProfileLoadoutGroup 1──* ProfileLoadout
Player *──* Round (через player_round)
Player *──* AdminLog (через admin_log_player)
Player 1──* AdminNote (как получатель, создатель, редактор, удалитель)
Player 1──* AdminWatchlist (те же роли)
Player 1──* AdminMessage (те же роли)
Player 1──* RoleWhitelist
Player 1──* Ban (как создатель, редактор)
Ban 1──* BanPlayer
Ban 1──* BanAddress
Ban 1──* BanHwid
Ban 1──* BanRole
Ban 1──* BanRound *──1 Round
Ban 1──0..1 Unban
Ban 1──* ServerBanHit *──1 ConnectionLog
ConnectionLog 1──* ServerBanHit
ConnectionLog *──1 Server
Server 1──* Round
Admin 0..1 AdminRank 1──* AdminRankFlag
Admin 1──* AdminFlag
Round 1──* AdminLog 1──* AdminLogPlayer *──1 Player
Ключевые особенности
- player.user_id (Guid) — сквозной идентификатор. Почти все таблицы ссылаются на player.user_id, а не на player_id. Это сделано для совместимости с SS14 Central.
- ban — единая таблица для серверных и ролевых банов. Раньше были две отдельные таблицы (server_ban, server_role_ban).
- admin_notes, admin_watchlists, admin_messages — три типа административных записей с одинаковой структурой (created/deleted/edited). Все поддерживают мягкое удаление и SET NULL для GDPR.
- GDPR-совместимость: внешние ключи на админов используют ON DELETE SET NULL, чтобы при удалении аккаунта игрока его данные в административных записях обнулялись, а не удаляли сами записи.
- DateTime всегда UTC — PostgreSQL использует timestamp with time zone для всех временных полей.
- SnakeCase — все имена таблиц, колонок, индексов и ограничений автоматически приводятся к snake_case.
- DeadSpace-форк: добавил таблицы bi_stats (статистика раундов) и information_topics (информационные страницы).
- BanTemplate — единственная таблица, созданная исключительно для нужд админ-панели (а не игрового сервера).