One Export.
Every Resource Asks It.
rde_property is the universal property access gateway that makes every RDE housing script talk to the same source of truth. rde_doors, rde_ipl, rde_elevators, and rde_organizations each had their own isolated access system — rde_property replaces that with one table, one link table, and one export.
Overview
A door had an owner_charid. An IPL had an owner_identifier. There was no way to say "this door, this interior, and this elevator all belong to the same property." rde_property fixes this with one table and one export:
local allowed, reason = exports.rde_property:canAccess(propertyId, source)
canAccess() resolves from data already resident, not a fresh query per call.
Architecture — Next Gen Housing
rde_property is Phase 1 of a five-phase rollout integrating every RDE housing resource behind one access layer:
| Phase | Resource | Status |
|---|---|---|
| 1 | rde_property | ✅ This resource |
| 2 | rde_doors | 🔜 canAccess() integration |
| 3 | rde_ipl | 🔜 Instance ↔ property bridge |
| 4 | rde_elevators | 🔜 Floor access control |
| 5 | rde_organizations | 🔜 Org-owned properties |
Install
ensure oxmysql
ensure ox_lib
ensure ox_core
ensure rde_property
DB tables auto-create on first start. No manual SQL needed.
Database Schema
Two tables. No join-table explosion.
rde_properties (
id VARCHAR(50) PRIMARY KEY, -- 'prop_{hex}'
owner_charid VARCHAR(50) NULL,
access_list LONGTEXT DEFAULT '[]', -- JSON charId array
group_access LONGTEXT DEFAULT NULL, -- JSON {groupName: minGrade}
locked TINYINT(1) DEFAULT 1,
metadata LONGTEXT DEFAULT NULL, -- JSON key/value store
)
-- The universal link table — replaces N join tables
rde_property_links (
property_id VARCHAR(50) NOT NULL, -- FK → rde_properties.id
resource_name VARCHAR(50) NOT NULL, -- 'rde_doors', 'rde_ipl', ...
resource_id VARCHAR(100) NOT NULL, -- door ID / IPL instance_id / ...
link_type VARCHAR(50) DEFAULT 'primary',
UNIQUE KEY uq_resource (resource_name, resource_id)
)
Export API
| Export | Notes |
|---|---|
| canAccess(propertyId, source) | Returns allowed (bool), reason — 'owner' | 'access_list' | 'group:police:2' | 'admin' | 'no_access' |
| createProperty(name, category, opts) | Returns propId or nil, error |
| linkResource(propId, resource, resourceId, type) | Links e.g. an rde_doors door to a property |
| getPropertyByLink(resource, resourceId) | Reverse lookup — find property from a door ID |
| setMetadata / getMetadata | Arbitrary key/value store on any property |
Server Events
AddEventHandler('rde_property:created', function(propId, prop) end)
AddEventHandler('rde_property:ownerChanged', function(propId, newCharId) end)
AddEventHandler('rde_property:linked', function(propId, resourceName, resourceId, linkType) end)
Phase 2 Integration Preview — rde_doors
When Phase 2 ships, rde_doors will replace its internal HasAccess() check with a single call into this resource:
local propId = exports.rde_property:getPropertyByLink('rde_doors', doorId)
if propId then
local allowed, reason = exports.rde_property:canAccess(propId, source)
if allowed then -- open door end
end
One access check, all resources, one source of truth.
FAQ
Do I need this if I only use rde_doors?
Not yet — rde_property is Phase 1, and rde_doors' native access system works standalone today. This becomes relevant once you want doors, IPL properties, and elevators to recognize the same "property" across resources.
Is this production-ready?
It's tagged 1.0.0-alpha — the export API and schema are stable, but the downstream Phase 2–5 integrations are still in progress on the other resources' side.
Roadmap
rde_doors canAccess() integration — replace internal HasAccess() with a call into rde_property.
rde_ipl instance ↔ property bridge.
rde_elevators floor access control via linked properties.
rde_organizations org-owned properties.