Mieszkania i apartamenty w FiveM: shell'e, instancje, sejfy i klucze
Jak działa system mieszkań w FiveM: wnętrza shell i MLO, instancjowanie za pomocą routing buckets, sejf dla każdego domu, klucze i uprawnienia, oraz zapisywanie właścicielstwa w bazie danych.
Objaw: dwaj gracze wchodzą do dwóch różnych apartamentów i widzą się nawzajem, sejf jest dzielony między wszystkie domy, lub właścicielstwo znika po restarcie serwera.
System mieszkań to cztery rzeczy pracujące razem: wnętrze, sposób na oddzielenie graczy, miejsce do przechowywania przedmiotów i rejestr tego, kto może wejść. Ten artykuł wyjaśnia każdą część i jak się ze sobą łączą.
Shell lub wnętrze MLO
Masz dwa sposoby na stworzenie wnętrza domu:
| Typ | Jak działa | Dobre dla |
|---|---|---|
| Shell | Prop spawowany w współrzędnych, usuwany przy wyjściu | Apartamenty, wiele identycznych domów |
| MLO | Stałe wnętrze na mapie | Unikalne domy i rezydencje |
Shell to model, który ładujesz, umieszczasz w stałej lokalizacji (często wysoko na niebie lub daleko, pod mapą), i usuwasz, gdy gracz wyjdzie. Ponieważ ten sam shell może być spawany dla dowolnej liczby domów, shell'e to sposób, w jaki robisz budynki apartamentów. MLO pozostaje na mapie, więc jest ograniczone do jednego miejsca. Aby je zainstalować, zobacz instalacja MLO, a jeśli psuje mapę wokół, konflikty map MLO.
Instancjowanie za pomocą routing buckets
Jeśli każdy apartament używa tego samego shell'a w tych samych współrzędnych, to wszyscy, którzy wchodzą, stoją w tym samym pokoju. Rozwiązaniem jest danie każdemu domowi jego własnego routing bucketa, izolowanej kopii świata na serwerze. Gracze w różnych bucketach nie mogą widzieć się nawzajem ani się nawzajem. Pomysł w jednym zdaniu: dom numer 12 używa bucketa 12 (plus przesunięcie, aby nigdy się nie zderzał z innymi użyciami).
-- 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)Wszyscy, którzy odwiedzają ten dom, muszą być umieszczeni w tym samym buckecie, a każde wyjście musi ustawić bucket z powrotem na 0. Obsługuj także rozłączenia i restarty skryptów, aby żaden gracz nie pozostał w buckecie, do którego nikt inny nie może dotrzeć. Wszystkie native'y są wyjaśnione w routing buckets.
Wskazówka: jeśli spawujesz prop shell'a na kliencie, tylko ten gracz go widzi. Dla shell'a, który widzą także goście, każdy gość spawuje go dla siebie, lub serwer tworzy go w tym samym buckecie.
Sejf dla każdego domu
Każdy dom potrzebuje własnego magazynu. Z ox_inventory zarejestruj sejf dla każdego domu, z identyfikatorem, który zawiera identyfikator domu:
-- server
exports.ox_inventory:RegisterStash('house_' .. houseId, 'House storage', 50, 100000, ownerId)Następnie otwórz go z tym samym identyfikatorem na kliencie:
exports.ox_inventory:openInventory('stash', 'house_' .. houseId)Jeśli identyfikator jest taki sam dla każdego domu, każdy dom dzieli jeden sejf, co jest objawem od początku tego artykułu. Dodaj sprawdzenie uprawnień na serwerze przed otwarciem sejfu i zobacz ox_inventory sejfy aby dowiedzieć się o slotach, wadze i tym, kto może otworzyć jeden.
Klucze i uprawnienia
Właścicielstwo to nie jedyny sposób, aby wejść. Zaplanuj na te przypadki:
- Właściciel: zawsze wchodzi, może sprzedać dom i dać klucze.
- Posiadacze kluczy: przyjaciele lub najemcy, którzy mogą wejść i używać sejfu, ale nie mogą sprzedawać.
- Goście: odwiedzają, gdy właściciel jest w środku i ich wpuszcza (dzwonek do drzwi).
- Policja: nalot lub oficjalny wjazd, jeśli Twój serwer taki posiada.
Przechowuj klucze jako dane, a nie jako przedmiot, który możesz upuścić: listę identyfikatorów postaci dla każdego domu. Sprawdzaj listę na serwerze za każdym razem, gdy ktoś próbuje wejść lub otworzyć sejf.
Zapisywanie właścicielstwa w bazie danych
Wszystko, co musi przetrwać restart, trafia do bazy danych. Prosta struktura to jedna tabela dla domów i jedna dla kluczy:
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)
);Przechowuj identyfikator postaci, który używa Twój framework (na przykład identyfikator postaci, a nie licencję gracza), aby właścicielstwo śledziło postać. Załaduj dane, gdy zasób się uruchamia i przechowuj kopię w tabeli serwera dla szybkich sprawdzeń, zapisując z powrotem do bazy danych przy każdej zmianie. Zapytania z Lua są w oxmysql queries.
Przepływy pieniędzy są także ważne: zakup, czynsz i zwrot sprzedaży powinny być obsługiwane na serwerze, i działają jako sink pieniędzy, jak opisano w balancing your server economy.
Częste błędy
- Nie resetowanie bucketa przy wyjściu, śmierci, rozłączeniu lub restarcie.
- Taki sam identyfikator sejfu dla wszystkich domów.
- Sprawdzanie właścicielstwa na kliencie tylko.
- Właścicielstwo przechowywane w pamięci i tracone przy restarcie.
- Spawanie shell'a więcej niż raz gdy gracz szybko wraca, zostawiając zduplikowane propsy.
Checklist
| Objaw | Rozwiązanie |
|---|---|
| Gracze w różnych domach widzą się nawzajem | Daj każdemu domowi jego własny routing bucket |
| Gracz utknął w pustym świecie | Resetuj bucket na 0 przy wyjściu, śmierci i rozłączeniu |
| Każdy dom dzieli jeden sejf | Użyj identyfikatora sejfu, który zawiera identyfikator domu |
| Właścicielstwo tracone przy restarcie | Zapisz to w bazie danych |
| Każdy może wejść | Sprawdzaj właściciela lub klucz na serwerze |
| Zduplikowane propsy shell'a | Usuń shell przy wyjściu i chrań przed podwójnymi spawami |
Szybkie odpowiedzi
Jaka jest różnica między shell'em a wnętrzem MLO?
MLO to wnętrze rzeczywiste umieszczone na mapie w stałych współrzędnych. Shell to prop, który spawujesz na żądanie, zwykle daleko od mapy, i usuwasz, gdy gracz wyjdzie.
Dlaczego gracze mogą widzieć się nawzajem w domach?
Każde wnętrze domu używa tych samych współrzędnych, więc gracze w różnych domach stoją w tej samej przestrzeni. Umieść każdy dom w swoim routing bucketcie, aby je oddzielić.
Gdzie należy zapisywać właścicielstwo domu?
W bazie danych, wraz z identyfikatorem domu i identyfikatorem postaci właściciela, oraz w osobnej tabeli lub kolumnie dla osób, które posiadają klucze. Nigdy nie przechowuj właścicielstwa tylko w pamięci.
Skrypty bez tego problemu
CCTV Security CamerasKamery do rozstawienia, tablet z podglądem wielu kamer na żywo i drukowane zdjęcia jako dowody.Zobacz skrypt →
Shop CreatorZbuduj sklep w niecałą minutę — właściciele, pracownicy, sejfy i napady w zestawie.Zobacz skrypt →
Item Creator V2Twórz używalne przedmioty z animacjami, propami, efektami i nie tylko — bez pisania kodu.Zobacz skrypt →