Logement FiveM et appartements : shells, instances, stashes et clés
Comment fonctionne un système de logement FiveM : intérieurs shell et MLO, instancing avec des routing buckets, un stash par maison, clés et autorisations, et sauvegarde de la propriété dans la base de données.
Le symptôme : deux joueurs entrent dans deux appartements différents et se voient, le stash est partagé entre toutes les maisons, ou la propriété disparaît quand le serveur redémarre.
Un système de logement est quatre choses qui fonctionnent ensemble : un intérieur, un moyen de séparer les joueurs, un endroit pour stocker des articles, et un registre de qui peut entrer. Cet article explique chaque partie et comment elles se connectent.
Shell ou intérieur MLO
Vous avez deux façons de donner un intérieur à une maison :
| Type | Comment ça marche | Bon pour |
|---|---|---|
| Shell | Un prop généré à des coordonnées, supprimé à la sortie | Appartements, nombreuses maisons identiques |
| MLO | Un intérieur permanent sur la carte | Maisons et manoirs uniques |
Un shell est un modèle que vous chargez, placez à un endroit fixe (souvent haut dans le ciel ou loin de là, sous la carte), et supprimez quand le joueur la quitte. Parce que le même shell peut être généré pour n'importe quel nombre de maisons, les shells sont comment les immeubles d'appartements sont faits. Un MLO reste sur la carte, donc il est limité à un endroit. Pour en installer un, consultez installation d'un MLO, et s'il casse la carte autour, conflits de carte MLO.
Instancing avec des routing buckets
Si chaque appartement utilise le même shell aux mêmes coordonnées, alors tout le monde qui entre se tient dans la même pièce. La solution est de donner à chaque maison son propre routing bucket, une copie isolée du monde sur le serveur. Les joueurs dans des buckets différents ne peuvent pas se voir ou voir les entités les uns des autres. L'idée en une phrase : la maison numéro 12 utilise le bucket 12 (plus un décalage pour qu'il n'entre jamais en collision avec d'autres utilisations).
-- 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)Tous ceux qui visitent cette maison doivent être mis dans le même bucket, et chaque sortie doit remettre le bucket à 0. Gérez aussi les déconnexions et les redémarrages de script, pour qu'aucun joueur ne reste dans un bucket que personne d'autre ne peut atteindre. Tous les natives sont expliqués dans routing buckets.
Conseil : si vous générez le shell prop sur le client, seul ce joueur le voit. Pour un shell que les visiteurs voient aussi, chaque visiteur le génère pour lui-même, ou le serveur le crée dans le même bucket.
Un stash pour chaque maison
Chaque maison a besoin de son propre stockage. Avec ox_inventory, enregistrez un stash par maison, avec un id qui inclut l'id de la maison :
-- server
exports.ox_inventory:RegisterStash('house_' .. houseId, 'House storage', 50, 100000, ownerId)Ouvrez-le ensuite avec le même id sur le client :
exports.ox_inventory:openInventory('stash', 'house_' .. houseId)Si l'id est le même pour chaque maison, chaque maison partage un stash, ce qui est le symptôme du début de cet article. Ajoutez la vérification des autorisations sur le serveur avant l'ouverture du stash, et consultez ox_inventory stashes pour les emplacements, le poids et qui peut en ouvrir un.
Clés et autorisations
La propriété n'est pas le seul moyen d'entrer. Planifiez ces cas :
- Propriétaire : entre toujours, peut vendre la maison et distribuer des clés.
- Détenteurs de clés : amis ou locataires qui peuvent entrer et utiliser le stash, mais ne peuvent pas vendre.
- Invités : visitent quand le propriétaire est à l'intérieur et les laisse entrer (une sonnette).
- Police : une incursion ou une entrée officielle, si votre serveur en a une.
Conservez les clés comme des données plutôt que comme un article que vous pouvez déposer : une liste d'identifiants de personnages par maison. Vérifiez la liste sur le serveur chaque fois que quelqu'un essaie d'entrer ou d'ouvrir le stash.
Sauvegarde de la propriété dans la base de données
Tout ce qui doit survivre à un redémarrage va dans la base de données. Une structure simple est une table pour les maisons et une pour les clés :
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)
);Stockez l'identifiant de personnage que votre framework utilise pour les personnages (par exemple l'identifiant du personnage plutôt que la licence du joueur), de sorte que la propriété suive le personnage. Chargez les données au démarrage de la ressource et conservez une copie dans une table serveur pour des vérifications rapides, en réécrivant dans la base de données à chaque changement. Les requêtes de Lua sont dans oxmysql queries.
Les flux d'argent sont aussi importants : l'achat, la location et le remboursement de la vente doivent tous être gérés sur le serveur, et ils agissent comme une fuite d'argent, comme décrit dans équilibrer l'économie de votre serveur.
Erreurs courantes
- Ne pas réinitialiser le bucket à la sortie, à la mort, à la déconnexion ou au redémarrage.
- Même id de stash pour toutes les maisons.
- Vérifier la propriété sur le client uniquement.
- Propriété conservée en mémoire et perdue au redémarrage.
- Générer le shell plus d'une fois quand le joueur rentre rapidement, laissant des props en double.
Liste de contrôle
| Symptôme | Solution |
|---|---|
| Les joueurs dans différentes maisons se voient | Donnez à chaque maison son propre routing bucket |
| Joueur coincé dans un monde vide | Réinitialisez le bucket à 0 à la sortie, à la mort et à la déconnexion |
| Chaque maison partage un stash | Utilisez un id de stash qui inclut l'id de la maison |
| Propriété perdue au redémarrage | Sauvegardez-la dans la base de données |
| Tout le monde peut entrer | Vérifiez le propriétaire ou la clé sur le serveur |
| Props shell en double | Supprimez le shell à la sortie et protégez-vous contre les doubles générations |
Réponses rapides
Quelle est la différence entre un shell et un intérieur MLO ?
Un MLO est un intérieur réel placé sur la carte à des coordonnées fixes. Un shell est un prop que vous générez à la demande, généralement loin de la carte, et que vous supprimez quand le joueur la quitte.
Pourquoi les joueurs peuvent-ils voir les maisons des uns et des autres ?
Chaque intérieur de maison utilise les mêmes coordonnées, donc les joueurs dans des maisons différentes se tiennent au même endroit. Mettez chaque maison dans son propre routing bucket pour qu'elles soient séparées.
Où la propriété de la maison doit-elle être sauvegardée ?
Dans la base de données, avec l'id de la maison et l'identifiant du personnage du propriétaire, et une table ou colonne séparée pour les personnes qui détiennent les clés. Ne gardez jamais la propriété uniquement en mémoire.
Des scripts sans ce problème
CCTV Security CamerasDes caméras à placer, une tablette multi-vues en direct et des photos imprimées comme preuves.Voir le script →
Shop CreatorCréez un magasin en moins d’une minute — propriétaires, employés, coffres et braquages inclus.Voir le script →
Item Creator V2Créez des items utilisables avec animations, props, effets et plus — sans écrire une ligne de code.Voir le script →