# Developer > Developer API reference for ML Water Stations Category: LIQUID STATIONS · Source: https://miciomods.it/docs/ml-water-stations-developer · Last updated: 2026-07-09 ## Overview Integration uses the `open/` folder handlers. Server handlers in `open/server.lua` control access, item flow, and action lifecycle. Client handlers in `open/client.lua` control UI and placement. Shared handlers in `open/shared.lua` run on both sides for global action gating and cooldowns. ## Server Handlers Located in `open/server.lua`. ### Item Control **open/server.lua** ```lua function OpenServer.BeforeGiveItem(src, item, amount) return true -- return false to block end function OpenServer.BeforeRemoveItem(src, item, amount) return true -- return false to block end ``` - `BeforeGiveItem`: Called before giving a filled/empty container to the player. Return `false` to block. - `BeforeRemoveItem`: Called before removing an item from the player. Return `false` to block. ### Action Lifecycle **open/server.lua** ```lua function OpenServer.OnActionComplete(src, actionType, data) end function OpenServer.OnTankPlaced(src, tankData) end ``` - `OnActionComplete`: Fires after any tank action completes. `actionType` is one of: `'fillTank'`, `'takeWater'`, `'repairTank'`, `'dismantleTank'`. - `OnTankPlaced`: Fires after a tank is saved to the database. ### Access Control **open/server.lua** ```lua function OpenServer.CanAccessTank(src, tankData) return true -- return false to block end function OpenServer.CanPlaceTank(src, tankType, coords) return true -- return false to block end function OpenServer.CanDismantleTank(src, tankData) return true -- return false to block end ``` - `CanAccessTank`: Gate access to a tank. Use for owner-only, gang territory, or job-lock checks. - `CanPlaceTank`: Gate placement. Use for zone restrictions or coordinate blacklists. - `CanDismantleTank`: Gate dismantling. Use for protected zones or admin overrides. ### Jerry Can **open/server.lua** ```lua function OpenServer.OnJerryCanTransfer(src, tankId, canItem, amount, direction) return true -- return false to block end ``` - `OnJerryCanTransfer`: Called before a jerry can fill or drain. `direction` is `'fill'` or `'drain'`. Return `false` to block. ## Client Handlers Located in `open/client.lua`. ### Interaction **open/client.lua** ```lua function OpenClient.BeforeOpenUI(data) return true -- return false to cancel end function OpenClient.CanInteract(tankData) return true -- return false to hide target end ``` - `BeforeOpenUI`: Called before the tank context menu opens. Return `false` to cancel. - `CanInteract`: Pre-check for target visibility. Block if the player is cuffed, dead, in a vehicle, etc. ### Placement **open/client.lua** ```lua function OpenClient.OnPlacementStart(tankType) return true -- return false to block end function OpenClient.OnPlacementConfirm(tankType, coords, heading) return true -- return false to reject end ``` - `OnPlacementStart`: Called when entering placement mode. Return `false` to block. - `OnPlacementConfirm`: Called before confirming position. Return `false` to reject coordinates. ## Shared Handlers Located in `open/shared.lua`. These run on both server and client. **open/shared.lua** ```lua function OpenHandlers.OnPlayerAction(src, data) return true -- return false to block end function OpenHandlers.ValidateAction(src, actionType) return true -- return false to block end function OpenHandlers.GetCooldown(actionType) return 0 -- seconds, 0 or nil to disable end function OpenHandlers.CanUseTankType(src, tankType) return true -- return false to block end ``` - `OnPlayerAction`: Global hook before any action is dispatched. Return `false` to block entirely. - `ValidateAction`: Pre-flight validation before the tank UI opens. Return `false` to block. - `GetCooldown`: Returns cooldown in seconds for an action type. Action types: `'fillTank'`, `'takeWater'`, `'repairTank'`, `'fillJerryCan'`, `'drainJerryCan'`. - `CanUseTankType`: Controls access to specific tank types. Use for tier/rank/job-based restrictions. ## Item Metadata Tank and jerry can items store dynamic data via inventory metadata: ### Tank items Key. Type. Description `lifetank`: float. Remaining durability when dismantled ### Jerry can items Key. Type. Description `fuelType`: string. Liquid type stored in the can `fuelAmount`: float. Current liquid amount stored on the can `maxCapacity`: float. Maximum capacity of the can ## Examples **Job-lock tank access** **open/server.lua** ```lua function OpenServer.CanAccessTank(src, tankData) local job = Bridge.GetJob(src) if tankData.type == 'fuel' and (not job or job.name ~= 'mechanic') then return false end return true end ``` **Cooldown per action type** **open/shared.lua** ```lua function OpenHandlers.GetCooldown(actionType) if actionType == 'fillTank' then return 30 end if actionType == 'takeWater' then return 10 end return 0 end ``` **VIP-only large tanks** **open/shared.lua** ```lua function OpenHandlers.CanUseTankType(src, tankType) if tankType == 'large_tank' then local job = Bridge.GetJob(src) return job and job.name == 'vip' end return true end ``` **Block placement in interiors** **open/client.lua** ```lua function OpenClient.OnPlacementStart(tankType) if GetInteriorFromEntity(cache.ped) ~= 0 then Bridge.Notify('Cannot place tanks indoors', 'error') return false end return true end ```