:house: Housing
Documentation related to the jo_housing script.
:::: tabs ::: tab BUY Buy it on the shop :::
::: tab PREVIEW <iframe width="560" height="315" src="https://www.youtube.com/embed/1A_ubufvh80?si=Vrw1RxNKarTFS2_6" title="RedM - Housing" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe> ::: ::::
1. Installation
jo_housing works on all frameworks compatible with jo_libs (the list).
To install jo_housing :
- Download the library: jo_libs
- Unzip the folder and drop it in your resource folder
- Download jo_housing from your account
- Unzip the folder and drop both
jo_housingANDjo_housing_interiorsin your resource folder - Add those two ensure in your server.cfg :
ensure jo_libsensure jo_housing(jo_housing_interiorswill be automatically ensured)
- This script uses the raw keys module, if you have any problem with the prompts you should set the keyboard layout
- If you want to use house key item, you must add House Key Item in your inventory:
:::: tabs
::: tab Example : VORP Framework
Add this item configuration into your items database table:
INSERT INTO `items` (`item`, `label`, `limit`, `can_remove`, `type`, `usable`, `groupId`, `desc`, `weight`)
VALUES ('house_key', 'House key', '10', '1', 'item_standard', '0', '1', 'A house key', '0.10');
:::
::: tab Example : RSG Framework V2
Add this item configuration to your RSG items file:
house_key = {
name = "house_key",
label = "A house key",
weight = 0,
type = "item",
image = "your_key_image.png",
unique = true,
useable = false,
shouldClose = false,
description = "A house key"
}
:::
::::
Congratulation, the Housing script is ready to be used! :::warning Be sure you have oxmysql ensure in your server.cfg ::: :::tip π‘ No SQL File The script automatically creates all necessary database tables during its first startup ::: :::danger π Script requirements Stable, Wagon and Wardrobe are not included. You have to link them with your other scripts. :::
2. Usage > Create / Update / Delete houses
The housing system provides an admin interface to manage properties on your server.
[!NOTE]
jo_housingsupports three distinct types of properties: MLOs, Zones and Shells. MLO and Zone houses are physically part of the game world, so they now share the same outside flow for buying, door interactions, inside/outside detection and build mode. In contrast, Shell houses use pre-defined propset interiors that exist separately from the main map. When a player enters a Shell house, they are teleported from the front door to an instance of the interior, which the script spawns on demand.
:::tip π Permission Control (By job, grade,etc.)
By default, any player can use the /houseManager command to create and manage houses.
You can restrict access by using the canUseHouseManagerCommand filter to implement your own permission system.
:::
:::: tabs
::: tab π¨ Creating a Shell House
-
Use the command
/houseManagerto open the housing management menu -
Select Create a new house, then choose the
Shelltype -
Fill in the house details :
- Name: Give your house a descriptive name
- Category: Choose from available interior categories (Houses, Shacks, Manors, etc.)
- Rooms Amount: Select the number of rooms for your chosen category
- Interior: Pick a specific interior
- Shell Location: Place the interior shell in the world
- Front Door Location: Move the entrance marker
- Contract Type: Choose between one-time sale or rent
- If rent: Select daily or weekly rent periods
- Price: Set money and gold prices
- Features:
- Stable: Enable/disable horse storage
- Stable Location: Place the stable interaction marker
- Stable Spawn Location: Place where horses will spawn
- Storage: Enable/disable item storage with weight/slot limits
- Wagon: Enable/disable wagon storage
- Wagon Location: Place the wagon interaction marker
- Wagon Spawn Location: Place where wagons will spawn
- Dressing Room: Enable/disable wardrobe functionality
- Stable: Enable/disable horse storage
-
Visit Mode: Press the visit mode key (default: R) to preview the interior
-
Validation: All required fields must be completed:
- House name cannot be empty
- Front door location must be set
- Valid interior must be selected
- Shell location must be placed
- If stable enabled: Both stable location and spawn location required
- If wagon enabled: Both wagon location and spawn location required
- Prices must be non-negative
-
Press the "Create House" key when all requirements are met
[!TIP] π‘ Multiple houses on the same location If you create multiple houses with the same front door location, all will be merged into one location menu. This allows you to virtually create 'buildings' with multiple flats with only one entry!
:::
::: tab π¨ Creating a MLO House
-
Use the command
/houseManagerto open the housing management menu -
Select Create a new house, then choose the
MLOtype -
Fill in the house details :
- Name: Give your house a descriptive name
- Interior: Go inside the house you want to create and press
Enterto set the interior - Add doors: While hovering this item, you can walk around the house and register the various doors. Each door you add will be treated as an access point for the property, showing the interaction prompt and marker (if enabled) when a player gets close. These registered doors are also used by the dedicated outside door menu and the quick open / close prompt.
- Contract Type: Choose between one-time sale or rent
- If rent: Select daily or weekly rent periods
- Price: Set money and gold prices
- Features:
- Stable: Enable/disable horse storage
- Stable Location: Place the stable interaction marker
- Stable Spawn Location: Place where horses will spawn
- Storage: Enable/disable item storage with weight/slot limits
- Wagon: Enable/disable wagon storage
- Wagon Location: Place the wagon interaction marker
- Wagon Spawn Location: Place where wagons will spawn
- Dressing Room: Enable/disable wardrobe functionality
- Stable: Enable/disable horse storage
-
Validation: All required fields must be completed:
- House name cannot be empty
- House interior must be set
- At least one door must be registered
- If stable enabled: Both stable location and spawn location required
- If wagon enabled: Both wagon location and spawn location required
- Prices must be non-negative
-
Press the "Create House" key when all requirements are met (you'll need to go outside the house first) :::
2. Usage > Create / Update / Delete houses
::: tab π¨ Creating a Zone House
-
Use the command
/houseManagerto open the housing management menu -
Select Create a new house, then choose the
Zonetype -
Fill in the house details :
- Name: Give your house a descriptive name
- Zone: Use the zone creator to add points and define the "inside" zone. This same zone is later reused for inside / outside checks, build mode safety and furniture placement validation.
- Add doors: While hovering this item, you can walk around the house and register the various doors. Each door you add will be treated as an access point for the property, showing the interaction prompt and marker (if enabled) when a player gets close. These registered doors are also used by the dedicated outside door menu and the quick open / close prompt.
- Contract Type: Choose between one-time sale or rent
- If rent: Select daily or weekly rent periods
- Price: Set money and gold prices
- Features:
- Stable: Enable/disable horse storage
- Stable Location: Place the stable interaction marker
- Stable Spawn Location: Place where horses will spawn
- Storage: Enable/disable item storage with weight/slot limits
- Wagon: Enable/disable wagon storage
- Wagon Location: Place the wagon interaction marker
- Wagon Spawn Location: Place where wagons will spawn
- Dressing Room: Enable/disable wardrobe functionality
- Stable: Enable/disable horse storage
-
Validation: All required fields must be completed:
- House name cannot be empty
- House zone must be set
- At least one door must be registered
- If stable enabled: Both stable location and spawn location required
- If wagon enabled: Both wagon location and spawn location required
- Prices must be non-negative
-
Press the "Create House" key when all requirements are met (you'll need to go outside the house first) :::
::: tab βοΈ Updating a House Updating a House:
- Use the command
/houseManagerto open the housing management menu - Select "Manage houses"
- Choose the house you want to modify
- Press the "Edit House" prompt key (default: E)
- Edit Mode Restrictions:
- <Badge type="tip" text="Shell houses" /> : Category, rooms amount, interior type and house type cannot be changed
- <Badge type="tip" text="MLO houses" /> : House type and interior cannot be changed
- <Badge type="tip" text="Zone houses" /> : House type cannot be changed
- All other properties can be modified
- Visit mode is available to preview changes
- Modify any editable house details as needed
- Press "Update House" to save your changes (only saves if changes were made) :::
::: tab ποΈ Deleting a House Deleting a House:
- Use the command
/houseManagerto open the housing management menu - Select "Manage houses"
- Choose the house you want to delete
- Press the "Delete House" prompt key (default: X)
- The house will be permanently deleted along with all associated data :::
::::
2. Usage > Buying a house
Players can purchase or rent available houses throughout your server.
:::: tabs
::: tab π Finding Available Houses Finding Available Houses:
- Approach a house door with the help of the map blips
- Press the front door prompt key (default: E) to open the contextual menu
- If several properties share the same entrance, first choose the unit you want to inspect :::
::: tab π° Purchasing a House
Purchasing a House:
- For
Shellhouses, the location menu lists the available units at that entrance - For unowned
MLOandZonehouses, the script opens a dedicated buy menu - Available properties will show their sale or rent price
- Press the "Buy House" prompt key (default: ENTER) to purchase with money
- Alternatively, press the "Buy with Gold" key (default: G) if enabled
- For rental properties:
- Select the number of days/weeks to rent using the slider
- Press the appropriate key to pay with money or gold
- Once purchased, the house switches to its owner flow:
Shell: shell entry and interior menu flowMLO/Zone: dedicated door menu and quick door prompt
:::
::: tab π Rental Information Rental Information:
- Rentals must be renewed before they expire
- The house menu shows your current rental status:
- π’ Green: Plenty of time remaining
- π Orange: Rent due soon (warning period)
- π΄ Red: Grace period (overdue but not yet evicted)
- If rent expires beyond the grace period, the house will return to the market :::
::::
2. Usage > Using a house
Once you own a house, you can use its features and customize its interior.
:::: tabs
::: tab πͺ Entering Your House Entering Your House:
- Approach your house's entrance
For <Badge type="tip" text="Shell houses" /> :
- Press the "Enter House" prompt key (default: ENTER)
- You'll be teleported inside your private shell instance
- Inside the shell, use the entrance prompts to open the interior menu or leave the house
For <Badge type="tip" text="MLO houses" /> and <Badge type="tip" text="Zone houses" />:
- Press the front door menu key (default: E) to open the dedicated door menu
- Depending on your access, this menu can show actions such as:
- Open / Close door
- Manage my house
- Enter build mode
- Knock on house
- If you are close to an eligible registered door, you can also use the quick door prompt (default: ENTER) to directly open or close the nearest door without opening the menu
- The quick door prompt label automatically switches between "Open door" and "Close door"
- Door states are synchronized between players
- Access to
MLO/Zonedoors depends on ownership, accessibility mode, access list permissions andConfig.enableKeyMode:::
::: tab π οΈ Build Mode Build Mode:
- Open the menu that matches your house type
Shell: use the interior menu near the entrance from inside the houseMLO/Zone: use the dedicated door menu
- Select "Enter build mode"
- For
MLOandZonehouses, this option is only shown to eligible players, and it only becomes available while you are physically inside the house bounds - In build mode, you can:
- Press the "Add Furnitures" key (default: A) to purchase and place furniture
- Press the "Edit Furnitures" key (default: E) to move, duplicate or delete existing furniture
- Set locations for dressing rooms and storage if your house has these features
- Furniture placement is validated according to the house type:
Shell: around the spawned shell interiorMLO: inside the registered interiorZone: inside the defined zone
- If you leave the bounds of an
MLOorZonehouse while building or editing, build mode closes automatically Zonehouses display their zone boundaries during build mode to make placement clearer- Press the "Leave Build Mode" key (default: R) to exit :::
::: tab π Managing Access Managing Access:
The access management options depend on your server's Config.enableKeyMode setting:
When Key Mode is Disabled (Config.enableKeyMode = false):
- Open the house menu for your property
- Select "Manage my house"
- Choose "Manage Access"
- Set your access type:
- "Only me": Only you can enter
- "List": Only players you've added to the access list can enter or use
MLO/Zonedoor interactions - "Everyone": Any player can enter your house and use
MLO/Zonedoor interactions
- If using the "List" option, you can add or remove players from your access list
- After adding a player, you can select them to manage their specific permissions:
- Can access storage
- Can access wardrobe
- Can add furniture
- Can edit furniture
- Access and permission updates are synchronized immediately for online players, even if they are currently outside the house
When Key Mode is Enabled (Config.enableKeyMode = true):
- Open the house menu for your property
- Select "Manage my house"
- Choose "Manage Access"
- Set your access type:
- "Anyone with the key": Anyone who has a key to your house can enter
- "Everyone": Any player can enter your house and toggle
MLO/Zonedoors
- Additional key management options:
- Buy new key: Purchase additional keys to give to other players
- Change lock: Change your house lock, making all existing keys obsolete (you'll receive a new key)
- For owned
MLOandZonehouses, door toggling follows the same key rules: a valid key is required unless the house is set toEveryone
If an access or permission change is invalid or not allowed, the player receives an error notification. :::
::: tab π Using House Features Using House Features:
- Storage: Approach your storage location and press the prompt key (default: E)
- Dressing Room* : Approach your dressing location and press the prompt key (default: E)
- Stable* : Approach the stable marker outside your house to access your horses
- Wagon* : Approach the wagon marker outside your house to access your wagons
* Integration Required <br> This script does not have built-in solutions for dressing, stable and wagon functionality. You need to integrate with your existing resources using the external handler functions.
:::
::: tab π₯ Inviting Players Inviting Players:
- Visitors can knock on an owned house from the front door or from the
MLO/Zonedoor menu - For
Shellhouses, eligible players inside receive a notification and can directly welcome the visitor in - For
MLOandZonehouses, eligible players are notified that someone is at the door and should go to the door to let them in - Alternatively, add the visitor to your access list for permanent access or give them a key if
Config.enableKeyModeistrue:::
::: tab π€ Transferring Ownership Transferring Ownership:
- Open the house menu for your property
- Select "Manage my house"
- Choose "Transfer House"
- Enter the player's server ID
- The house ownership will transfer to that player :::
::::
:::tip π‘ Key Mode Configuration
The Config.enableKeyMode setting fundamentally changes how house access is managed. Choose the mode that best fits your server's desired gameplay style.
π Key Mode Enabled
When Config.enableKeyMode = true, house access is tied to a physical key item, creating a more immersive experience.
2. Usage > Using a house
- Ownership: Players receive a key in their inventory upon purchasing a house.
- Sharing: Owners can buy additional keys to give to friends or other players.
- Security: An owner can change the locks at any time. This action makes all previously issued keys for that house obsolete and provides the owner with a new one.
- Requirement: A player must have the corresponding key in their inventory to enter the house. For owned
MLOandZonehouses, the same rule also applies to door toggling unless the house accessibility is set toEveryone.
π€ Access List Mode
When Config.enableKeyMode = false, access is managed digitally through an in-game menu, offering a simpler, hassle-free system.
- No Items: This mode does not use physical key items.
- Management: Owners manage a digital access list for their property via the house menu.
- Permissions: The owner can instantly grant or revoke access to any player.
- Granular Controls: For each player on the list, the owner can set specific permissions:
- Can access storage
- Can access wardrobe
- Can add furniture
- Can edit furniture
- Requirement: Players on the access list can enter without needing any specific item. On
MLOandZonehouses, the same access rules also govern the door menu and quick door prompt. :::
3. Interiors Shells Gallery
Browse through all available interior options for the Shell houses.
This gallery showcases the complete collection of interiors you can choose from when creating houses of type Shell using the /houseManager command.
:::details The gallery <InteriorGallery /> :::
4. Script Configuration
<ScriptConfig scriptPath="redm/housing" />
5. FAQ
:::details It's raining in my house ! Weather effects (rain, snow) can appear inside interiors due to your framework's weather synchronization system. To fix this, you need to disable weather sync when players enter houses and re-enable it when they leave.
Solution: Use the housing script's server actions to control your framework's weather sync:
-- Disable weather sync when entering a house
exports.jo_housing:registerAction('houseEntered', function(source, house, isVisiting)
-- Weather sync from kibook
TriggerClientEvent('weathersync:setSyncEnabled', source, false)
end)
-- Re-enable weather sync when leaving a house
exports.jo_housing:registerAction('houseLeft', function(source, house)
-- Weather sync from kibook
TriggerClientEvent('weathersync:setSyncEnabled', source, true)
end)
Reference: houseEntered action and houseLeft action :::
:::details Can I add custom interiors ?
Yes! You can add your own custom interiors using the addInteriors filter. This allows you to integrate custom MLO interiors or propsets into the housing system.
How to add custom interiors:
-- In your server-side resource or in jo_housing itself
exports.jo_housing:registerFilter('addInteriors', function(customInteriors)
-- Add your custom interiors
customInteriors.my_custom_cabin = {
entries = {
vec4(2.022125, -0.556265, 1.696404, 91.094) -- Main door spawn point (relative to interior origin)
},
propset = "my_custom_cabin", -- Interior propset/MLO name
category = "shack", -- Interior category (house, shack, manor, flat, rock_shack, worker)
numberRoom = 2, -- Number of rooms in the interior
insideDoors = { -- Optional: Interior working doors configuration
{
model = "p_door04x",
position = vec3(0.062589, -4.6552873, 0.738253)
}
}
}
customInteriors.luxury_penthouse = {
entries = {
vec4(0.0, 0.0, 2.0, 180.0) -- Main door spawn point
},
propset = "luxury_penthouse_mlo",
category = "manor",
numberRoom = 8
-- insideDoors is optional - omit if no working interior doors needed
}
return customInteriors
end)
Configuration Tips:
- Set furniture limits for your custom interiors in
Config.interiorsMaxFurnitures - Use
/houseManagervisit mode to test and preview your interior placement - Interior categories affect available furniture limits and UI organization
Reference: addInteriors filter in the Developer section :::
:::details Can I add custom furnitures (props) ?
Yes! You can add custom furniture categories and props using the addFurnitures filter. This allows you to expand the available furniture options beyond the default categories.
How to add custom furniture:
-- In your server-side resource or in jo_housing itself
exports.jo_housing:registerFilter('addFurnitures', function(customFurnitures)
-- Add your custom furniture categories
customFurnitures.custom_electronics = {
"p_tv01x",
"p_radio01x",
"p_lamp_handheld01x",
"p_phonograph01x"
}
customFurnitures.outdoor_furniture = {
"p_bench05x",
"p_campfire01x",
"p_tent01x",
"p_waterbarrel01x"
}
customFurnitures.western_decor = {
"p_spittoon01x",
"p_horseshoe01x",
"p_banjo01x"
}
return customFurnitures
end)
Don't forget to configure pricing:
Add pricing for your custom categories in your overwriteConfig.lua:
-- Configure pricing for custom furniture categories
Config.furnituresCategoriesPrices.custom_electronics = {
money = 250,
gold = 3
}
Config.furnituresCategoriesPrices.outdoor_furniture = {
money = 75,
gold = 1
}
-- You can also set specific prices for individual props
Config.furnituresPrices.p_tv01x = {
money = 500,
gold = 5
}
Reference: addFurnitures filter and Furniture Configuration in the Developer section :::
:::details Can I disable the Build Mode ?
If you set the interiorβs max furniture to 0 (zero), players wonβt be able to add any furniture inside, effectively disabling build mode for that interior.
Example:
-- Available interior categories: shack, rock_shack, house, flat, manor, worker
-- Default furniture limit for interior categories
Config.interiorsCategoriesMaxFurnitures = {
default = 0, -- Disable build mode for all interiors
manor = 200 -- Except for the manor category
}
-- Specific furniture limits per interior ID
Config.interiorsMaxFurnitures = {
jo_pai_house = 0, -- Disable build mode only for jo_pai_house
}
:::
:::details The prompts are not working ! If prompts aren't appearing or responding, this is usually related to key binding or keyboard layout issues. Here are the most common solutions:
Primary Solution - Keyboard Layout: This script uses the raw keys module. If you have problems with prompts, set the keyboard layout properly.
Additional Troubleshooting Steps:
-
Check for Key Conflicts:
- Other resources might be using the same keys
- Review your
Config.keyssettings inoverwriteConfig.lua - Try changing conflicting keys to different bindings
-
Verify Distance Settings:
- Make sure you're close enough to interact with objects
- Check
Config.distanceShowHousePromptand related distance settings - Default house prompt distance is 2.5 meters
5. FAQ
- Framework Compatibility:
- Ensure your framework is compatible with jo_libs
- Check that jo_libs is properly installed and started before jo_housing :::
6. For Developers > Actions
Actions are one of the two types of Hooks. They provide a way for running a function at a specific point in the execution of scripts. Callback functions for an Action do not return anything back to the calling Action hook. They are the counterpart to Filters.
Below is a complete list of all available actions in the jo_housing script.
6. For Developers > Actions > <Badge type="server" text="Server" /> accessibilityChanged
Triggered when house accessibility settings are changed.
-- @param source - serverID of the house owner
-- @param house - the house object
-- @param accessibilityType - new accessibility type ("everyone", "list", or "onlyMe")
exports.jo_housing:registerAction('accessibilityChanged', function(source, house, accessibilityType)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> buildModeEntered
Triggered when a player enters build mode in their house.
-- @param source - serverID of the player
exports.jo_housing:registerAction('buildModeEntered', function(source)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> dressingLocationSet
Triggered when a dressing room location is set in a house.
-- @param source - serverID of the player
-- @param house - the house object
-- @param coords - coordinates of the dressing location
exports.jo_housing:registerAction('dressingLocationSet', function(source, house, coords)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> furnitureBought
Triggered when a player purchases furniture for their house.
-- @param source - serverID of the player
-- @param house - the house object where furniture was bought
-- @param furniture - the furniture object that was purchased
exports.jo_housing:registerAction('furnitureBought', function(source, house, furniture)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> furnitureDeleted
Triggered when furniture is deleted from a house.
-- @param source - serverID of the player deleting the furniture
-- @param house - the house object containing the furniture
-- @param furnitureId - ID of the furniture that was deleted
exports.jo_housing:registerAction('furnitureDeleted', function(source, house, furnitureId)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> furnitureMoved
Triggered when furniture is moved within a house.
-- @param source - serverID of the player
-- @param house - the house object containing the furniture
-- @param furnitureId - ID of the furniture that was moved
exports.jo_housing:registerAction('furnitureMoved', function(source, house, furnitureId)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseBought
Triggered when a player successfully purchases a house.
-- @param source - serverID of the buyer
-- @param house - the house object that was purchased
exports.jo_housing:registerAction('houseBought', function(source, house)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseCreated
Triggered when a new house is created .
-- @param source - serverID of the player who created the house
-- @param house - the newly created house object
exports.jo_housing:registerAction('houseCreated', function(source, house)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseDeleted
Triggered when a house is deleted .
-- @param source - serverID of the player who deleted the house
-- @param house - the house object that was deleted
exports.jo_housing:registerAction('houseDeleted', function(source, house)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseEntered
Triggered when a player enters a house.
-- @param source - serverID of the player
-- @param house - the house object being entered
-- @param isVisiting - boolean indicating if the player is visiting
exports.jo_housing:registerAction('houseEntered', function(source, house, isVisiting)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseKeyBought
Triggered when a new house key is purchased.
-- @param source - serverID of the player buying the key
-- @param house - the house object
exports.jo_housing:registerAction('houseKeyBought', function(source, house)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseLeft
Triggered when a player leaves a house.
-- @param source - serverID of the player
-- @param house - the house object being left
exports.jo_housing:registerAction('houseLeft', function(source, house)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseLocationMenuOpened
Triggered when a player opens the house location menu.
-- @param source - serverID of the player
-- @param houses - array of nearby houses
exports.jo_housing:registerAction('houseLocationMenuOpened', function(source, houses)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseLockChanged
Triggered when a house lock is changed.
-- @param source - serverID of the house owner
-- @param house - the house object
-- @param success - boolean indicating if lock change was successful
exports.jo_housing:registerAction('houseLockChanged', function(source, house, success)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseStorageOpened
Triggered when a player opens house storage.
-- @param source - serverID of the player
-- @param house - the house object
-- @param invId - inventory ID that was opened
exports.jo_housing:registerAction('houseStorageOpened', function(source, house, invId)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseTransfered
Triggered when house ownership is transferred to another player.
-- @param source - serverID of the current owner
-- @param toPlayerSrc - serverID of the new owner
-- @param house - the house object being transferred
-- @param transferDone - boolean indicating if transfer was successful
exports.jo_housing:registerAction('houseTransfered', function(source, toPlayerSrc, house, transferDone)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseUpdated
Triggered when an existing house is updated .
-- @param source - serverID of the player who updated the house
-- @param house - the updated house object
-- @param changeset - table containing the changes made
exports.jo_housing:registerAction('houseUpdated', function(source, house, changeset)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseWardrobeOpened
Triggered when a player opens house wardrobe.
-- @param source - serverID of the player
-- @param house - the house object
exports.jo_housing:registerAction('houseWardrobeOpened', function(source, house)
-- Your code here
end)
#### <Badge type="server" text="Server" /> knockedOnHouse
Triggered when someone knocks on a house door.
```lua
-- @param source - serverID of the player knocking
-- @param house - the house object being knocked on
-- @param foundSources - array of player sources who were notified (propset: eligible players inside the house, MLO/Zone: notified targets excluding the knocker)
exports.jo_housing:registerAction('knockedOnHouse', function(source, house, foundSources)
-- Your code here
end)
Rental & Keys Actions
<Badge type="server" text="Server" /> playerAddedToHouse
Triggered when a player is added to a house's access list.
-- @param source - serverID of the house owner
-- @param house - the house object
-- @param playerSrc - serverID of the player being added
-- @param playerName - name of the player being added
exports.jo_housing:registerAction('playerAddedToHouse', function(source, house, playerSrc, playerName)
-- Your code here
end)
<Badge type="server" text="Server" /> playerPermissionsChanged
Triggered when the permissions for a player on the access list are changed.
-- @param source - serverID of the house owner
-- @param house - the house object
-- @param accessibilityId - ID of the access entry being changed
-- @param permissions - table containing the new permissions
exports.jo_housing:registerAction('playerPermissionsChanged', function(source, house, accessibilityId, permissions)
-- Your code here
end)
<Badge type="server" text="Server" /> playerRemovedFromHouse
Triggered when a player is removed from a house's access list.
-- @param source - serverID of the house owner
-- @param house - the house object
-- @param accessibilityId - ID of the access entry that was removed
-- @param success - boolean indicating if removal was successful
exports.jo_housing:registerAction('playerRemovedFromHouse', function(source, house, accessibilityId, success)
-- Your code here
end)
<Badge type="server" text="Server" /> storageLocationSet
Triggered when a storage location is set in a house.
-- @param source - serverID of the player
-- @param house - the house object
-- @param coords - coordinates of the storage location
exports.jo_housing:registerAction('storageLocationSet', function(source, house, coords)
-- Your code here
end)
Access Management Actions
<Badge type="server" text="Server" /> rentPaid
Triggered when rent is paid for a house.
-- @param source - serverID of the player paying rent
-- @param house - the house object
-- @param numPeriods - number of periods paid for
-- @param isDaily - boolean indicating if it's daily or weekly rent
-- @param totalPrice - total amount paid
-- @param moneyType - payment type (0 for money, 1 for gold)
-- @param success - boolean indicating if payment was successful
exports.jo_housing:registerAction('rentPaid', function(source, house, numPeriods, isDaily, totalPrice, moneyType, success)
-- Your code here
end)
Filters
Filters allow you to modify data or control permissions during script execution. Introduced in v1.2.0, filters provide a synchronous way to intercept and modify script behavior at specific points, unlike events which are asynchronous.
Below is a complete list of all available filters in the jo_housing script.
<Badge type="server" text="Server" /> addFurnitures
Allows you to add custom furniture categories and items to the housing system.
-- @param customFurnitures - empty table by default
-- @return table - table with custom furniture categories
exports.jo_housing:registerFilter('addFurnitures', function(customFurnitures)
-- Add your custom furniture categories
customFurnitures.custom_electronics = {
"p_tv01x",
"p_radio01x",
"p_lamp_handheld01x"
}
customFurnitures.outdoor_furniture = {
"p_bench05x",
"p_campfire01x",
"p_tent01x"
}
return customFurnitures
end)
:::tip π‘ Custom Furniture Pricing
Don't forget to configure pricing for your custom categories in Config.furnituresCategoriesPrices or specific items in Config.furnituresPrices.
-- In your overwriteConfig.lua
Config.furnituresCategoriesPrices.custom_electronics = {
money = 250,
gold = 3
}
Config.furnituresCategoriesPrices.outdoor_furniture = {
money = 75,
gold = 1
}
:::
<Badge type="server" text="Server" /> addInteriors
Allows you to add custom interior configurations to the housing system.
6. For Developers > Actions > <Badge type="server" text="Server" /> houseWardrobeOpened
-- @param customInteriors - empty table by default
-- @return table - table with custom interior configurations
exports.jo_housing:registerFilter('addInteriors', function(customInteriors)
-- Add your custom interiors
customInteriors.my_custom_cabin = {
entries = {
vec4(2.022125, -0.556265, 1.696404, 91.094) -- Main door spawn point (relative to interior origin)
},
propset = "my_custom_cabin", -- Interior propset/MLO name
category = "shack", -- Interior category (house, shack, manor, flat, rock_shack, worker)
numberRoom = 2, -- Number of rooms in the interior
insideDoors = { -- Optional: Interior working doors configuration
{
model = "p_door04x",
position = vec3(0.062589, -4.6552873, 0.738253)
},
{
model = "p_door04x",
position = vec3(-1.473662, -4.661302, 0.738253)
},
}
}
customInteriors.luxury_penthouse = {
entries = {
vec4(0.0, 0.0, 2.0, 180.0) -- Main door spawn point (relative to interior origin)
},
propset = "luxury_penthouse_mlo",
category = "manor",
numberRoom = 8
-- insideDoors is optional - omit if no working interior doors needed
}
return customInteriors
end)
Interior Properties:
| Property | Type | Required | Description |
|---|---|---|---|
entries |
table |
β | Array containing the main door spawn point (vec4 with heading). Only the first entry is used, coordinates are relative to interior origin |
propset |
string |
β | Interior propset/MLO resource name |
category |
string |
β | Interior category: house, shack, manor, flat, rock_shack, worker |
numberRoom |
number |
β | Number of rooms in the interior |
insideDoors |
table |
β | Optional array of interior doors with model and position properties |
:::tip π‘ Interior Configuration
- Configure furniture limits for your custom interiors using
Config.interiorsMaxFurnituresor category limits withConfig.interiorsCategoriesMaxFurnitures - Test your interior coordinates thoroughly - use
/houseManagervisit mode to preview placement - Interior categories affect available furniture limits and UI organization
-- In your overwriteConfig.lua
Config.interiorsMaxFurnitures.my_custom_cabin = 150
Config.interiorsCategoriesMaxFurnitures.luxury = 300 -- If you add a custom category
:::
<Badge type="server" text="Server" /> canAddPlayerToHouse
Controls who can add players to a house's access list.
-- @param canAdd - boolean indicating if the action is allowed by default
-- @param source - serverID of the player adding someone
-- @param houseId - ID of the house
-- @param playerSrc - serverID of the player being added
-- @param playerName - name of the player being added
exports.jo_housing:registerFilter('canAddPlayerToHouse', function(canAdd, source, houseId, playerSrc, playerName)
return canAdd
end)
<Badge type="server" text="Server" /> canBuyFurniture
Controls who can buy furniture.
-- @param canBuy - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param furniture - furniture model/object data
-- @param houseId - ID of the house
-- @param moneyType - payment type (0 for money, 1 for gold)
-- @param categoryKey - category key of the furniture
exports.jo_housing:registerFilter('canBuyFurniture', function(canBuy, source, furniture, houseId, moneyType, categoryKey)
return canBuy
end)
<Badge type="server" text="Server" /> canBuyHouse
Controls who can buy a house.
-- @param canBuy - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house being purchased
-- @param moneyType - payment type (0 for money, 1 for gold)
-- @param period - for rentals, number of periods the player is paying for
exports.jo_housing:registerFilter('canBuyHouse', function(canBuy, source, houseId, moneyType, period)
return canBuy
end)
<Badge type="server" text="Server" /> canDeleteFurniture
Controls who can delete furniture from a house.
-- @param canDelete - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param furnitureId - ID of the furniture
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canDeleteFurniture', function(canDelete, source, furnitureId, houseId)
return canDelete
end)
<Badge type="server" text="Server" /> canDeleteHouse
Controls who can delete houses.
-- @param canDelete - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseData - table containing house data
exports.jo_housing:registerFilter('canDeleteHouse', function(canDelete, source, houseData)
return canDelete
end)
<Badge type="server" text="Server" /> canEnterBuildMode
Controls who can enter build mode in a house.
6. For Developers > Actions > <Badge type="server" text="Server" /> houseWardrobeOpened
-- @param canEnter - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canEnterBuildMode', function(canEnter, source, houseId)
return canEnter
end)
<Badge type="server" text="Server" /> canEnterHouse
Controls who can enter a house.
Door toggling for owned MLO and Zone houses is handled separately by canToggleHouseDoor.
-- @param canEnter - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house being entered
exports.jo_housing:registerFilter('canEnterHouse', function(canEnter, source, houseId)
return canEnter
end)
<Badge type="server" text="Server" /> canGetPlayersAccessibilityList
Controls who can retrieve the list of players with access to a house.
-- @param canGet - boolean indicating if the action is allowed by default
-- @param source - serverID of the player requesting the list
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canGetPlayersAccessibilityList', function(canGet, source, houseId)
return canGet
end)
<Badge type="server" text="Server" /> canMoveFurniture
Controls who can move furniture in a house.
-- @param canMove - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param furnitureId - ID of the furniture
-- @param houseId - ID of the house
-- @param relPos - new relative position for the furniture
-- @param relRot - new relative rotation for the furniture
exports.jo_housing:registerFilter('canMoveFurniture', function(canMove, source, furnitureId, houseId, relPos, relRot)
return canMove
end)
<Badge type="server" text="Server" /> canOpenHouseLocationMenu
Controls who can open the house location menu.
-- @param canOpen - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houses - array of nearby houses
exports.jo_housing:registerFilter('canOpenHouseLocationMenu', function(canOpen, source, houses)
return canOpen
end)
<Badge type="server" text="Server" /> canOpenHouseStorage
Controls who can open a house's storage.
-- @param canOpenStorage - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canOpenHouseStorage', function(canOpenStorage, source, houseId)
return canOpenStorage
end)
<Badge type="server" text="Server" /> canOpenHouseWardrobe
Controls who can open a house's wardrobe.
-- @param canOpen - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canOpenHouseWardrobe', function(canOpen, source, houseId)
return canOpen
end)
<Badge type="server" text="Server" /> canPlaceFurniture
Controls who can place furniture in a house.
-- @param canPlace - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param furniture - furniture model/object data
-- @param houseId - ID of the house
-- @param relPos - relative position where furniture will be placed
-- @param relRot - relative rotation of the furniture
-- @param moneyType - payment type (0 for money, 1 for gold)
-- @param categoryKey - category key of the furniture
exports.jo_housing:registerFilter('canPlaceFurniture', function(canPlace, source, furniture, houseId, relPos, relRot, moneyType, categoryKey)
return canPlace
end)
<Badge type="server" text="Server" /> canRemovePlayerFromHouse
Controls who can remove players from a house's access list.
-- @param canRemove - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
-- @param accessibilityId - ID of the access entry to remove
exports.jo_housing:registerFilter('canRemovePlayerFromHouse', function(canRemove, source, houseId, accessibilityId)
return canRemove
end)
<Badge type="server" text="Server" /> canSetDressingLocation
Controls who can set a dressing room location inside a house.
-- @param canSet - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
-- @param coords - coordinates for the dressing location
exports.jo_housing:registerFilter('canSetDressingLocation', function(canSet, source, houseId, coords)
return canSet
end)
<Badge type="server" text="Server" /> canSetStorageLocation
Controls who can set a storage location inside a house.
-- @param canSet - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
-- @param coords - coordinates for the storage location
exports.jo_housing:registerFilter('canSetStorageLocation', function(canSet, source, houseId, coords)
return canSet
end)
<Badge type="server" text="Server" /> canToggleHouseDoor
Controls who can open or close an owned MLO or Zone house door.
This filter is evaluated by the dedicated server door-toggle callback, separately from canEnterHouse.
-- @param canToggle - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canToggleHouseDoor', function(canToggle, source, houseId)
return canToggle
end)
<Badge type="server" text="Server" /> canTransferHouse
Controls who can transfer house ownership.
6. For Developers > Actions > <Badge type="server" text="Server" /> houseWardrobeOpened
-- @param canTransfer - boolean indicating if the action is allowed by default
-- @param source - serverID of the current owner
-- @param toPlayerSrc - serverID of the player receiving the house
-- @param houseId - ID of the house being transferred
exports.jo_housing:registerFilter('canTransferHouse', function(canTransfer, source, toPlayerSrc, houseId)
return canTransfer
end)
<Badge type="server" text="Server" /> canUpdateAccessibility
Controls who can update a house's accessibility settings.
-- @param canUpdate - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param accessibilityType - type of access ("everyone", "list", or "onlyMe")
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canUpdateAccessibility', function(canUpdate, source, accessibilityType, houseId)
return canUpdate
end)
<Badge type="server" text="Server" /> canUpdatePlayerPermissions
Controls who can update permissions for a player on a house's access list.
-- @param canUpdate - boolean indicating if the action is allowed by default
-- @param source - serverID of the player making the changes
-- @param houseId - ID of the house
-- @param accessibilityId - ID of the access entry being changed
-- @param permissions - table of the new permissions
exports.jo_housing:registerFilter('canUpdatePlayerPermissions', function(canUpdate, source, houseId, accessibilityId, permissions)
return canUpdate
end)
<Badge type="server" text="Server" /> canUpsertHouse
Controls who can create or update houses.
-- @param canUpsert - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house (nil for creation)
-- @param changesetOrHouseData - changes to apply or full house data for creation
exports.jo_housing:registerFilter('canUpsertHouse', function(canUpsert, source, houseId, changesetOrHouseData)
return canUpsert
end)
<Badge type="server" text="Server" /> canUseHouseManagerCommand
Controls who can use the /houseManager command to create and manage houses.
-- @param canUse - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
exports.jo_housing:registerFilter('canUseHouseManagerCommand', function(canUse, source)
-- Example: Only allow admins
local isAdmin = exports.your_permission_system:isAdmin(source)
return isAdmin
end)
:::details Example of job lock for VORP
AllowedJobs = {
houser = true,
houseManager = true,
}
exports.jo_housing:registerFilter('canUseHouseManagerCommand', function(canUse, source)
local job = jo.framework:getJob(source)
if AllowedJobs[job] then
return canUse
else
jo.notif.rightError("You don't have the right job to use the house manager")
return false
end
end)
:::
2. Usage > Create / Update / Delete houses
The housing system provides an admin interface to manage properties on your server.
[!NOTE]
jo_housingsupports three distinct types of properties: MLOs, Zones and Shells. MLO and Zone houses are physically part of the game world, so they now share the same outside flow for buying, door interactions, inside/outside detection and build mode. In contrast, Shell houses use pre-defined propset interiors that exist separately from the main map. When a player enters a Shell house, they are teleported from the front door to an instance of the interior, which the script spawns on demand.
:::tip π Permission Control (By job, grade,etc.)
By default, any player can use the /houseManager command to create and manage houses.
You can restrict access by using the canUseHouseManagerCommand filter to implement your own permission system.
:::
:::: tabs
::: tab π¨ Creating a Shell House
-
Use the command
/houseManagerto open the housing management menu -
Select Create a new house, then choose the
Shelltype -
Fill in the house details :
- Name: Give your house a descriptive name
- Category: Choose from available interior categories (Houses, Shacks, Manors, etc.)
- Rooms Amount: Select the number of rooms for your chosen category
- Interior: Pick a specific interior
- Shell Location: Place the interior shell in the world
- Front Door Location: Move the entrance marker
- Contract Type: Choose between one-time sale or rent
- If rent: Select daily or weekly rent periods
- Price: Set a
jo.pricingprice group. Payment options can use money, gold, role currency or items, and multiple alternatives can be combined withOR - House Tax: For sale houses only, enable recurring tax and configure its price group and period in days
- Features:
- Stable: Enable/disable horse storage
- Stable Location: Place the stable interaction marker
- Stable Spawn Location: Place where horses will spawn
- Storage: Enable/disable item storage with weight/slot limits
- Wagon: Enable/disable wagon storage
- Wagon Location: Place the wagon interaction marker
- Wagon Spawn Location: Place where wagons will spawn
- Dressing Room: Enable/disable wardrobe functionality
- Stable: Enable/disable horse storage
-
Visit Mode: Press the visit mode key (default: R) to preview the interior
-
Validation: All required fields must be completed:
- House name cannot be empty
- Front door location must be set
- Valid interior must be selected
- Shell location must be placed
- If stable enabled: Both stable location and spawn location required
- If wagon enabled: Both wagon location and spawn location required
- Prices must be non-negative
-
Press the "Create House" key when all requirements are met
[!TIP] π‘ Multiple houses on the same location If you create multiple houses with the same front door location, all will be merged into one location menu. This allows you to virtually create 'buildings' with multiple flats with only one entry!
:::
::: tab π¨ Creating a MLO House
-
Use the command
/houseManagerto open the housing management menu -
Select Create a new house, then choose the
MLOtype -
Fill in the house details :
- Name: Give your house a descriptive name
- Interior: Go inside the house you want to create and press
Enterto set the interior - Add doors: While hovering this item, you can walk around the house and register the various doors. Each door you add will be treated as an access point for the property, showing the interaction prompt and marker (if enabled) when a player gets close. These registered doors are also used by the dedicated outside door menu and the quick open / close prompt.
- Contract Type: Choose between one-time sale or rent
- If rent: Select daily or weekly rent periods
- Price: Set a
jo.pricingprice group. Payment options can use money, gold, role currency or items, and multiple alternatives can be combined withOR - House Tax: For sale houses only, enable recurring tax and configure its price group and period in days
- Features:
- Stable: Enable/disable horse storage
- Stable Location: Place the stable interaction marker
- Stable Spawn Location: Place where horses will spawn
- Storage: Enable/disable item storage with weight/slot limits
- Wagon: Enable/disable wagon storage
- Wagon Location: Place the wagon interaction marker
- Wagon Spawn Location: Place where wagons will spawn
- Dressing Room: Enable/disable wardrobe functionality
- Stable: Enable/disable horse storage
-
Validation: All required fields must be completed:
- House name cannot be empty
- House interior must be set
- At least one door must be registered
- If stable enabled: Both stable location and spawn location required
- If wagon enabled: Both wagon location and spawn location required
- Prices must be non-negative
-
Press the "Create House" key when all requirements are met (you'll need to go outside the house first) :::
2. Usage > Create / Update / Delete houses
::: tab π¨ Creating a Zone House
-
Use the command
/houseManagerto open the housing management menu -
Select Create a new house, then choose the
Zonetype -
Fill in the house details :
- Name: Give your house a descriptive name
- Zone: Use the zone creator to add points and define the "inside" zone. This same zone is later reused for inside / outside checks, build mode safety and furniture placement validation.
- Add doors: While hovering this item, you can walk around the house and register the various doors. Each door you add will be treated as an access point for the property, showing the interaction prompt and marker (if enabled) when a player gets close. These registered doors are also used by the dedicated outside door menu and the quick open / close prompt.
- Contract Type: Choose between one-time sale or rent
- If rent: Select daily or weekly rent periods
- Price: Set a
jo.pricingprice group. Payment options can use money, gold, role currency or items, and multiple alternatives can be combined withOR - House Tax: For sale houses only, enable recurring tax and configure its price group and period in days
- Features:
- Stable: Enable/disable horse storage
- Stable Location: Place the stable interaction marker
- Stable Spawn Location: Place where horses will spawn
- Storage: Enable/disable item storage with weight/slot limits
- Wagon: Enable/disable wagon storage
- Wagon Location: Place the wagon interaction marker
- Wagon Spawn Location: Place where wagons will spawn
- Dressing Room: Enable/disable wardrobe functionality
- Stable: Enable/disable horse storage
-
Validation: All required fields must be completed:
- House name cannot be empty
- House zone must be set
- At least one door must be registered
- If stable enabled: Both stable location and spawn location required
- If wagon enabled: Both wagon location and spawn location required
- Prices must be non-negative
-
Press the "Create House" key when all requirements are met (you'll need to go outside the house first) :::
::: tab βοΈ Updating a House Updating a House:
- Use the command
/houseManagerto open the housing management menu - Select "Manage houses"
- Choose the house you want to modify
- Press the "Edit House" prompt key (default: E)
- Edit Mode Restrictions:
- <Badge type="tip" text="Shell houses" /> : Category, rooms amount, interior type and house type cannot be changed
- <Badge type="tip" text="MLO houses" /> : House type and interior cannot be changed
- <Badge type="tip" text="Zone houses" /> : House type cannot be changed
- All other properties can be modified
- Visit mode is available to preview changes
- Modify any editable house details as needed
- Press "Update House" to save your changes (only saves if changes were made) :::
::: tab ποΈ Deleting a House Deleting a House:
- Use the command
/houseManagerto open the housing management menu - Select "Manage houses"
- Choose the house you want to delete
- Press the "Delete House" prompt key (default: X)
- The house will be permanently deleted along with all associated data :::
::::
2. Usage > Buying a house
Players can purchase or rent available houses throughout your server.
:::: tabs
::: tab π Finding Available Houses Finding Available Houses:
- Approach a house door with the help of the map blips
- Press the front door prompt key (default: E) to open the contextual menu
- If several properties share the same entrance, first choose the unit you want to inspect :::
::: tab π° Purchasing a House
Purchasing a House:
- For
Shellhouses, the location menu lists the available units at that entrance - For unowned
MLOandZonehouses, the script opens a dedicated buy menu - Available properties will show their sale or rent price
- Press the "Buy House" prompt key (default: ENTER) to purchase with money
- Alternatively, press the "Buy with Gold" key (default: G) if enabled
- For rental properties:
- Select the number of days/weeks to rent using the slider
- Press the appropriate key to pay with money or gold
- Once purchased, the house switches to its owner flow:
Shell: shell entry and interior menu flowMLO/Zone: dedicated door menu and quick door prompt
:::
::: tab π Rental Information Rental Information:
- Rentals must be renewed before they expire
- The house menu shows your current rental status:
- π’ Green: Plenty of time remaining
- π Orange: Rent due soon (warning period)
- π΄ Red: Grace period (overdue but not yet evicted)
- If rent expires beyond the grace period, the house will return to the market :::
::: tab π§Ύ House Tax House Tax:
House tax is an optional recurring payment for houses configured as for sale. Rental houses are never taxed because they already use the rent lifecycle.
Tax is configured by an administrator when creating or editing a house:
- House Tax: Enable or disable the tax for the sale house
- Tax Price: Price charged for one tax period; multiple payment alternatives are supported
- Tax Period: Number of days covered by one payment
Once a taxed house is owned:
- The owner can open the house menu and select Pay house tax.
- The menu displays the date until which the tax is paid (
Tax Paid Until). - The owner can pay one or more periods at once, up to the configured advance limit.
- Early payments extend the existing paid period. Late payments start from the current date, so missed periods are not charged twice.
The default tax settings are:
50 moneyper period7 daysper period24 hourswarning period3 daysgrace period after the due date14 daysmaximum paid-ahead balance
The house menu displays the current tax status:
- π’ Green: Tax is paid and the due date is not approaching
- π Orange: Tax is due within the warning period
- π΄ Red: The due date has passed and the owner is within the grace period
- Eviction suspended: An external filter temporarily prevents eviction
- Eviction processed: The grace period has expired and the house has returned to the market
Tax status is enforced when the resource starts and when relevant house menus are opened. If the grace period expires, the owner is notified when online, occupants are removed, furniture and resale listings are cleared, and the house becomes available again. A new buyer or transferee receives a fresh paid period and never inherits the previous owner's tax debt.
For example, a server can temporarily suspend tax evictions for protected characters or during a server event:
exports.jo_housing:registerFilter('canEvictForUnpaidTax', function(canEvict, house, ownerIdentifier, ownerCharId)
if exports.your_staff_system:isTaxProtected(ownerIdentifier, ownerCharId) then
return false
end
return canEvict
end)
:::
::::
5. FAQ
:::details It's raining in my house ! Weather effects (rain, snow) can appear inside interiors due to your framework's weather synchronization system. To fix this, you need to disable weather sync when players enter houses and re-enable it when they leave.
Solution: Use the housing script's server actions to control your framework's weather sync:
-- Disable weather sync when entering a house
exports.jo_housing:registerAction('houseEntered', function(source, house, isVisiting)
-- Weather sync from kibook
TriggerClientEvent('weathersync:setSyncEnabled', source, false)
end)
-- Re-enable weather sync when leaving a house
exports.jo_housing:registerAction('houseLeft', function(source, house)
-- Weather sync from kibook
TriggerClientEvent('weathersync:setSyncEnabled', source, true)
end)
Reference: houseEntered action and houseLeft action :::
:::details Can I add custom interiors ?
Yes! You can add your own custom interiors using the addInteriors filter. This allows you to integrate custom MLO interiors or propsets into the housing system.
How to add custom interiors:
-- In your server-side resource or in jo_housing itself
exports.jo_housing:registerFilter('addInteriors', function(customInteriors)
-- Add your custom interiors
customInteriors.my_custom_cabin = {
entries = {
vec4(2.022125, -0.556265, 1.696404, 91.094) -- Main door spawn point (relative to interior origin)
},
propset = "my_custom_cabin", -- Interior propset/MLO name
category = "shack", -- Interior category (house, shack, manor, flat, rock_shack, worker)
numberRoom = 2, -- Number of rooms in the interior
insideDoors = { -- Optional: Interior working doors configuration
{
model = "p_door04x",
position = vec3(0.062589, -4.6552873, 0.738253)
}
}
}
customInteriors.luxury_penthouse = {
entries = {
vec4(0.0, 0.0, 2.0, 180.0) -- Main door spawn point
},
propset = "luxury_penthouse_mlo",
category = "manor",
numberRoom = 8,
-- insideDoors is optional - omit if no working interior doors needed
}
return customInteriors
end)
Configuration Tips:
- Set furniture limits for your custom interiors in
Config.interiorsMaxFurnitures - Use
/houseManagervisit mode to test and preview your interior placement - Interior categories affect available furniture limits and UI organization
Reference: addInteriors filter in the Developer section :::
:::details Can I add custom furnitures (props) ?
Yes! You can add custom furniture categories and props using the addFurnitures filter. This allows you to expand the available furniture options beyond the default categories.
How to add custom furniture:
-- In your server-side resource or in jo_housing itself
exports.jo_housing:registerFilter('addFurnitures', function(customFurnitures)
-- Add your custom furniture categories
customFurnitures.custom_electronics = {
"p_tv01x",
"p_radio01x",
"p_lamp_handheld01x",
"p_phonograph01x"
}
customFurnitures.outdoor_furniture = {
"p_bench05x",
"p_campfire01x",
"p_tent01x",
"p_waterbarrel01x"
}
customFurnitures.western_decor = {
"p_spittoon01x",
"p_horseshoe01x",
"p_banjo01x"
}
return customFurnitures
end)
Don't forget to configure pricing:
Add pricing for your custom categories in your overwriteConfig.lua:
-- Configure pricing for custom furniture categories
Config.furnituresCategoriesPrices.custom_electronics = {
money = 250,
gold = 3
}
Config.furnituresCategoriesPrices.outdoor_furniture = {
money = 75,
gold = 1
}
-- You can also set specific prices for individual props
Config.furnituresPrices.p_tv01x = {
money = 500,
gold = 5
}
Reference: addFurnitures filter and Furniture Configuration in the Developer section :::
:::details Can I disable the Build Mode ?
If you set the interiorβs max furniture to 0 (zero), players wonβt be able to add any furniture inside, effectively disabling build mode for that interior.
Example:
-- Available interior categories: shack, rock_shack, house, flat, manor, worker
-- Default furniture limit for interior categories
Config.interiorsCategoriesMaxFurnitures = {
default = 0, -- Disable build mode for all interiors
manor = 200 -- Except for the manor category
}
-- Specific furniture limits per interior ID
Config.interiorsMaxFurnitures = {
jo_pai_house = 0, -- Disable build mode only for jo_pai_house
}
:::
:::details The prompts are not working ! If prompts aren't appearing or responding, this is usually related to key binding or keyboard layout issues. Here are the most common solutions:
Primary Solution - Keyboard Layout: This script uses the raw keys module. If you have problems with prompts, set the keyboard layout properly.
Additional Troubleshooting Steps:
-
Check for Key Conflicts:
- Other resources might be using the same keys
- Review your
Config.keyssettings inoverwriteConfig.lua - Try changing conflicting keys to different bindings
-
Verify Distance Settings:
- Make sure you're close enough to interact with objects
- Check
Config.distanceShowHousePromptand related distance settings - Default house prompt distance is 2.0 meters
6. For Developers > Actions > <Badge type="server" text="Server" /> furnitureBought
Triggered when a player purchases furniture for their house.
-- @param source - serverID of the player
-- @param house - the house object where furniture was bought
-- @param furniture - the furniture object that was purchased
-- @param price - resolved price paid for the furniture
-- @param priceIndex - selected price option index
exports.jo_housing:registerAction('furnitureBought', function(source, house, furniture, price, priceIndex)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseBought
Triggered when a player successfully purchases a house.
-- @param source - serverID of the buyer
-- @param house - the house object that was purchased
-- @param price - resolved price paid for the house
-- @param priceIndex - selected price option index
exports.jo_housing:registerAction('houseBought', function(source, house, price, priceIndex)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseKeyBought
Triggered when a new house key is purchased.
-- @param source - serverID of the player buying the key
-- @param house - the house object
-- @param price - resolved price paid for the key
-- @param priceIndex - selected price option index
exports.jo_housing:registerAction('houseKeyBought', function(source, house, price, priceIndex)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseListedForResale
Triggered when an owned house is listed for resale.
-- @param source - serverID of the player listing the house
-- @param house - the house object being listed
-- @param groupOrReason - resale price group or the reason for the listing
exports.jo_housing:registerAction('houseListedForResale', function(source, house, groupOrReason)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseLockChanged
Triggered when a house lock is changed.
-- @param source - serverID of the house owner
-- @param house - the house object
-- @param price - resolved price paid for the lock change
-- @param priceIndex - selected price option index
-- @param success - boolean indicating if lock change was successful
exports.jo_housing:registerAction('houseLockChanged', function(source, house, price, priceIndex, success)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseOwnerRemoved
Triggered when an owner is removed from a house.
-- @param source - serverID of the player or script removing the owner
-- @param house - the house object
-- @param ownerRemoved - boolean indicating if the owner was successfully removed
exports.jo_housing:registerAction('houseOwnerRemoved', function(source, house, ownerRemoved)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseSold
Triggered when an owner sells or leaves a house.
-- @param source - serverID of the player selling the house
-- @param house - the house object that was sold
-- @param refundPrice - price refunded to the previous owner
exports.jo_housing:registerAction('houseSold', function(source, house, refundPrice)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseTaxEvicted
Triggered after an owner loses a house because its tax remained unpaid beyond the grace period.
-- @param house - the house object that was evicted
-- @param ownerIdentifier - identifier of the previous owner
-- @param ownerCharId - character ID of the previous owner
-- @param ownerSource - serverID of the previous owner, or false if offline
exports.jo_housing:registerAction('houseTaxEvicted', function(house, ownerIdentifier, ownerCharId, ownerSource)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseTaxPaid
Triggered after a house-tax payment has been processed.
-- @param source - serverID of the player paying the tax
-- @param house - the taxed house
-- @param price - resolved total price for the selected number of periods
-- @param priceIndex - selected price option index
-- @param numPeriods - number of tax periods selected
-- @param success - boolean indicating if the payment was recorded successfully
exports.jo_housing:registerAction('houseTaxPaid', function(source, house, price, priceIndex, numPeriods, success)
-- Your code here
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseWardrobeOpened
Triggered when a player opens house wardrobe.
-- @param source - serverID of the player
-- @param house - the house object
exports.jo_housing:registerAction('houseWardrobeOpened', function(source, house)
-- Your code here
end)
#### <Badge type="server" text="Server" /> knockedOnHouse
Triggered when someone knocks on a house door.
```lua
-- @param source - serverID of the player knocking
-- @param house - the house object being knocked on
-- @param foundSources - array of player sources who were notified (propset: eligible players inside the house, MLO/Zone: notified targets excluding the knocker)
exports.jo_housing:registerAction('knockedOnHouse', function(source, house, foundSources)
-- Your code here
end)
Rental & Keys Actions
<Badge type="server" text="Server" /> playerAddedToHouse
Triggered when a player is added to a house's access list.
-- @param source - serverID of the house owner
-- @param house - the house object
-- @param playerSrc - serverID of the player being added
-- @param playerName - name of the player being added
exports.jo_housing:registerAction('playerAddedToHouse', function(source, house, playerSrc, playerName)
-- Your code here
end)
<Badge type="server" text="Server" /> playerPermissionsChanged
Triggered when the permissions for a player on the access list are changed.
-- @param source - serverID of the house owner
-- @param house - the house object
-- @param accessibilityId - ID of the access entry being changed
-- @param permissions - table containing the new permissions
exports.jo_housing:registerAction('playerPermissionsChanged', function(source, house, accessibilityId, permissions)
-- Your code here
end)
<Badge type="server" text="Server" /> playerRemovedFromHouse
Triggered when a player is removed from a house's access list.
-- @param source - serverID of the house owner
-- @param house - the house object
-- @param accessibilityId - ID of the access entry that was removed
-- @param success - boolean indicating if removal was successful
exports.jo_housing:registerAction('playerRemovedFromHouse', function(source, house, accessibilityId, success)
-- Your code here
end)
<Badge type="server" text="Server" /> storageLocationSet
Triggered when a storage location is set in a house.
-- @param source - serverID of the player
-- @param house - the house object
-- @param coords - coordinates of the storage location
exports.jo_housing:registerAction('storageLocationSet', function(source, house, coords)
-- Your code here
end)
Access Management Actions
<Badge type="server" text="Server" /> rentPaid
Triggered when rent is paid for a house.
-- @param source - serverID of the player paying rent
-- @param house - the house object
-- @param numPeriods - number of periods paid for
-- @param isDaily - boolean indicating if it's daily or weekly rent
-- @param totalPrice - total amount paid
-- @param priceIndex - selected price option index
-- @param success - boolean indicating if payment was successful
exports.jo_housing:registerAction('rentPaid', function(source, house, numPeriods, isDaily, totalPrice, priceIndex, success)
-- Your code here
end)
<Badge type="client" text="Client" /> interiorsInitialized
Triggered after the shared interior list has been initialized and custom interiors have been added.
jo.hook.registerAction('interiorsInitialized', function()
-- Your code here
end)
Filters
Filters allow you to modify data or control permissions during script execution. Introduced in v1.2.0, filters provide a synchronous way to intercept and modify script behavior at specific points, unlike events which are asynchronous.
Below is a complete list of all available filters in the jo_housing script.
<Badge type="server" text="Server" /> addFurnitures
Allows you to add custom furniture categories and items to the housing system.
-- @param customFurnitures - empty table by default
-- @return table - table with custom furniture categories
exports.jo_housing:registerFilter('addFurnitures', function(customFurnitures)
-- Add your custom furniture categories
customFurnitures.custom_electronics = {
"p_tv01x",
"p_radio01x",
"p_lamp_handheld01x"
}
customFurnitures.outdoor_furniture = {
"p_bench05x",
"p_campfire01x",
"p_tent01x"
}
return customFurnitures
end)
:::tip π‘ Custom Furniture Pricing
Don't forget to configure pricing for your custom categories in Config.furnituresCategoriesPrices or specific items in Config.furnituresPrices.
-- In your overwriteConfig.lua
Config.furnituresCategoriesPrices.custom_electronics = {
money = 250,
gold = 3
}
Config.furnituresCategoriesPrices.outdoor_furniture = {
money = 75,
gold = 1
}
:::
<Badge type="server" text="Server" /> addInteriors
Allows you to add custom interior configurations to the housing system.
6. For Developers > Actions > <Badge type="server" text="Server" /> houseWardrobeOpened
-- @param customInteriors - empty table by default
-- @return table - table with custom interior configurations
exports.jo_housing:registerFilter('addInteriors', function(customInteriors)
-- Add your custom interiors
customInteriors.my_custom_cabin = {
entries = {
vec4(2.022125, -0.556265, 1.696404, 91.094) -- Main door spawn point (relative to interior origin)
},
propset = "my_custom_cabin", -- Interior propset/MLO name
category = "shack", -- Interior category (house, shack, manor, flat, rock_shack, worker)
numberRoom = 2, -- Number of rooms in the interior
insideDoors = { -- Optional: Interior working doors configuration
{
model = "p_door04x",
position = vec3(0.062589, -4.6552873, 0.738253)
},
{
model = "p_door04x",
position = vec3(-1.473662, -4.661302, 0.738253)
},
}
}
customInteriors.luxury_penthouse = {
entries = {
vec4(0.0, 0.0, 2.0, 180.0) -- Main door spawn point (relative to interior origin)
},
propset = "luxury_penthouse_mlo",
category = "manor",
numberRoom = 8,
-- insideDoors is optional - omit if no working interior doors needed
}
return customInteriors
end)
Interior Properties:
| Property | Type | Required | Description |
|---|---|---|---|
entries |
table |
β | Array containing the main door spawn point (vec4 with heading). Only the first entry is used, coordinates are relative to interior origin |
propset |
string |
β | Interior propset/MLO resource name |
category |
string |
β | Interior category: house, shack, manor, flat, rock_shack, worker |
numberRoom |
number |
β | Number of rooms in the interior |
insideDoors |
table |
β | Optional array of interior doors with model and position properties |
:::tip π‘ Interior Configuration
- Configure furniture limits for your custom interiors using
Config.interiorsMaxFurnituresor category limits withConfig.interiorsCategoriesMaxFurnitures - Test your interior coordinates thoroughly - use
/houseManagervisit mode to preview placement - Interior categories affect available furniture limits and UI organization
-- In your overwriteConfig.lua
Config.interiorsMaxFurnitures.my_custom_cabin = 150
Config.interiorsCategoriesMaxFurnitures.luxury = 300 -- If you add a custom category
:::
<Badge type="server" text="Server" /> canAddPlayerToHouse
Controls who can add players to a house's access list.
-- @param canAdd - boolean indicating if the action is allowed by default
-- @param source - serverID of the player adding someone
-- @param houseId - ID of the house
-- @param playerSrc - serverID of the player being added
-- @param playerName - name of the player being added
exports.jo_housing:registerFilter('canAddPlayerToHouse', function(canAdd, source, houseId, playerSrc, playerName)
return canAdd
end)
<Badge type="server" text="Server" /> canBuyFurniture
Controls who can buy furniture.
-- @param canBuy - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param furniture - furniture model/object data
-- @param houseId - ID of the house
-- @param price - resolved price for the furniture
-- @param priceIndex - selected price option index
-- @param categoryKey - category key of the furniture
exports.jo_housing:registerFilter('canBuyFurniture', function(canBuy, source, furniture, houseId, price, priceIndex, categoryKey)
return canBuy
end)
<Badge type="server" text="Server" /> canBuyHouse
Controls who can buy a house.
-- @param canBuy - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house being purchased
-- @param price - resolved price for the house
-- @param priceIndex - selected price option index
-- @param period - for rentals, number of periods the player is paying for
exports.jo_housing:registerFilter('canBuyHouse', function(canBuy, source, houseId, price, priceIndex, period)
return canBuy
end)
<Badge type="server" text="Server" /> canDeleteFurniture
Controls who can delete furniture from a house.
-- @param canDelete - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param furnitureId - ID of the furniture
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canDeleteFurniture', function(canDelete, source, furnitureId, houseId)
return canDelete
end)
<Badge type="server" text="Server" /> canDeleteHouse
Controls who can delete houses.
-- @param canDelete - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseData - table containing house data
exports.jo_housing:registerFilter('canDeleteHouse', function(canDelete, source, houseData)
return canDelete
end)
6. For Developers > Actions > <Badge type="server" text="Server" /> houseWardrobeOpened
<Badge type="server" text="Server" /> canEnterBuildMode
Controls who can enter build mode in a house.
-- @param canEnter - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canEnterBuildMode', function(canEnter, source, houseId)
return canEnter
end)
<Badge type="server" text="Server" /> canEnterHouse
Controls who can enter a house.
Door toggling for owned MLO and Zone houses is handled separately by canToggleHouseDoor.
-- @param canEnter - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house being entered
exports.jo_housing:registerFilter('canEnterHouse', function(canEnter, source, houseId)
return canEnter
end)
<Badge type="server" text="Server" /> canEvictForUnpaidTax
Controls whether an owner can be evicted when a house tax remains unpaid beyond the grace period. Return false to suspend the eviction; the owner keeps the house and the client receives an eviction-suspended status.
-- @param canEvict - boolean indicating if the eviction is allowed by default
-- @param house - the house object that is overdue
-- @param ownerIdentifier - identifier of the owner
-- @param ownerCharId - character ID of the owner
exports.jo_housing:registerFilter('canEvictForUnpaidTax', function(canEvict, house, ownerIdentifier, ownerCharId)
return canEvict
end)
<Badge type="server" text="Server" /> canGetPlayersAccessibilityList
Controls who can retrieve the list of players with access to a house.
-- @param canGet - boolean indicating if the action is allowed by default
-- @param source - serverID of the player requesting the list
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canGetPlayersAccessibilityList', function(canGet, source, houseId)
return canGet
end)
<Badge type="server" text="Server" /> canListHouseForResale
Controls who can list a house for resale.
-- @param canList - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canListHouseForResale', function(canList, source, houseId)
return canList
end)
<Badge type="server" text="Server" /> canMoveFurniture
Controls who can move furniture in a house.
-- @param canMove - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param furnitureId - ID of the furniture
-- @param houseId - ID of the house
-- @param relPos - new relative position for the furniture
-- @param relRot - new relative rotation for the furniture
exports.jo_housing:registerFilter('canMoveFurniture', function(canMove, source, furnitureId, houseId, relPos, relRot)
return canMove
end)
<Badge type="server" text="Server" /> canOpenHouseLocationMenu
Controls who can open the house location menu.
-- @param canOpen - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houses - array of nearby houses
exports.jo_housing:registerFilter('canOpenHouseLocationMenu', function(canOpen, source, houses)
return canOpen
end)
<Badge type="server" text="Server" /> canOpenHouseStorage
Controls who can open a house's storage.
-- @param canOpenStorage - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canOpenHouseStorage', function(canOpenStorage, source, houseId)
return canOpenStorage
end)
<Badge type="server" text="Server" /> canOpenHouseWardrobe
Controls who can open a house's wardrobe.
-- @param canOpen - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canOpenHouseWardrobe', function(canOpen, source, houseId)
return canOpen
end)
<Badge type="server" text="Server" /> canPayHouseTax
Controls whether an owner can pay the tax of a house after the payment has been validated and the price has been resolved.
-- @param canPay - boolean indicating if the payment is allowed by default
-- @param source - serverID of the player paying the tax
-- @param houseId - ID of the house
-- @param price - resolved total price for the selected number of periods
-- @param priceIndex - selected price option index
-- @param numPeriods - number of tax periods selected
exports.jo_housing:registerFilter('canPayHouseTax', function(canPay, source, houseId, price, priceIndex, numPeriods)
return canPay
end)
<Badge type="server" text="Server" /> canPlaceFurniture
Controls who can place furniture in a house.
-- @param canPlace - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param furniture - furniture model/object data
-- @param houseId - ID of the house
-- @param relPos - relative position where furniture will be placed
-- @param relRot - relative rotation of the furniture
-- @param price - resolved price for the furniture
-- @param priceIndex - selected price option index
-- @param categoryKey - category key of the furniture
exports.jo_housing:registerFilter('canPlaceFurniture', function(canPlace, source, furniture, houseId, relPos, relRot, price, priceIndex, categoryKey)
return canPlace
end)
<Badge type="server" text="Server" /> canRemoveHouseOwner
Controls who can remove the owner from a house.
6. For Developers > Actions > <Badge type="server" text="Server" /> houseWardrobeOpened
-- @param canRemove - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canRemoveHouseOwner', function(canRemove, source, houseId)
return canRemove
end)
<Badge type="server" text="Server" /> canRemovePlayerFromHouse
Controls who can remove players from a house's access list.
-- @param canRemove - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
-- @param accessibilityId - ID of the access entry to remove
exports.jo_housing:registerFilter('canRemovePlayerFromHouse', function(canRemove, source, houseId, accessibilityId)
return canRemove
end)
<Badge type="client" text="Client" /> canSeeBlipForHouse
Controls if a blip should be created for a specific house on the client.
This filter is evaluated locally for each house after the global canSeeHousesBlips filter has allowed blips.
-- @param canSee - boolean indicating if the blip is visible by default
-- @param house - house object
jo.hook.registerFilter('canSeeBlipForHouse', function(canSee, house)
if not canSee then return false end
-- Example: only show blips for houses owned by the current player
return house:isOwner()
end)
<Badge type="server" text="Server" /> canSeeHousesBlips
Controls if the player can see housing blips at all. This filter is called once when the player's housing data is initialized, before houses are sent to the client.
-- @param canSee - boolean indicating if housing blips are visible by default
-- @param source - serverID of the player
exports.jo_housing:registerFilter('canSeeHousesBlips', function(canSee, source)
return canSee
end)
<Badge type="server" text="Server" /> canSellHouse
Controls who can sell a house.
-- @param canSell - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canSellHouse', function(canSell, source, houseId)
return canSell
end)
<Badge type="server" text="Server" /> canSetDressingLocation
Controls who can set a dressing room location inside a house.
-- @param canSet - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
-- @param coords - coordinates for the dressing location
exports.jo_housing:registerFilter('canSetDressingLocation', function(canSet, source, houseId, coords)
return canSet
end)
<Badge type="server" text="Server" /> canSetStorageLocation
Controls who can set a storage location inside a house.
-- @param canSet - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
-- @param coords - coordinates for the storage location
exports.jo_housing:registerFilter('canSetStorageLocation', function(canSet, source, houseId, coords)
return canSet
end)
<Badge type="server" text="Server" /> canToggleHouseDoor
Controls who can open or close an owned MLO or Zone house door.
This filter is evaluated by the dedicated server door-toggle callback, separately from canEnterHouse.
-- @param canToggle - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canToggleHouseDoor', function(canToggle, source, houseId)
return canToggle
end)
<Badge type="server" text="Server" /> canTransferHouse
Controls who can transfer house ownership.
-- @param canTransfer - boolean indicating if the action is allowed by default
-- @param source - serverID of the current owner
-- @param toPlayerSrc - serverID of the player receiving the house
-- @param houseId - ID of the house being transferred
exports.jo_housing:registerFilter('canTransferHouse', function(canTransfer, source, toPlayerSrc, houseId)
return canTransfer
end)
<Badge type="server" text="Server" /> canUpdateAccessibility
Controls who can update a house's accessibility settings.
-- @param canUpdate - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param accessibilityType - type of access ("everyone", "list", or "onlyMe")
-- @param houseId - ID of the house
exports.jo_housing:registerFilter('canUpdateAccessibility', function(canUpdate, source, accessibilityType, houseId)
return canUpdate
end)
<Badge type="server" text="Server" /> canUpdatePlayerPermissions
Controls who can update permissions for a player on a house's access list.
-- @param canUpdate - boolean indicating if the action is allowed by default
-- @param source - serverID of the player making the changes
-- @param houseId - ID of the house
-- @param accessibilityId - ID of the access entry being changed
-- @param permissions - table of the new permissions
exports.jo_housing:registerFilter('canUpdatePlayerPermissions', function(canUpdate, source, houseId, accessibilityId, permissions)
return canUpdate
end)
<Badge type="server" text="Server" /> canUpsertHouse
Controls who can create or update houses.
-- @param canUpsert - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
-- @param houseId - ID of the house (nil for creation)
-- @param changesetOrHouseData - changes to apply or full house data for creation
exports.jo_housing:registerFilter('canUpsertHouse', function(canUpsert, source, houseId, changesetOrHouseData)
return canUpsert
end)
<Badge type="server" text="Server" /> canUseHouseManagerCommand
Controls who can use the /houseManager command to create and manage houses.
6. For Developers > Actions > <Badge type="server" text="Server" /> houseWardrobeOpened
-- @param canUse - boolean indicating if the action is allowed by default
-- @param source - serverID of the player
exports.jo_housing:registerFilter('canUseHouseManagerCommand', function(canUse, source)
-- Example: Only allow admins
local isAdmin = exports.your_permission_system:isAdmin(source)
return isAdmin
end)
<Badge type="server" text="Server" /> houseTaxPrice
Allows you to adjust the total price charged for a house-tax payment, for example to apply discounts or tax-free events. The returned value is validated again before the payment is taken.
-- @param price - resolved total price for the selected number of periods
-- @param source - serverID of the player paying the tax
-- @param house - the taxed house
-- @param numPeriods - number of tax periods selected
-- @param priceIndex - selected price option index
exports.jo_housing:registerFilter('houseTaxPrice', function(price, source, house, numPeriods, priceIndex)
return price
end)
<Badge type="server" text="Server" /> resalePaymentAmount
Allows you to modify the amount paid to the previous owner when a resale listing is bought.
-- @param amount - default resale payment amount
-- @param previousOwnerSource - serverID of the previous owner, or false if offline
-- @param previousOwnerIdentifier - identifier of the previous owner
-- @param previousOwnerCharId - character ID of the previous owner
-- @param buyerSource - serverID of the buyer
-- @param house - house object
-- @param priceIndex - selected price option index
exports.jo_housing:registerFilter('resalePaymentAmount', function(amount, previousOwnerSource, previousOwnerIdentifier, previousOwnerCharId, buyerSource, house, priceIndex)
return amount
end)
:::details Example of job lock for VORP
AllowedJobs = {
houser = true,
houseManager = true,
}
exports.jo_housing:registerFilter('canUseHouseManagerCommand', function(canUse, source)
local job = jo.framework:getJob(source)
if AllowedJobs[job] then
return canUse
else
jo.notif.rightError("You don't have the right job to use the house manager")
return false
end
end)
:::