FiveM alloggi e appartamenti: shell, istanze, nascondigli e chiavi
Come funziona un sistema di alloggi FiveM: shell e interni MLO, instanziazione con routing bucket, un nascondiglio per casa, chiavi e autorizzazioni, e salvataggio della proprietà nel database.
Il sintomo: due giocatori entrano in due appartamenti diversi e si vedono, il nascondiglio è condiviso tra ogni casa, oppure la proprietà scompare quando il server si riavvia.
Un sistema di alloggi è quattro cose che lavorano insieme: un interno, un modo per separare i giocatori, un posto dove immagazzinare oggetti e un record di chi può entrare. Questo articolo spiega ogni parte e come si collegano.
Shell o interno MLO
Hai due modi per dare un interno a una casa:
| Tipo | Come funziona | Adatto per |
|---|---|---|
| Shell | Un prop generato a coordinate, rimosso all'uscita | Appartamenti, molte case identiche |
| MLO | Un interno permanente sulla mappa | Case uniche e ville |
Una shell è un modello che carichi, posizioni in una posizione fissa (spesso in alto nel cielo o lontano, sotto la mappa), e elimini quando il giocatore se ne va. Poiché la stessa shell può essere generata per qualsiasi numero di case, le shell sono il modo in cui si costruiscono i condomini. Un MLO rimane sulla mappa, quindi è limitato a un posto. Per installarne uno, vedi installazione di un MLO, e se rompe la mappa intorno, conflitti mappa MLO.
Instanziazione con routing bucket
Se ogni appartamento utilizza la stessa shell alle stesse coordinate, allora tutti coloro che entrano si trovano nella stessa stanza. La soluzione è dare a ogni casa il proprio routing bucket, una copia isolata del mondo sul server. I giocatori in bucket diversi non possono vedersi l'un l'altro o le rispettive entità. L'idea in una frase: la casa numero 12 utilizza il bucket 12 (più un offset per evitare collisioni con altri usi).
-- 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)Tutti coloro che visitano quella casa devono essere messi nello stesso bucket, e ogni uscita deve impostare il bucket di nuovo su 0. Gestisci anche le disconnessioni e i riavvii degli script, in modo che nessun giocatore rimanga in un bucket che nessun altro possa raggiungere. Tutti i nativi sono spiegati in routing bucket.
Suggerimento: se generi il prop shell sul client, solo quel giocatore lo vede. Per una shell che i visitatori vedono anche, ogni visitatore la genera per se stesso, oppure il server la crea nello stesso bucket.
Un nascondiglio per ogni casa
Ogni casa ha bisogno del proprio deposito. Con ox_inventory, registra un nascondiglio per casa, con un id che include l'id della casa:
-- server
exports.ox_inventory:RegisterStash('house_' .. houseId, 'House storage', 50, 100000, ownerId)Quindi aprilo con lo stesso id sul client:
exports.ox_inventory:openInventory('stash', 'house_' .. houseId)Se l'id è lo stesso per ogni casa, ogni casa condivide un nascondiglio, che è il sintomo dall'inizio di questo articolo. Aggiungi il controllo dei permessi sul server prima che il nascondiglio sia aperto, e vedi nascondigli ox_inventory per slot, peso e chi può aprirne uno.
Chiavi e autorizzazioni
La proprietà non è l'unico modo per entrare. Pianifica per questi casi:
- Proprietario: entra sempre, può vendere la casa e distribuire le chiavi.
- Detentori di chiavi: amici o inquilini che possono entrare e usare il nascondiglio, ma non possono vendere.
- Ospiti: visitano quando il proprietario è dentro e li fa entrare (un campanello).
- Polizia: un raid o un ingresso ufficiale, se il tuo server ne ha uno.
Mantieni le chiavi come dati piuttosto che come un oggetto che puoi lasciare cadere: un elenco di identificatori di personaggi per casa. Controlla l'elenco sul server ogni volta che qualcuno tenta di entrare o aprire il nascondiglio.
Salvataggio della proprietà nel database
Tutto ciò che deve sopravvivere a un riavvio va nel database. Una struttura semplice è una tabella per le case e una per le chiavi:
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)
);Memorizza l'identificatore del personaggio che il tuo framework utilizza per i personaggi (ad esempio l'identificatore del personaggio piuttosto che la licenza del giocatore), in modo che la proprietà segua il personaggio. Carica i dati all'avvio della risorsa e mantieni una copia in una tabella del server per controlli veloci, scrivendo di nuovo nel database ad ogni cambio. Le query da Lua sono in query oxmysql.
I flussi di denaro sono importanti anche: l'acquisto, l'affitto e il rimborso della vendita dovrebbero tutti essere gestiti sul server, e agiscono come un assorbimento di denaro, come descritto in bilanciamento dell'economia del server.
Errori comuni
- Non reimpostare il bucket all'uscita, morte, disconnessione o riavvio.
- Stesso id nascondiglio per tutte le case.
- Controllare la proprietà sul client solo.
- Proprietà mantenuta in memoria e persa al riavvio.
- Generare la shell più di una volta quando il giocatore rientra velocemente, lasciando prop duplicate.
Elenco di controllo
| Sintomo | Soluzione |
|---|---|
| I giocatori in case diverse si vedono | Dai a ogni casa il suo routing bucket |
| Giocatore bloccato in un mondo vuoto | Reimposta il bucket su 0 all'uscita, morte e disconnessione |
| Ogni casa condivide un nascondiglio | Usa un id nascondiglio che include l'id della casa |
| Proprietà persa al riavvio | Salvala nel database |
| Chiunque può entrare | Controlla il proprietario o la chiave sul server |
| Prop shell duplicate | Elimina la shell all'uscita e proteggi da generazioni doppie |
Risposte rapide
Qual è la differenza tra una shell e un interno MLO?
Un MLO è un interno reale posizionato sulla mappa con coordinate fisse. Una shell è un prop che generi su richiesta, solitamente lontano dalla mappa, e rimuovi quando il giocatore se ne va.
Perché i giocatori possono vedersi le case a vicenda?
Ogni interno di casa utilizza le stesse coordinate, quindi i giocatori in case diverse si trovano nello stesso spazio. Metti ogni casa nel proprio routing bucket in modo che siano separate.
Dove dovrebbe essere salvata la proprietà della casa?
Nel database, con l'id della casa e l'identificatore del personaggio del proprietario, e una tabella o colonna separata per le persone che hanno le chiavi. Non mantenere mai la proprietà solo in memoria.
Script senza questo problema
CCTV Security CamerasTelecamere posizionabili, un tablet multi-vista in diretta e foto stampate come prove.Vedi script →
Shop CreatorCrea un negozio in meno di un minuto — proprietari, dipendenti, casseforti e rapine inclusi.Vedi script →
Item Creator V2Crea oggetti utilizzabili con animazioni, props, effetti e altro — senza scrivere codice.Vedi script →