Installation
This guide will walk you through installing prp-property on your FiveM server.
Installation steps
prp-property from the CFX portal and place it in your resources folder. You also need the Housing Pack shells (prp-housing-loader, prp-housing-main, prp-housing) for interior assets. For tower apartments, also get Apartment Towers (prp-apartments) — soft dependency, see Apartments.ensure ox_lib
ensure oxmysql
ensure ox_doorlock
ensure prp-bridge
ensure prp-housing-loader
ensure prp-housing-main
ensure prp-housing
ensure prp-apartments
ensure prp-property ox_doorlock must start before prp-property. Start prp-apartments before prp-property when you use apartments (recommended, not required).ox_doorlock automatically on first start — see ox_doorlock below.Housing shells
The housing script does not include MLO interiors. Install the Housing Pack separately and ensure shell resources start before prp-property.
Apartments (optional)
Tower apartments need Apartment Towers (prp-apartments). Soft dependency: if it is not started, apartment features stay off. Prefer starting it before prp-property. Details: Apartments.
Garages
Start one supported garage resource before or with housing. Detection and placement: Garages. Config/shared Lua and all JSON are open; UI and client/server Lua are escrowed — Editable files.
Items
Add all required items to your inventory resource. HousingBridge.registerItem is a no-op in the bridge adapter — items must be defined manually.
lockpick
If your inventory already ships with a default lockpick item (common with ox_inventory), remove that entry before using the definitions below. The default item registers its own use handler (e.g. vehicle lockpicking) and will conflict with housing door lockpicking.
Add the items below to your ox_inventory into data/items.lua.
["placeable_furniture_item"] = {
label = "Placeable Furniture",
weight = 1000,
stack = false,
close = true,
consume = 0,
},
["collectable_furniture_item"] = {
label = "Collectable Furniture",
weight = 1000,
stack = false,
close = true,
consume = 0,
},
["master_key"] = {
label = "Master Key",
weight = 200,
stack = false,
},
["lockpick"] = {
label = "Lockpick",
weight = 160,
},
["improved_lockpick"] = {
label = "Improved Lockpick",
weight = 160,
},
["expert_lockpick"] = {
label = "Expert Lockpick",
weight = 160,
},Real estate tablet
If you enable the real estate panel (Config.RealEstate), add the usable item that opens it (default name realtor_tablet). Example for ox_inventory (data/items.lua):
["realtor_tablet"] = {
label = "Realtor Tablet",
weight = 1000,
stack = false,
close = true,
},Only players allowed by Config.HousingStaff (mode + jobs) and admins (when mode permits) can open the panel — using the item without permission shows an error. Staff can also use the real estate radial when enabled. See Real estate.
Furniture item metadata
When a player receives a placeable_furniture_item or collectable_furniture_item, the item metadata must include:
| Field | Type | Description |
|---|---|---|
model | string | Prop model name (e.g. pr_furniture_chair_01) |
category | string | Furniture category from the catalog |
Using the item from inventory opens the placement mode for that model.
ox_doorlock
Exterior property doors use ox_doorlock (same pattern as prp-outposts). Doors are locked by default (state: 1). Lock/unlock from housing target options syncs through ox_doorlock when Config.Doorlock.enabled = true.
Automatic registration
On first start (and when new locations are created), prp-property inserts missing rows into ox_doorlock:
| Field | Value |
|---|---|
| Name | housing_loc_{locationId}_door_{doorIndex} |
| Data | model, coords, heading, state: 1, hideUi: true, lockpick: false |
Example for location 403:
INSERT INTO `ox_doorlock` (`name`, `data`) VALUES (
'housing_loc_403_door_1',
'{"model":-514036887,"coords":{"x":960.0,"y":-669.0,"z":58.0},"heading":0.0,"state":1,"maxDistance":2,"hideUi":true,"doors":false,"lockpick":false,"autolock":false}'
);After bulk inserts on first boot, the script reloads ox_doorlock once so clients receive all doors.
Configuration
In config/sh_config.lua:
Config.Doorlock = {
enabled = true,
openOnAccess = true,
namePrefix = "housing_loc",
maxDistance = 2.0,
hideUi = true,
holdOpen = true,
defaultHeading = 0.0,
autolock = false,
}| Option | Default | Description |
|---|---|---|
enabled | true | Sync exterior doors to ox_doorlock |
openOnAccess | true | With access, door interact opens the door |
Set enabled = false only if you replace door sync entirely from another resource (door lock logic is escrowed — not in escrow_ignore).
Database
The required tables are created automatically on first server start:
CREATE TABLE IF NOT EXISTS `world_housing_locations` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`property_name` VARCHAR(100) NULL,
`property_price` INT DEFAULT 0 NULL,
`property_zone` LONGTEXT NULL,
`property_settings` LONGTEXT NULL,
`interior_type` VARCHAR(16) DEFAULT 'mlo' NOT NULL,
`shell_id` VARCHAR(128) NULL,
`exterior_coords` LONGTEXT NULL,
`interior_location` LONGTEXT DEFAULT '{}' NULL,
`doors` LONGTEXT NULL,
`property_seller` VARCHAR(50) NULL,
`property_sale_data` LONGTEXT NULL,
`time_added` TIMESTAMP DEFAULT CURRENT_TIMESTAMP() NULL
) CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `world_housing` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`location_id` INT NOT NULL,
`owner` VARCHAR(50) NOT NULL,
`upgrades` LONGTEXT DEFAULT '{}' NOT NULL,
`settings` LONGTEXT DEFAULT '{}' NULL,
`time_bought` TIMESTAMP DEFAULT CURRENT_TIMESTAMP() NULL
) CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `world_housing_access` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`housing_id` INT NOT NULL,
`stateId` VARCHAR(50) NOT NULL,
`character_privileges` LONGTEXT DEFAULT '{}' NOT NULL,
`access_gained` TIMESTAMP DEFAULT CURRENT_TIMESTAMP() NULL,
FOREIGN KEY (`housing_id`) REFERENCES `world_housing` (`id`) ON DELETE CASCADE
) CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `world_housing_furniture` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`housing_id` INT NULL,
`placer_id` VARCHAR(50) NULL,
`furniture_data` LONGTEXT NOT NULL,
`furniture_health` INT DEFAULT 100 NOT NULL,
`furniture_placed` TIMESTAMP DEFAULT CURRENT_TIMESTAMP() NULL,
FOREIGN KEY (`housing_id`) REFERENCES `world_housing` (`id`) ON DELETE CASCADE
) CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `world_housing_garages` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`housing_id` INT NULL,
`access_location` LONGTEXT NOT NULL,
`vehicle_location` LONGTEXT NULL,
`time_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP() NULL,
FOREIGN KEY (`housing_id`) REFERENCES `world_housing` (`id`) ON DELETE CASCADE
) CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;Additional tables (world_housing_mdt, world_housing_rent, etc.) are created on first start. A full reference schema is in sql/housing_schema.sql.
The interior_type, shell_id, and exterior_coords columns drive shell properties (interior_type = 'shell'). MLO properties keep the default 'mlo'.
Fresh install only
prp-property creates its tables from scratch and ships no migrations. The schema is treated as greenfield: if you change it during setup, drop and recreate the housing tables rather than expecting an in-place upgrade.