FiveM Wohnen und Apartments: Shells, Instanzen, Verstecke und Schlüssel

Wie ein FiveM-Wohnsystem funktioniert: Shell- und MLO-Innenräume, Instancing mit Routing-Buckets, ein Versteck pro Haus, Schlüssel und Berechtigungen, und Speicherung der Eigentümerschaft in der Datenbank.

Das Symptom: zwei Spieler betreten zwei verschiedene Apartments und sehen sich gegenseitig, das Versteck wird zwischen jedem Haus geteilt, oder die Eigentümerschaft verschwindet nach einem Neustart des Servers.

Ein Wohnsystem besteht aus vier Dingen, die zusammenarbeiten: ein Innenraum, ein Weg, um Spieler zu trennen, ein Platz zum Speichern von Gegenständen und ein Datensatz, wer eintreten darf. Dieser Artikel erklärt jeden Teil und wie sie zusammenhängen.

Shell oder MLO-Innenraum

Du hast zwei Möglichkeiten, einem Haus ein Inneres zu geben:

Typ Funktionsweise Gut für
Shell Ein Prop, der an Koordinaten gespawnt und beim Verlassen entfernt wird Apartments, viele identische Häuser
MLO Ein permanenter Innenraum auf der Karte Einzigartige Häuser und Herrenhäuser

Eine Shell ist ein Modell, das du ladst, an einer festen Position platzierst (oft hoch in den Himmel oder weit weg, unter der Karte), und das du löschst, wenn der Spieler geht. Da die gleiche Shell für beliebig viele Häuser gespawnt werden kann, sind Shells die Methode für Wohnblöcke. Ein MLO bleibt auf der Karte, daher ist es auf einen Ort begrenzt. Um eines zu installieren, siehe MLO installieren, und wenn es die Karte um sich herum beschädigt, MLO-Kartenkonflikte.

Instancing mit Routing-Buckets

Wenn jedes Apartment die gleiche Shell an den gleichen Koordinaten nutzt, dann stehen alle, die eintreten, im selben Raum. Die Lösung ist, jedem Haus seinen eigenen Routing-Bucket zu geben, eine isolierte Kopie der Welt auf dem Server. Spieler in verschiedenen Buckets können sich gegenseitig oder ihre Entitäten nicht sehen. Die Idee in einem Satz: Haus Nummer 12 nutzt Bucket 12 (plus einen Offset, damit er nie mit anderen Verwendungen kollidiert).

lua
-- 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)

Jeder, der dieses Haus besucht, muss in den gleichen Bucket gesteckt werden, und jeder Ausgang muss den Bucket zurück auf 0 setzen. Behandle auch Trennungen und Script-Neustarts, damit kein Spieler in einem Bucket steckenbleibt, den niemand anderes erreichen kann. Alle Natives sind in Routing-Buckets erklärt.

Tipp: wenn du den Shell-Prop auf dem Client spawnst, sieht ihn nur dieser Spieler. Für eine Shell, die auch Besucher sehen, spawnt jeder Besucher sie für sich selbst, oder der Server erstellt sie im gleichen Bucket.

Ein Versteck für jedes Haus

Jedes Haus braucht seinen eigenen Speicher. Mit ox_inventory registriere ein Versteck pro Haus mit einer ID, die die Haus-ID enthält:

lua
-- server
exports.ox_inventory:RegisterStash('house_' .. houseId, 'House storage', 50, 100000, ownerId)

Öffne es dann auf dem Client mit der gleichen ID:

lua
exports.ox_inventory:openInventory('stash', 'house_' .. houseId)

Wenn die ID für jedes Haus gleich ist, teilt jedes Haus ein Versteck, was das Symptom vom Anfang dieses Artikels ist. Füge die Berechtigungsprüfung auf dem Server hinzu, bevor das Versteck geöffnet wird, und siehe ox_inventory Verstecke für Plätze, Gewicht und wer eines öffnen darf.

Schlüssel und Berechtigungen

Eigentümerschaft ist nicht der einzige Weg herein. Plane für diese Fälle:

  • Besitzer: betritt immer, kann das Haus verkaufen und Schlüssel austeilen.
  • Schlüsselinhaber: Freunde oder Mieter, die eintreten und das Versteck nutzen dürfen, aber nicht verkaufen können.
  • Gäste: besuchen, wenn der Besitzer drin ist und sie hereinlässt (eine Türklingel).
  • Polizei: eine Razzia oder ein offizieller Eintritt, wenn dein Server einen hat.

Bewahre die Schlüssel als Daten statt als Gegenstand auf, den du fallen lassen kannst: eine Liste von Charakter-Identifikatoren pro Haus. Überprüfe die Liste auf dem Server jedes Mal, wenn jemand versucht, einzutreten oder das Versteck zu öffnen.

Eigentümerschaft in der Datenbank speichern

Alles, das einen Neustart überstehen muss, geht in die Datenbank. Eine einfache Struktur ist eine Tabelle für Häuser und eine für die Schlüssel:

sql
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)
);

Speichere den Charakter-Identifikator, den dein Framework für Charaktere nutzt (zum Beispiel den Identifikator des Charakters statt der Spielerlizenz), damit die Eigentümerschaft den Charakter folgt. Lade die Daten, wenn die Resource startet, und behalte eine Kopie in einer Server-Tabelle für schnelle Checks, schreibe zurück zur Datenbank bei jedem Wechsel. Queries aus Lua sind in oxmysql Queries.

Geldflüsse sind wichtig: der Kauf, die Miete und die Verkaufsrückerstattung sollten alle auf dem Server behandelt werden, und sie funktionieren als ein Geldsenke, wie in Ausgleich deiner Server-Wirtschaft beschrieben.

Häufige Fehler

  • Den Bucket nicht zurücksetzen beim Verlassen, Tod, Trennung oder Neustart.
  • Gleiche Versteck-ID für alle Häuser.
  • Eigentümerschaft nur auf dem Client überprüfen.
  • Eigentümerschaft im Speicher behalten und beim Neustart verlieren.
  • Die Shell mehr als einmal spawnen, wenn der Spieler schnell zurückkommt, hinterlässt doppelte Props.

Checkliste

Symptom Behebung
Spieler in verschiedenen Häusern sehen sich gegenseitig Gib jedem Haus seinen eigenen Routing-Bucket
Spieler ist in einer leeren Welt stecken Setze den Bucket auf 0 zurück beim Verlassen, Tod und Trennung
Jedes Haus teilt ein Versteck Nutze eine Versteck-ID, die die Haus-ID enthält
Eigentümerschaft beim Neustart verloren Speichere es in der Datenbank
Jeder kann eintreten Überprüfe Besitzer oder Schlüssel auf dem Server
Doppelte Shell-Props Lösche den Shell beim Verlassen und schütze vor doppeltem Spawn

Kurze Antworten

Was ist der Unterschied zwischen einer Shell und einem MLO-Innenraum?

Ein MLO ist ein echter Innenraum, der auf der Karte an festen Koordinaten platziert ist. Eine Shell ist ein Prop, das du auf Abruf spawnst, normalerweise weit weg von der Karte, und das du entfernst, wenn der Spieler geht.

Warum können Spieler die Häuser anderer sehen?

Jedes Hausinnere nutzt dieselben Koordinaten, also stehen Spieler in verschiedenen Häusern im selben Raum. Lege jedes Haus in seinen eigenen Routing-Bucket, damit sie getrennt sind.

Wo sollte die Hauseigentümerschaft gespeichert werden?

In der Datenbank, mit der Haus-ID und dem Charakter-Identifikator des Besitzers, und eine separate Tabelle oder Spalte für die Personen, die Schlüssel haben. Behalte die Eigentümerschaft nie nur im Speicher.

Scripts ohne dieses Problem

CCTV Security CamerasPlatzierbare Kameras, ein Live-Tablet mit Multi-View und ausgedruckte Beweisfotos.Script ansehen →Shop CreatorBau einen Shop in unter einer Minute — Besitzer, Angestellte, Tresore und Überfälle inklusive.Script ansehen →Item Creator V2Erstelle nutzbare Items mit Animationen, Props, Effekten und mehr — ganz ohne Code.Script ansehen →

Weiterlesen