# Drone logistics (automation.logistics) ## What it is for Drones that carry items so the player stops being the conveyor. A hub owns a few drones and serves the ports around it: containers that offer what they hold or ask to keep some in stock, and machines, whose outputs are offered and whose inputs are asked for. Every `tickSeconds` each hub sends its idle drones where something is missing, nearest source first, by priority. Nothing is ever lost or invented on the way. A farm, a factory, a colony, a warehouse: the same bricks. It needs `storage.containers` or `machines.production` to have something to carry. ## Turn it on ```text gripforge_gamekit_install { project_id: "gkp_…", id: "automation.logistics" } gripforge_gamekit_configure { project_id: "gkp_…", id: "automation.logistics", config: { "altitude": 6, "tickSeconds": 0.25 } } ``` ## First example A mine and a smelter are placed with `machines.production`, a hub with two drones sits between them, and the drones carry the ore the mine makes to the smelter that needs it; stats show the delivered units and the trips, nothing is lost, and pausing lets the drones end their trip. ```text machines.production.place("mine", [8,0,0]) machines.production.place("smelter", [-8,0,0]) automation.logistics.placeHub([0,0,0], { "drones": 2, "speed": 10, "capacity": 2 }) ... 240 ticks ... stats() -> { "delivered": { "ore": >= 4 }, "trips": >= 2 } events: logistics.assigned pause() -> true ... 300 ticks ... event: logistics.idle tasks() -> [] ``` ## Settings and defaults | Setting | Default | Meaning | |---|---|---| | `machines` | `true` | Machines of `machines.production` are ports on their own: outputs offered, inputs asked for up to the room of the store | | `altitude` | 4 | Height the drones fly at, above their hub (meters) | | `tickSeconds` | 0.5 | How often the hubs hand out work (seconds) | All three are moddable. ## Components An entity with `logistics_hub { drones, range, speed, capacity, label }` is a hub (defaults: 2 drones, range 60 m, speed 8 m/s, 10 units per trip). A container with `logistics_port { supply, demand, priority }` is a port: `supply` is `true` (it offers everything it holds) or a list of item names; `demand` is `{ "": number }`, the stock it wants to keep; a higher `priority` is served first. A machine of `machines.production` is a port on its own when `machines` is on. The placed models are the assets `logistics_hub` and `logistics_drone`. ## Services - `hubs()` and `drones()` list the hubs and the drones (`{ entity, hub, state, cargo }`); `tasks()` lists the trips under way. - `port(entity)` reads the port of an entity and `setPort(entity, port | null)` sets or clears it. - `placeHub(at, opts?)` stands a hub (with the options of `logistics_hub`) and its drones, and returns its entity. - `stats()` answers `{ delivered, trips }` (units delivered per item, number of trips); `pause(on?)` stops handing out work (drones in flight end their trip) and `paused()` tells. Variables: `logistics.drones`, `logistics.busy` (drones in flight) and `logistics.delivered`. Scripts can use the action `pause_logistics { paused }` and the condition `delivered_at_least { item, count }`. ## Events | Name | Detail | |---|---| | `logistics.assigned` | A drone left for a pick-up; payload `{ drone, item, count, from, to }`, `count` being what it plans to carry. | | `logistics.delivered` | Units reached the port that wanted them; payload `{ item, count, from, to }`. | | `logistics.idle` | A hub has nothing left to do; payload `{ hub }`. It is told when the hub stops working, not every tick. | ## Hooks and modding A game or a mod taps a hook with a document of its `hooks` list, without touching the kit. A trip is a discrete event: the hooks are asked when a hub hands a trip to a drone and when the drone unloads, never during the flight. - `logistics.assign`: before a hub sends an idle drone to a pick-up; payload `{ hub, drone, item, count, from, to }`; cancel: no trip, and that demand is left aside by this hub until its next tick. - `logistics.deliver`: when a drone reached the port that wants its cargo and is about to unload; payload `{ drone, hub, item, count, from, to }`; a tap may lower `count`, or cancel so nothing is unloaded: what is not delivered stays aboard and the drone flies home loaded. ```json { "id": "keep_ore", "hook": "logistics.deliver", "match": { "item": "ore" }, "mul": { "count": 0.5 } } ``` ## When it does not do what you expect - Nothing moves: the hub has no port in `range`, no container offers anything or asks for stock, there is no `machines.production` or `storage.containers`, or the kit is paused (`paused()`). - A hub has no drones: `drones` is 0 on its component; set it, or place it with `placeHub(at, { drones: 2 })`. ## Limits - Items are conserved: the kit moves existing stock between ports and never creates or destroys any. A drone carries one item kind per trip, up to `capacity`. - It has no pathfinding: drones fly straight at `altitude`. It targets the web player and the native player. ## Versions 1.1.0 (2026-10-10): the hooks `logistics.assign` and `logistics.deliver` and moddable settings; 1.0.0 (2026-10-04): first release. Requires `game.engine`.