Developer

4 min readUpdated 2 weeks ago

Overview

Integration with ML Smelter Stations is done through client exports, the open/ folder handlers, and server-side OpenServer functions. The open/ folder is not escrowed and can be freely modified to hook into any external system.

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 requiring the player to interact with a prop or target zone. Triggers a server-side lock request and opens the UI on success.

lua
1-- Open the main forge from a command or external trigger
2exports.ml_smelter_stations:openStation('main_forge_sandy')

Server Handlers

Located in open/server.lua. All OpenServer functions can be modified to customize behavior.

BeforeGiveItem

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

Called before giving a crafted item to the player. Return false to block the item from being given.

OnActionComplete

open/server.lua
1function OpenServer.OnActionComplete(src, actionType, data)
2    -- actionType: 'start_cooking', 'take_item', 'add_fuel', 'repair'
3end

Called after any station action completes. By default, this awards XP based on Config.XP.Rewards. Override to add custom logic (missions, achievements, analytics).

CanCraftTier

open/server.lua
1function OpenServer.CanCraftTier(src, tier)
2    return true -- or false to block
3end

Checks if a player meets the level requirement for a recipe tier. Returns true if XP is disabled or the player's level meets the tier threshold.

GetPlayerProgress

open/server.lua
1function OpenServer.GetPlayerProgress(src)
2    return progressData -- or nil
3end

Returns the player's full XP progress data for the UI. Includes level, totalXp, xpCurrent, xpNeeded, progress fraction, craftsCompleted, tiers, and bonuses.

GetBonuses

open/server.lua
1function OpenServer.GetBonuses(src)
2    return { speed = 0.12, antiCarbonize = 0.20 }
3end

Returns the player's current tier bonuses (cook time reduction, carbonize time extension). Based on the highest tier the player qualifies for.

AwardXp

open/server.lua
1function OpenServer.AwardXp(src, actionType, recipeId)
2end

Awards XP to the player for a specific action. Uses Config.XP.Rewards for base values, with optional Config.XP.RecipeXpOverride for per-recipe overrides.

Shared Handlers

Located in open/shared.lua.

OnPlayerAction

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

Generic hook for any player action. Return false to block.

ValidateAction

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

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

Client Handlers

Located in open/client.lua.

Notify

open/client.lua
1function OpenClient.Notify(message, type)
2    Bridge.Notify(message, type)
3end

Override to use a custom notification system.

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)
2    -- identifier: player's framework identifier (from Bridge.GetPlayerId)
3    -- stationType: key from Config.Stations (e.g., 'forge', 'campfire')
4    -- recipeName: key from Config.Recipes
5    -- quantity: number of items queued
6end)

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 -- return player level
3end
4
5Config.XP.CustomGetXp = function(src)
6    return 0 -- return total XP
7end
8
9Config.XP.CustomAddXp = function(src, amount)
10    return true -- return success
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
1-- In another resource, e.g., an NPC script
2Bridge.AddEntityTarget(npcEntity, { {
3    name = 'open_forge',
4    label = 'Use Forge',
5    icon = 'fas fa-fire',
6    distance = 2.0,
7    onSelect = function()
8        exports.ml_smelter_stations:openStation('main_forge_sandy')
9    end
10} })