Shells
Shell properties are interiors spawned from a prop instead of a world MLO. When a player enters, the resource teleports them to a fixed underground origin where the shell prop is spawned, and places them in a shared routing bucket for that property (Config.Shells.bucketOffset + housing.id). Every keyholder who enters the same property ends up in the same bucket and can see each other — there is no invitation step.
You can author packs natively, or import an external shell config into a prp-housing-v2 pack (see Import shell config).
File structure
Shells are configured in three layers so values are never repeated:
prp-housing-v2/
config/
shells_defaults.lua # global defaults (stash, door width, categories)
shells/
manifest.json # which packs are active
packs/
example.json # a pack of shells
custom/...
import/ # drop foreign configs here for /importshellpack1. Manifest — shells/manifest.json
The only file you edit to enable a pack:
{
"packs": ["example", "custom/my_pack"]
}2. Defaults — config/shells_defaults.lua
Shared values applied to every shell unless overridden:
ShellDefaults = {
door = { width = 2.0 },
stash = { weight = 8000000, slots = 120 },
categories = {
residential = "Residential",
commercial = "Commercial",
warehouse = "Warehouse",
garage = "Garage",
illegal = "Illegal",
},
}3. Pack — shells/packs/<id>.json
{
"id": "example",
"label": "Example Shells",
"author": "you",
"defaults": { "category": "residential" },
"shells": {
"medium_2": {
"label": "Medium 2",
"model": "shell_medium2",
"category": "residential",
"door": { "x": 5.96, "y": 0.39, "z": -0.66, "h": 10.21 },
"preview": "https://i.ibb.co/VvtRX1Z/image.png"
}
}
}| Field | Required | Notes |
|---|---|---|
| shell key | yes | snake_case slug; the global id is packId.shellKey (e.g. example.medium_2) |
label | yes | Shown in the real estate panel |
model | yes | Shell prop model |
door x/y/z/h | yes | Entrance offset relative to the shell origin |
door.width | no | Falls back to ShellDefaults.door.width |
stash | no | Falls back to pack then global defaults |
preview | no | Image URL for the panel (or imgs[] array) |
category | no | Used for the panel category filter |
A property stores only interior_type = 'shell' and shell_id = 'packId.shellKey' — the registry resolves the model, door and stash at runtime.
Adding a shell
- Add (or create) a pack JSON under
shells/packs/. - List the pack id in
shells/manifest.json. - Add a shell entry with
label,model,categoryand a roughdooroffset. - Restart
prp-housing-v2(or reload via a shell staff command). - Fine-tune the entrance in-game with
/testshell packId.shellKey— stand where the door should be and press E to save the offset.
Import shell config
You can convert an external shell config.json (with an interiors table) into a native prp-housing-v2 pack. The importer maps interiors (label, doorOffset, model, imgs, stash) into our pack format.
- Copy the config into
shells/import/and rename it (example:shells/import/k4mb1.json). - Make sure you are housing staff (or admin, depending on
Config.HousingStaff). - In-game, run
/importshellpack k4mb1(filename without.json). - Confirm the new file
shells/packs/k4mb1.jsonwas written and thatk4mb1appears inshells/manifest.json. - The registry reloads after import — open the real estate Shells tab and verify the pack is listed.
- Optional: run
/testshell packId.shellKeyon any shell whose door offset needs a tweak.
Creating a shell property
Use the Shells wizard in the real estate panel — full steps: Creating properties.
Preview drops you into the void
If Preview teleports you into empty space, you do not have the resource for that default or custom shell. The catalog is still supported by prp-housing-v2 — you can buy or install the shell later if you want it in-world. We do not provide support for installing those resources.