Developer

3 min readUpdated 2 weeks ago

Overview

Other scripts integrate through a client export, a server event and the handlers in the open/ folder, which is not escrowed.

Client Exports

openStation

lua
1exports.ml_smelter_stations:openStation(fixedStationId)
  • fixedStationId (string). The id of a fixed station from Config.FixedStations

Opens the station UI for a fixed station without the player using its prop or target zone. The player must be within 10 m of the station. Triggers a server-side lock request and opens the UI on success.

your_script/client.lua
1exports.ml_smelter_stations:openStation('main_forge_sandy')

Server Handlers

BeforeGiveItem is in open/server.lua:

open/server.lua
1function OpenServer.BeforeGiveItem(src, item, amount)
2    return true
3end

Called before a crafted item is given to the player. Return false to block it.

The other handlers are built in. open/server.lua loads after them, so a function you define there with the same name replaces the built-in one:

  • OpenServer.OnActionComplete(src, actionType, data): runs after a station action. actionType is 'start_cooking', 'take_item', 'add_fuel', 'repair' or 'extinguish'. The built-in version awards XP from Config.XP.Rewards, so a replacement that does nothing turns XP off
  • OpenServer.CanCraftTier(src, tier): true when XP is off or the player's level reaches the tier
  • OpenServer.GetPlayerProgress(src): XP progress for the UI: level, totalXp, xpCurrent, xpNeeded, progress, craftsCompleted, tiers and bonuses
  • OpenServer.GetBonuses(src): tier bonuses, for example { speed = 0.12, antiCarbonize = 0.20 }
  • OpenServer.AwardXp(src, actionType, recipeId): gives XP for an action, from Config.XP.Rewards and Config.XP.RecipeXpOverride

To extend one, keep a reference to the original and call it from your version, as in the Examples below.

Shared Handlers

Located in open/shared.lua.

ValidateAction

open/shared.lua
1function OpenHandlers.ValidateAction(src, actionType)
2    return true
3end

Called before destroy, repair, extinguish, add_fuel, start_cooking, take_item and take_all_items actions. Return false to block the action. Useful for permission checks or conditional access.

Client Handlers

Located in open/client.lua.

BeforeOpenUI

open/client.lua
1function OpenClient.BeforeOpenUI(data)
2    return true
3end

Called before the station UI opens. Return false to block the UI. By default, fetches and sends XP progression data to the UI.

Server Events

ml_smelter_stations:playerCraftingStarted

Fires on the server when a player successfully starts cooking at any station. Listen with AddEventHandler.

lua
1AddEventHandler('ml_smelter_stations:playerCraftingStarted', function(identifier, stationType, recipeName, quantity)
2end)

Server Callbacks

These callbacks are registered via Bridge.OnServerRequest and used internally by the client.

  • stations:getPlayerProgress: Returns full XP progress data for the requesting player
  • stations:getRecipeTiers: Returns all recipe tier requirements and lock states for the requesting player

Custom XP Provider

To use a custom XP backend, set Config.XP.Provider = 'custom' and define functions in open/server.lua:

open/server.lua
1Config.XP.CustomGetLevel = function(src)
2    return 1
3end
4
5Config.XP.CustomGetXp = function(src)
6    return 0
7end
8
9Config.XP.CustomAddXp = function(src, amount)
10    return true
11end
12
13Config.XP.CustomGetProgress = function(src)
14    return {
15        level = 1,
16        maxLevel = 50,
17        totalXp = 0,
18        xpCurrent = 0,
19        xpNeeded = 100,
20        progress = 0,
21        craftsCompleted = 0,
22        tiers = Config.XP.Tiers,
23    }
24end

Examples

open/shared.lua
1function OpenHandlers.ValidateAction(src, actionType)
2    if actionType == 'start_cooking' then
3        local job = Bridge.GetJob(src)
4        if job and job.name == 'police' then
5            Bridge.NotifyPlayer(src, 'error', 'Police cannot use crafting stations on duty.')
6            return false
7        end
8    end
9    return true
10end
open/server.lua
1local originalOnAction = OpenServer.OnActionComplete
2function OpenServer.OnActionComplete(src, actionType, data)
3    originalOnAction(src, actionType, data)
4
5    if actionType == 'take_item' then
6        PerformHttpRequest('https://api.example.com/crafting', function() end, 'POST', json.encode({
7            player = Bridge.GetPlayerId(src),
8            action = actionType,
9            timestamp = os.time(),
10        }))
11    end
12end
lua
1Bridge.AddEntityTarget(npcEntity, { {
2    name = 'open_forge',
3    label = 'Use Forge',
4    icon = 'fas fa-fire',
5    distance = 2.0,
6    onSelect = function()
7        exports.ml_smelter_stations:openStation('main_forge_sandy')
8    end
9} })