FiveM жилая система и апартаменты: shells, instances, stashes и ключи
Как работает жилая система в FiveM: оболочки и MLO интерьеры, инстансирование с routing buckets, storage для каждого дома, ключи и доступ, сохранение владения в базе данных.
Симптом: два игрока входят в два разных апартамента и видят друг друга, storage разделён между всеми домами, или владение теряется при перезагрузке сервера.
Жилая система — это четыре вещи, работающие вместе: интерьер, способ разделения игроков, место для хранения предметов и запись о том, кто может входить. В этой статье объясняется каждая часть и как они взаимодействуют.
Shell или MLO интерьер
У вас есть два способа создать интерьер дома:
| Тип | Как это работает | Подходит для |
|---|---|---|
| Shell | Пропс, спаунящийся в координатах, удаляется при выходе | Апартаменты, много идентичных домов |
| MLO | Постоянный интерьер на карте | Уникальные дома и особняки |
Shell — это модель, которую вы загружаете, размещаете в фиксированном месте (часто высоко в небе или далеко, под картой) и удаляете когда игрок выходит. Поскольку один и тот же shell может быть спаунят для любого количества домов, shells используются для жилых зданий. MLO остаётся на карте, поэтому он ограничен одним местом. Чтобы установить его, смотрите установка MLO, и если он нарушит карту вокруг него, конфликты MLO.
Инстансирование с routing buckets
Если каждый апартамент использует один и тот же shell на одних и тех же координатах, то все, кто входит, стоят в одной комнате. Решение — дать каждому дому свой routing bucket, изолированную копию мира на сервере. Игроки в разных buckets не видят друг друга и друг друга сущностей. Суть в одном предложении: дом номер 12 использует bucket 12 (плюс смещение, чтобы он никогда не совпадал с другими использованиями).
-- server
local HOUSE_BUCKET_OFFSET = 1000
RegisterNetEvent('housing:enter', function(houseId)
local src = source
if not canEnter(src, houseId) then return end -- ownership or key check
SetPlayerRoutingBucket(src, HOUSE_BUCKET_OFFSET + houseId)
TriggerClientEvent('housing:spawnShell', src, houseId)
end)
RegisterNetEvent('housing:leave', function()
local src = source
SetPlayerRoutingBucket(src, 0)
TriggerClientEvent('housing:removeShell', src)
end)Каждый, кто посещает этот дом, должен быть помещён в один bucket, и каждый выход должен установить bucket обратно в 0. Обработайте также отключения и перезагрузки скриптов, чтобы ни один игрок не остался в bucket, который больше никто не может достичь. Все native функции объяснены в routing buckets.
Совет: если вы спаунят shell пропс на клиенте, только этот игрок его видит. Для shell, который видят и посетители, каждый посетитель спаунят его для себя, или сервер создаёт его в одном bucket.
Storage для каждого дома
Каждому дому нужно своё хранилище. С ox_inventory зарегистрируйте stash для каждого дома с идентификатором, который включает id дома:
-- server
exports.ox_inventory:RegisterStash('house_' .. houseId, 'House storage', 50, 100000, ownerId)Затем откройте его с тем же идентификатором на клиенте:
exports.ox_inventory:openInventory('stash', 'house_' .. houseId)Если идентификатор одинаков для всех домов, все дома будут разделять один stash, что является симптомом из начала статьи. Добавьте проверку разрешения на сервере перед открытием stash, и смотрите ox_inventory stashes для информации о слотах, весе и кто может открыть один.
Ключи и доступ
Владение — не единственный способ входа. Планируйте эти случаи:
- Владелец: всегда входит, может продать дом и выдать ключи.
- Владельцы ключей: друзья или арендаторы, которые могут входить и использовать storage, но не могут продать.
- Гости: посещают когда владелец внутри и разрешает им войти (звонок в дверь).
- Полиция: рейд или официальный вход, если ваш сервер это имеет.
Храните ключи как данные, а не как предмет, который можно выбросить: список идентификаторов персонажей на дом. Проверяйте список на сервере каждый раз, когда кто-то пытается войти или открыть storage.
Сохранение владения в базе данных
Всё, что должно пережить перезагрузку, должно быть в базе данных. Простая структура — одна таблица для домов и одна для ключей:
CREATE TABLE IF NOT EXISTS houses (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(64) NOT NULL,
owner VARCHAR(64) DEFAULT NULL,
price INT NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS house_keys (
house_id INT NOT NULL,
holder VARCHAR(64) NOT NULL,
PRIMARY KEY (house_id, holder)
);Храните идентификатор персонажа, который использует ваш фреймворк для персонажей (например идентификатор персонажа, а не лицензию игрока), чтобы владение следовало персонажу. Загружайте данные при запуске ресурса и храните копию в таблице сервера для быстрых проверок, записывая обратно в базу данных при каждом изменении. Запросы из Lua находятся в oxmysql запросы.
Потоки денег тоже имеют значение: покупка, аренда и возврат при продаже должны обрабатываться на сервере, и они действуют как сток денег, как описано в балансировка экономики сервера.
Распространённые ошибки
- Неправильный сброс bucket при выходе, смерти, отключении или перезагрузке.
- Один и тот же stash id для всех домов.
- Проверка владения только на клиенте.
- Владение хранится только в памяти и теряется при перезагрузке.
- Спаун shell больше одного раза когда игрок быстро входит снова, оставляя дубликаты пропсов.
Контрольный список
| Симптом | Решение |
|---|---|
| Игроки в разных домах видят друг друга | Дайте каждому дому свой routing bucket |
| Игрок застрял в пустом мире | Сбросьте bucket в 0 при выходе, смерти и отключении |
| Все дома разделяют один stash | Используйте stash id, который включает id дома |
| Владение теряется при перезагрузке | Сохраняйте его в базе данных |
| Кто угодно может входить | Проверьте владение или ключ на сервере |
| Дубликаты shell пропсов | Удалите shell при выходе и защитите от двойного спауна |
Короткие ответы
В чём разница между shell и MLO интерьером?
MLO — это реальный интерьер, расположенный на карте в фиксированных координатах. Shell — это пропс, который вы спаунятся по требованию, обычно далеко от карты, и удаляется когда игрок выходит.
Почему игроки видят дома друг друга?
Каждый дом использует одни и те же координаты, поэтому игроки в разных домах находятся в одном пространстве. Поместите каждый дом в свой routing bucket, чтобы они были разделены.
Где должны быть сохранены данные владения домом?
В базе данных с идентификатором дома и идентификатором персонажа владельца, плюс отдельная таблица или колонка для людей, у которых есть ключи. Никогда не храните владение только в памяти.
Скрипты без этой проблемы
CCTV Security CamerasУстанавливаемые камеры, планшет с мультиэкраном в реальном времени и распечатанные фото-улики.Смотреть скрипт →
Shop CreatorМагазин меньше чем за минуту — владельцы, сотрудники, сейфы и ограбления в комплекте.Смотреть скрипт →
Item Creator V2Создавайте используемые предметы с анимациями, пропами, эффектами и не только — без кода.Смотреть скрипт →