Configuration defaults: Values shown for operator-configurable settings are the bundled defaults, and can be changed in the module’s configuration or definitions. The server’s active settings take precedence, so costs, speeds, ranges, durations, chances, effects, recipes, limits and enabled features may differ. Command examples illustrate syntax; fixed mechanics and validation bounds are not configuration defaults.
Utilities supplies player-funded power/water, property meters, batteries, reservoirs, virtual fluids, machine access and electrical lamps. Industry registers production content in the same system. It is a configurable prototype; there is no free NPC supply or automatic treasury billing.
First grid and machine
- Register the property in Property. The landlord owns its machines; tenancy/membership alone is insufficient.
- Use
/utilities types and /utilities blueprint meter to inspect the actual configured footprint. Build it, look at its controller and commission a unique meter ID. - Infrastructure staff create a named grid, then look at the meter and connect it.
- Zoning staff stand in the intended machinery property and run
/utilities industrial on. All non-meter machines need approval; registered street lamps may serve ordinary plots. - Build/commission a generator using its blueprint, deposit accepted fuel and verify its output. Add batteries for generated-energy reserves and waterworks/reservoirs for powered water supply.
- Build/commission production/storage types and grant per-machine operators. Deposit inputs and explicitly start one recipe batch.
Example (using actual type IDs from your configured types list): /utilities commission meter workshop_meter, /utilities grid city, /utilities connect city. Do not use the administrative blueprint builder for ordinary player production: it places blocks directly and requires admin authority.
Implemented rules
- One meter per registered Property plot. The Property API's landlord/owner UUID owns the machines. Tenants are not automatically owners; grant them operator access if desired.
- Owners can add individual operators to each machine. Operators can use dashboards, deposit/withdraw resources, start/cancel batches, pause/resume machines, and create fluid links when authorized at both endpoints. They cannot manage operators or decommission machines.
- Owner changes revoke the old operator list and remove fluid links touching the affected machines. Access is checked again on every action, including already-open GUIs. Physical WorldGuard build rules still govern commissioning.
- Infrastructure staff connect property meters to named grids. Appliances and machinery inherit that meter's connection. Electrical lamp registration also requires the grid-connection permission.
- Grids contain no free supply and no NPC fallback. Generators consume player-delivered fuel. Batteries store only actual generated energy. Waterworks consume electricity and require the configured water-containing structure.
- All production machines, extraction machines, tanks, gas vessels, generators, batteries, and water facilities run virtually while their chunks are unloaded. Fluid transfers also work with both endpoints unloaded. There are no chunk tickets, forced chunks, or chunk-load requests in these plugins.
- Commissioning still requires one complete, physically loaded validation. Thereafter, loaded portions are rechecked without loading missing portions. Known damage pauses the machine; repairing a known-invalid machine requires a complete physical validation once. An entirely unloaded, previously validated machine continues from its saved record.
- Staff approve machinery plots with
/utilities industrial on. All device types except property meters require an approved plot to commission and operate. Revocation pauses existing machines and routes without deleting stock. Meters and street lamps can serve ordinary properties. - Production runs only in manually started finite batches. Inputs are reserved, progress pauses if power, authorization, valid structure, or output capacity is unavailable, and cancellation returns inputs. Nothing automatically starts the next batch.
- One simulation step is scheduled per 20 server ticks. Unloaded machines advance normally while the server runs; there is no elapsed-time catch-up after server downtime, slow computation, or a discarded stale calculation.
- Registered lamps draw their normal electrical demand even while unloaded. Their physical block states are updated only when already loaded. The plugin does not keep mobs, hoppers, redstone, or other vanilla systems ticking in remote areas.
Permissions
| Permission | Default | Capability |
|---|
utilities.use | Everyone | Use commands and machines when their owner/operator ACL allows it |
utilities.grid.connect | False | Connect/disconnect any property meter; register/unregister electrical lamps |
utilities.grid.manage | False | Create named grids |
utilities.plots.manage | False | Approve/revoke plots for virtual machinery; never loads chunks |
utilities.reload | False; included in admin | Reload shared messages only, from player or console |
utilities.admin | Operators | All of the above, ownership override, test blueprint building, explicit save |
For an infrastructure department using LuckPerms, for example:
/lp group infrastructure permission set utilities.grid.connect true
/lp group infrastructure permission set utilities.grid.manage true
Grant utilities.plots.manage to the role responsible for industrial zoning. None of these department permissions grants access to machine stock. The owner manages per-machine access while looking at its controller:
/utilities access add PlayerName
/utilities access list
/utilities access remove PlayerName
Names resolve from online/cached players, without a blocking profile lookup; UUIDs are also accepted. Lists persist across restart. There are no automatic trust grants to the owner's previous delegates on a sale.
Controls
Right-click a commissioned structure near its controller to open its dashboard. Only the controller needs to be loaded for local GUI access. Sneak-right-click with a supported resource to deposit the main-hand stack. One portable fluid container holds 100 liters by default; its name and lore show the resource and quantity. Containers are tagged inventory items, not flowing Minecraft liquid blocks. Older tagged containers remain recognized after the display-text upgrade.
The vanilla GUI provides a colored nine-segment fill gauge, exact contents/capacity, percentage full, reserved ingredients, energy, progress, and status. It has paginated Contents, Recipes, and Connections tabs:
- Contents: left-click withdraws one item/container, right-click withdraws eight, and shift-left requests up to 64, subject to inventory space. Quantities smaller than one portable container remain stored.
- Network ports: choose Both, Input, Output, or Disabled. Modes control logical fluid routes; battery modes control charging/discharging. Manual deposits and withdrawals remain available.
- Auto-eject: turn off to retain fluid or energy reserves. The device can still receive input. Water held behind closed output controls is excluded from municipal supply.
- Contents lock: choose a permitted fluid for a tank, including while it is empty. Shift-click clears the lock. A different resource cannot replace existing contents without emptying them first.
- Connections: left-click enables/pauses a route; right-click increases its rate; shift-left decreases it; shift-right removes it. Rate edits require operator access at both endpoints. Displayed rates are configured maximums, not measured flow.
- Recipes: left-click starts exactly one batch. Separate buttons pause operation, deposit held resources, and cancel a batch.
These are Mekanism-inspired controls implemented with ordinary inventory slots and tooltips. They do not require a client mod/resource pack and do not add display entities. Port modes apply to logical endpoints rather than six physical faces; there are no animated fluid meshes or custom mod screens.
Both /utilities and /industry reach the shared command interface. Their reload subcommands refresh their respective message files:
/utilities help
/utilities types
/utilities blueprint <type>
/utilities commission <type> <unique-id>
/utilities open
/utilities deposit
/utilities withdraw <resource> [item-count]
/utilities start <recipe>
/utilities pause
/utilities resume
/utilities cancel
/utilities remove
/utilities link <source-id> <destination-id> <fluid> <liters-per-second>
/utilities links
/utilities unlink <link-id>
/utilities grid <name>
/utilities connect <grid-name>
/utilities disconnect
/utilities lamp add
/utilities lamp remove
/utilities industrial on
/utilities industrial off
/utilities survey
/utilities status
/utilities reload
connect and disconnect operate on the meter being looked at. industrial approves/revokes the property the staff member is standing in. link requires matching grids/worlds and operator access to both endpoints. A tank holds only one fluid/gas resource at a time; empty it to change contents. Transfer rates are bounded per link. Named IDs contain lowercase letters, digits, underscores, or hyphens and start with a letter.
An industrial designation is a persisted permission for machinery, not a chunk loader. The plugins never request or retain chunks. Normal players, spawn rules, or other plugins may still load areas; these plugins do not alter those rules. Bounds on registered machines, links, lamps, surveyed fields, and operators remain configurable. Every registered machine has a finite simulation cost even while unloaded, so zoning does not replace these limits.
The production, transfer, and power calculations run on one background worker using detached snapshots of the logical state. Only one calculation can be in flight. The main thread validates its revision and endpoint availability before applying any resource changes. Player actions, ownership changes, connections, and relevant chunk changes invalidate stale results. There is no growing work backlog and no concurrent mutation of Bukkit inventories.
YAML encoding, backup copying, and atomic state-file replacement run on a separate writer. The main thread captures snapshots, checks a bounded number of already-loaded multiblock portions, applies resource results, changes loaded physical blocks, and services GUIs. Those world/inventory operations cannot safely be run asynchronously through Bukkit. Fully unloaded structures skip physical block reads. Lamp block updates are queued with a per-tick limit; GUIs refresh only while open. No per-pipe-block fluid simulation, fluid entities, per-machine Bukkit repeating tasks, or world-wide block scans are used.
/utilities status reports the last background calculation time, stale-result count, approved plots, and zero chunk tickets. It does not measure the whole plugin's main-thread cost; profile the live server at your intended scale before raising limits. Snapshot capture, ownership checks, and result application still occur on the main thread.
Configuration and persistence
Messages and MiniMessage
Utilities creates plugins/MCSkylines-Utilities/messages.yml. It owns command replies, input errors, help, simulation statuses, dashboard titles, button names/lore, units, and default portable-resource item presentation. Industry creates its own messages.yml for its console and reload replies; Industry machinery uses the shared Utilities catalog.
All these templates support MiniMessage, including gradients and hex colors. Placeholders such as <machine>, <resource>, <amount>, and <prefix> appear in the bundled examples. Player names, identifiers, and other substituted strings are inserted as literal components; they cannot inject MiniMessage click events or formatting. Administratively configured markup is trusted.
/utilities reload requires utilities.reload (included in utilities.admin). /industry reload requires industry.reload (operators by default). Both work from console, refresh messages only, and retain the previous catalog when YAML or template types are invalid. Missing keys fall back to bundled defaults without overwriting customized files. Reopen a dashboard after changing its title; button text refreshes at the configured interval. Already-issued custom items keep their previous appearance but remain valid by resource identity.
Content presentation
Resources, machines, and recipes accept a MiniMessage display-name in their owning plugin's config.yml. Resources also accept an optional lore list and gauge-material. Omit lore to use item-lore from Utilities messages; set lore: [] to hide it. Resource lore supports <resource>, <amount>, and <unit>. Vanilla resource items retain their native item metadata; their configured display names are used in the dashboard.
resources:
water:
material: HONEY_BOTTLE
unit: 100
vanilla: false
fluid: true
display-name: '<aqua>City Water</aqua>'
gauge-material: BLUE_STAINED_GLASS_PANE
lore:
- '<gray>Contents: <resource>'
- '<blue><amount> <unit> per sealed container'
Runtime controls
interaction.target-range (default 6 blocks) controls command targeting, while interaction.controller-range (10 blocks) controls local machine access. performance.structure-audit-ticks defaults to 2, performance.save-interval-ticks to 200, and performance.dashboard-refresh-ticks to 20. Lighting budgets, registry limits, and geology settings remain configurable. Invalid numeric ranges, fractional integer values, malformed YAML, non-text lore, and non-boolean flags reject startup rather than silently substituting another gameplay policy.
The simulation step stays fixed at 20 server ticks so configured per-second power, quantities, and durations keep their meaning. Audit, save, and GUI refresh intervals do not change production speed. Increasing the save interval increases the amount of progress exposed to an unclean shutdown.
Machines, footprints, resource forms, storage sizes, generator output, fuel energy, recipes, durations, input/output quantities, and electrical consumption are data-driven. Blocks are relative x y z MATERIAL entries from the controller, with fixed world axes. AIR entries reserve required interior space. Default copper structures are waxed to prevent ordinary oxidation from disabling a plant.
Restart after editing definitions. The prototype intentionally does not hot-reload an in-flight factory. Active batches retain their original recipe snapshot so a configuration edit cannot silently change reserved ingredients. Removing an occupied machine definition or shrinking capacity below its contents/escrow fails startup without overwriting state. Cancel and empty machines before making incompatible changes. Keep geology field size stable once players start extracting resources.
State is saved every 10 seconds and on a clean stop to state.yml, with the previous snapshot in state.yml.bak. On a save failure the simulation and player mutations pause. Do not edit the state file while running.
This is an isolated-test-server release: snapshots are not a transaction shared with Minecraft's player-inventory files. An abrupt process/host crash can roll these files back to different moments. Crash-consistent item delivery needs further work before this should run an established economy. Normal batch cancellation, transfers, and clean restart persistence are covered by automated tests.
Integrations and remaining scope
- Core registers the resources under
industry:<resource> for /skylines give testing. - Fire's existing
HydrantWaterProvider reports whether the hydrant property's grid has water. This initial bridge gates availability; the current Fire refill API does not debit measured water. Metered hydrant withdrawal is a follow-up integration. UtilitiesApi.consumeWater(location, liters) is provided for later brewing and other water consumers. Narcotics brewing has not been changed.- This version controls registered redstone lamps. Universal vanilla-light conversion, custom lamp models, tanker vehicles, pressure physics, billing, pollution, and a complete downstream crafting economy are not implemented.
- Generic tanks and gas vessels currently use the same quantity-based storage rules. Materials, sizes, and appearance differ; they do not simulate pressure.
- Utility generation is continuous while enabled, consuming fuel even if surplus power cannot be stored. Waterworks stop when full. Batteries have per-step charge/discharge limits.
Build: gradlew.bat :Utilities:build :Industry:build. The automated suite covers finite batches, conservation, fuel/battery limits, blocked outputs, finite deposits, snapshots, persistence, migration, virtual operation, port/lock controls, gauges, configuration parsing, and owner/operator transitions. A source architecture test rejects chunk-loading/ticket API calls. Actual Paper GUIs, lighting, and unloaded-world behavior require the in-game acceptance pass.
Commodity appearance
The complete matching resource pack supplies native held models for water, steel, crude oil, diesel, naphtha, refinery gas, residue and polymer resin. Utilities assigns those models to the stock tagged commodities shared with Industry. Vanilla coal, iron and carbon keep their vanilla appearance. Reissue older items if needed; visual-only items do not carry resource metadata. Operator-defined commodity IDs retain their configured appearance. This changes items, not machine multiblocks.
Machine faults and recovery
If commissioning fails, check controller target, complete loaded footprint including required AIR, property control, approval, unique ID and meter-before-machinery order. If a batch pauses, inspect power, resource reservations, output capacity, structure damage, grid/ACL and plot approval. Cancel returns reserved inputs rather than duplicating outputs. Empty stock, energy/fuel credit and active batch before owner-authorized decommissioning.
Ordinary server downtime does not create catch-up production. Unloaded validated logical machines continue only while the server runs, without ticking vanilla hoppers/redstone/mobs. Ownership changes revoke delegates and fluid links; reopen a dashboard and reauthorize new operators.
Bundled machine directory
Use the live blueprint for every coordinate and orientation; required AIR and WATER cells are part of validation. Capacities and power below are bundled abstract simulation units and can be changed by operators. All machines retain the owner/operator, zoning and same-grid requirements above.
| Type ID | Role | Default capacity / operation |
|---|
meter | Property’s grid connection | One controller block; no resource storage or generated supply |
coal_generator | Electricity from delivered coal | 4,096 resource capacity; power 200; fuel-energy 24,000 per coal |
battery | Store generated electricity | 1,000,000 energy capacity; charge/discharge power 1,000 |
waterworks | Powered water production | 20,000 resource capacity; power demand 40; water rate 100; required water cell in its footprint |
reservoir | Dedicated water storage | 200,000 capacity; fixed water product |
tank | Generic fluid storage | 20,000 capacity; one chosen fluid until emptied |
gas_vessel | Generic gas/fluid storage | 10,000 capacity; quantity-based, without pressure simulation |
Industry registers additional types, resources and finite recipes; see the Industry directory. A machine’s capacity does not create stock. Deposit genuine resources or produce them through a valid batch. The default portable water container carries 100 liters; a displayed commodity model alone does not confer resource identity.
Reading command syntax
Configuration defaults: Values shown for operator-configurable settings are the bundled defaults, and can be changed in the module’s configuration or definitions. The server’s active settings take precedence, so costs, speeds, ranges, durations, chances, effects, recipes, limits and enabled features may differ. Command examples illustrate syntax; fixed mechanics and validation bounds are not configuration defaults.
<argument> is required; [argument] is optional. Replace the placeholder, including its brackets, with your value. Choices separated by a vertical bar mean choose one. ... accepts the remaining words. Do not type quotation marks around multiword names unless the command specifically requires them. A bare command has no required arguments. Examples use sample players/IDs: substitute entries from your server and use Tab for configured IDs.
player means a username; operational actions usually require that player online. amount and price are currency values such as 25.00, unless the row specifies items, levels, or units. reason, memo, message, name, and statement accept text where supported. duration uses the module's duration format (for example 10m, 2h, or 7d); it is not a bare number of minutes unless stated. id is the exact identifier displayed by that system, not its friendly name. Permissions and ownership/state/location checks both apply.
Shared machine commands
Both /utilities and /industry route to this interface. All gameplay commands require utilities.use and an in-game player; targeted stock/batch actions also require owner/operator ACL. Staff grid/zoning permissions do not grant stock access. Industry reload refreshes Industry messages; Utilities reload refreshes shared messages, not machine footprints/recipes.
| Syntax | Required/optional values and action | Additional authority |
|---|
/utilities, /utilities open | Open looked-at machine dashboard | Operator |
/utilities help | Help | Use |
/utilities types | List registered machine type IDs | Use |
/utilities resources | List registered resource IDs | Use |
/utilities blueprint <type> | Print relative block coordinates/materials, including AIR | Use |
/utilities build <type> | Place blueprint directly for testing | utilities.admin |
/utilities commission <type> <unique-id> | Register looked-at fully built controller/footprint | Property/build control, approval except meters |
/utilities grid <name> | Create named grid ID | utilities.grid.manage |
/utilities connect <grid-name> | Connect looked-at meter | utilities.grid.connect |
/utilities disconnect | Disconnect looked-at meter | utilities.grid.connect |
/utilities access list | Owner/operators of looked-at machine | Owner/admin |
/utilities access add <player-or-UUID> | Add cached/online player or exact UUID delegate | Owner/admin |
/utilities access remove <player-or-UUID> | Remove delegate | Owner/admin |
/utilities deposit | Deposit supported main-hand stack into target | Operator |
/utilities withdraw <resource> [item-count] | Withdraw portable items; defaults one, not liters | Operator and inventory space |
/utilities start <recipe> | Start exactly one configured recipe batch | Operator; input/power/output checks |
/utilities pause, /utilities resume | Disable/enable target operation | Operator |
/utilities cancel | Cancel target batch and return reserved inputs | Operator |
/utilities remove | Decommission empty target, removing attached links | Owner/admin; no batch, stock, energy or fuel credit |
/utilities link <source-id> <destination-id> <fluid> <liters-per-second> | Directed virtual fluid route, integer rate bounded by configured limit | Operator at both endpoints, same world/grid |
/utilities links | List links accessible at either endpoint | Operator |
/utilities unlink <link-id> | Remove route ID shown by links | Operator at either endpoint |
/utilities industrial <on or off> | Approve/revoke the property you stand in | utilities.plots.manage |
/utilities lamp <add or remove> | Register/unregister looked-at configured electrical lamp | utilities.grid.connect; property/meter/grid |
/utilities survey | Survey finite local field state | Use |
/utilities status | Logical registries/background simulation counts | Use |
/utilities save | Explicit state snapshot | utilities.admin |
/utilities reload | Shared message catalog only | utilities.reload; player/console |
/industry reload | Industry message catalog only | industry.reload; player/console |
IDs use lowercase letters/digits/underscore/hyphen and begin with a letter. Type, resource and recipe IDs come from config/types/resources/dashboard. Links use the listed generated ID. Example: /utilities link oil_storage refinery_input crude_oil 100. Fluid defaults use 100-liter portable containers, so withdraw water 2 requests two containers rather than two liters.
Root commands and aliases
These are the registered command entry points. The subcommand tables above describe their complete operations. Alias names use the same arguments as their root.
| Syntax | Purpose | Permission / aliases |
|---|
/utilities help | Property utilities and industrial infrastructure | Checked by operation; aliases: /utility |