# Developer > Developer API reference for ML Smelter Stations Category: SMELTER STATIONS · Source: https://miciomods.it/docs/ml-smelter-stations-developer · Last updated: 2026-07-09 ## 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 exports.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. **Example: Open a station from another script** ```lua -- Open the main forge from a command or external trigger exports.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** ```lua function OpenServer.BeforeGiveItem(src, item, amount) return true end ``` Called before giving a crafted item to the player. Return `false` to block the item from being given. ### OnActionComplete **open/server.lua** ```lua function OpenServer.OnActionComplete(src, actionType, data) -- actionType: 'start_cooking', 'take_item', 'add_fuel', 'repair' end ``` 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** ```lua function OpenServer.CanCraftTier(src, tier) return true -- or false to block end ``` 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** ```lua function OpenServer.GetPlayerProgress(src) return progressData -- or nil end ``` 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** ```lua function OpenServer.GetBonuses(src) return { speed = 0.12, antiCarbonize = 0.20 } end ``` 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** ```lua function OpenServer.AwardXp(src, actionType, recipeId) end ``` 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** ```lua function OpenHandlers.OnPlayerAction(src, data) return true end ``` Generic hook for any player action. Return `false` to block. ### ValidateAction **open/shared.lua** ```lua function OpenHandlers.ValidateAction(src, actionType) return true end ``` 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** ```lua function OpenClient.Notify(message, type) Bridge.Notify(message, type) end ``` Override to use a custom notification system. ### BeforeOpenUI **open/client.lua** ```lua function OpenClient.BeforeOpenUI(data) return true end ``` 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 AddEventHandler('ml_smelter_stations:playerCraftingStarted', function(identifier, stationType, recipeName, quantity) -- identifier: player's framework identifier (from Bridge.GetPlayerId) -- stationType: key from Config.Stations (e.g., 'forge', 'campfire') -- recipeName: key from Config.Recipes -- quantity: number of items queued end) ``` ## 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** ```lua Config.XP.CustomGetLevel = function(src) return 1 -- return player level end Config.XP.CustomGetXp = function(src) return 0 -- return total XP end Config.XP.CustomAddXp = function(src, amount) return true -- return success end Config.XP.CustomGetProgress = function(src) return { level = 1, maxLevel = 50, totalXp = 0, xpCurrent = 0, xpNeeded = 100, progress = 0, craftsCompleted = 0, tiers = Config.XP.Tiers, } end ``` ## Examples **Block crafting for specific jobs** **open/shared.lua** ```lua function OpenHandlers.ValidateAction(src, actionType) if actionType == 'start_cooking' then local job = Bridge.GetJob(src) if job and job.name == 'police' then Bridge.NotifyPlayer(src, 'error', 'Police cannot use crafting stations on duty.') return false end end return true end ``` **Log crafting to an external API** **open/server.lua** ```lua local originalOnAction = OpenServer.OnActionComplete function OpenServer.OnActionComplete(src, actionType, data) originalOnAction(src, actionType, data) if actionType == 'take_item' then PerformHttpRequest('https://api.example.com/crafting', function() end, 'POST', json.encode({ player = Bridge.GetPlayerId(src), action = actionType, timestamp = os.time(), })) end end ``` **Open a fixed station via NPC interaction** ```lua -- In another resource, e.g., an NPC script Bridge.AddEntityTarget(npcEntity, { { name = 'open_forge', label = 'Use Forge', icon = 'fas fa-fire', distance = 2.0, onSelect = function() exports.ml_smelter_stations:openStation('main_forge_sandy') end } }) ```