Create a Housing System in FiveM — houses that players can own.
Create a Housing system in FiveM
The house system helps players feel that they have "Own location" on the server is a feature that greatly increases engagement and immersion.
Database Schema
CREATE TABLE `housing` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(100) NOT NULL,
`coords` TEXT NOT NULL, -- JSON {x, y, z, h}
`interior_coords` TEXT, -- interior coords
`price` INT DEFAULT 100000,
`owner` VARCHAR(50) DEFAULT NULL, -- identifier
`locked` TINYINT DEFAULT 1,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE `housing_storage` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`house_id` INT,
`identifier` VARCHAR(50),
`items` LONGTEXT, -- JSON inventory
FOREIGN KEY (`house_id`) REFERENCES `housing`(`id`)
);
Config
Config = {}
Config.Houses = {
{
id = 1,
name = 'Luxury house Mirror Park',
coords = vector4(1271.8, -730.4, 67.8, 270.0),
interior = vector4(266.0, -1007.4, 29.0, 270.0), -- apartment interior
price = 500000,
garageCoords = vector4(1259.0, -733.0, 67.0, 90.0),
maxGarage = 2
},
{
id = 2,
name = 'Vinewood middle class house',
coords = vector4(325.5, 188.8, 104.5, 0.0),
interior = vector4(346.7, -1013.3, -99.2, 0.0),
price = 250000,
garageCoords = vector4(330.0, 185.0, 104.0, 180.0),
maxGarage = 1
}
}
Core Functions (Server)
-- server.lua
local houseData = {} -- cache
-- Load all home information
MySQL.query.await('SELECT * FROM housing', {}, function(result)
for _, house in ipairs(result) do
houseData[house.id] = house
end
end)
-- Buy a house
ESX.RegisterServerCallback('housing:buyHouse', function(source, cb, houseId)
local xPlayer = ESX.GetPlayerFromId(source)
local house = houseData[houseId]
if not house then cb(false, 'no house found') return end
if house.owner then cb(false, 'This house is already owned') return end
local config = GetHouseConfig(houseId)
if not config then cb(false, 'Config is not valid') return end
if xPlayer.getMoney() < config.price then
cb(false, 'not enough money')
return
end
xPlayer.removeMoney(config.price)
MySQL.update.await(
'UPDATE housing SET owner = ? WHERE id = ?',
{ xPlayer.identifier, houseId }
)
houseData[houseId].owner = xPlayer.identifier
cb(true, 'Successfully bought the house!')
end)
-- Lock/unlock home
RegisterNetEvent('housing:toggleLock')
AddEventHandler('housing:toggleLock', function(houseId)
local src = source
local xPlayer = ESX.GetPlayerFromId(src)
local house = houseData[houseId]
if not house or house.owner ~= xPlayer.identifier then
TriggerClientEvent('M2.Notify:Notify', src, 'error', 'Not your home', 3000)
return
end
local newLocked = house.locked == 1 and 0 or 1
MySQL.update.await('UPDATE housing SET locked = ? WHERE id = ?', { newLocked, houseId })
houseData[houseId].locked = newLocked
TriggerClientEvent('housing:updateLock', src, houseId, newLocked == 1)
end)
Client — enter/exit the house
-- client.lua
local insideHouse = nil
local function EnterHouse(house)
local interior = house.interior
SetEntityCoords(PlayerPedId(), interior.x, interior.y, interior.z)
SetEntityHeading(PlayerPedId(), interior.w)
insideHouse = house.id
exports['M2.Notify']:Notify('success', 'Home entered', 2000)
TriggerEvent('housing:onEnter', house.id)
end
local function ExitHouse()
local houseConfig = GetHouseConfig(insideHouse)
local exitCoords = houseConfig.coords
SetEntityCoords(PlayerPedId(), exitCoords.x, exitCoords.y, exitCoords.z)
SetEntityHeading(PlayerPedId(), exitCoords.w)
insideHouse = nil
TriggerEvent('housing:onExit')
end
-- Check proximity and show interaction
Citizen.CreateThread(function()
while true do
local coords = GetEntityCoords(PlayerPedId())
if insideHouse then
-- Find exit point
DrawText3D(coords.x, coords.y, coords.z + 0.5, '[E] left home')
if IsControlJustReleased(0, 38) then
ExitHouse()
end
Citizen.Wait(0)
else
-- Check nearby houses
for _, house in ipairs(Config.Houses) do
local dist = GetDistanceBetweenCoords(coords, house.coords, true)
if dist <= 2.0 then
DrawText3D(house.coords.x, house.coords.y, house.coords.z + 0.5,
'[E]enter the house')
if IsControlJustReleased(0, 38) then
-- Check if it's locked.
TriggerServerEvent('housing:enter', house.id)
end
break
end
end
Citizen.Wait(500)
end
end
end)
Summary
The housing system is more complex than the job system, but provides very high value for the RP server. Start with the basic buy/enter/exit first, then add the garage, storage, and furniture system.
Related Articles
Breaking: GTA Online อัพเดท "Money Fronts" — FiveM Server Owners ต้องทำอะไร?
Rockstar ปล่อย GTA Online อัพเดท Money Fronts มีผลกระทบต่อ FiveM servers บางส่วน นี่คือสิ่งที่ต้องทำทันทีหลังอัพเดท
Community Spotlight: Script และ Projects ที่น่าสนใจจาก FiveM Community
รวม scripts, tools และ projects ที่โดดเด่นจาก FiveM community ในช่วงที่ผ่านมา ตั้งแต่ free resources ถึง open-source projects
txAdmin อัพเดทใหม่ — Dashboard, Diagnostics และ Ban System ที่ดีขึ้น
txAdmin ซึ่งตอนนี้เป็นส่วนหนึ่งของ Cfx.re อย่างเป็นทางการ ได้รับการอัพเดทครั้งใหญ่ มี features ใหม่ที่ทำให้ Server Management ง่ายขึ้นมาก