Перейти к содержимому

IEMS

Added SE energy units and a series of energy transmission devices in the style of 《Arknights: Endfield》, utilizing high-precision storage and computation for energy.

NeoForge
Загрузчики
NeoForge
Скачиваний на Modrinth
268
Подписчиков на Modrinth
2
версии
4
Обновлён
11 октября 202611 окт.
Опубликован
в 2026
Normally Operating Power Grid · свайп

Коротко о моде

Работает на NeoForge
Для Minecraft 1.21.1
Нужен и в игре, и на сервере
Последняя версия — 0.8.0-beta.120 от 11 октября 2026
Лицензия MIT — бесплатно
Где нужен
В игреобязателенНа сервереобязателен

Нужен и в игре, и на сервере

Версии игры1.21.1
Перевода пока нет — показываем оригинал на английском

Integrated Energy Management System (IEMS)

Version Codename NEOFORGE MINECRAFT

⚠️ IMPORTANT NOTICE FOR INTERNATIONAL PLAYERS:

IEMS is currently a FRAMEWORK ONLY. It does not contain any functional core blocks, generators, or energy storage on its own.

The official Core Provider Mod is currently undergoing testing in the China region and will be released on Modrinth soon.

An energy management framework mod designed for large modpacks: a unified energy abstraction, high-precision BigInteger arithmetic, laser topology visualization, and a web monitoring panel. Devices and cores are hooked up by external mods; IEMS's job is to weave them into one single power grid.

Development team: 等离子工作室 (DLZstudio)

Mod ID: iems

Development codename: IEMS0930

License: MIT License


📖 Table of Contents


Introduction

IEMS 0.8.0-beta is a complete rewrite of the old IEMS (with a total separation of logic layer and presentation layer):

  • Energy management framework — this mod does not ship power generation/storage cores; cores and devices are hooked up by external mods through the API (official reference implementation: IEMS-TestDevices)
  • Unified energy abstraction — units such as FE / AE are uniformly converted to SE (Standard Energy), with BigInteger high-precision arithmetic and no precision loss for extremely large values
  • Laser connection visualization — laser beams between devices show the grid topology in real time: powered yellow / unpowered red / bridged cyan (configurable)
  • Manual wire pulling + automatic networking — Shift + right-click to drag a wire and create a connection (HUD shows live distance), automatic scanning and connection within a broadcast tower's range, automatic bridging of external FE devices
  • Protocol capacity management — a device-count-based load limit for the grid, with automatic shutdown protection when exceeded
  • Web monitoring panel — view grid status, devices, topology, and historical metrics in a browser in real time (JDK built-in HttpServer, zero third-party dependencies)
  • Simulation-style persistence — grid data is stored in iems_grid.dat and rebuilt from device factories after a restart; it keeps running even when chunks are not loaded
  • Open API — a stable IEMSAPI static facade + the IIemsInteractable wire-pulling contract, for external mods to hook into

⚠️ Important: this mod is a framework and does not provide core blocks! You need to install a mod that provides a core (the official test mod IEMS-TestDevices, or wire one up yourself via the API) to form a complete grid.


Blocks

Core Block

📌 Provided by other mods through CoreDevice (e.g. the test core from IEMS-TestDevices)

  • The grid's identity anchor, the main inlet/outlet of the energy pool, and the protocol capacity manager
  • The chunk it is in when registered is automatically set to force-loaded (released on unregister)
  • Unique instance; the starting point for the grid's BFS reachability check

Energy Transfer Relay

  • Long-distance signal relaying and power transfer; a manual wire-pulling device (does not take part in automatic scanning)
  • Connection distance: 500 blocks
  • Laser anchor: block center (0.5, 10.75, 0.5) (tower top)
  • Laser color: yellow (powered) / red (unpowered)
  • Protocol capacity used: 1

Energy Broadcast Tower

  • Short-range wireless transfer, with automatic + manual dual modes
  • Connection distance: 50 blocks
  • Signal source position: tower top (0.5, 8.0, 0.5)
  • After placement, automatically scans and connects devices in range (including relays and other broadcast towers)
  • Must be connected to the core directly or indirectly to actually supply power (isolated connections are rendered with a red laser)
  • Protocol capacity used: 1
  • Comes with light level 7, visible in the dark

External FE Devices (automatic bridging)

  • IEMS automatically discovers any NeoForge FE device in range (generators/consumers/energy storage from other tech mods)
  • Rescans every 20 ticks (1 second) and automatically creates a bridge connection on discovery (cyan laser, configurable to a regular color)
  • The other mod needs no adaptation at all

Gameplay Guide

Getting Started

1. Understand the energy unit

All energy uses SE (Standard Energy) as its unified unit and is stored precisely as a BigInteger. The energy of external FE devices is converted automatically by the bridge layer.

2. How the grid works

┌────────────────────────────────────────────┐
│       Core (provided by another mod)       │
│    Energy pool · Protocol cap · BFS root   │
│                     │                      │
│       ┌─────────────┼─────────────┐        │
│       ↓             ↓             ↓        │
│   ┌────────┐   ┌────────┐   ┌──────────┐   │
│   │ Relay  │───│ Tower  │───│FE device │   │
│   │500 blk │   │ 50 blk │   │ auto-brg │   │
│   └────────┘   └────────┘   └──────────┘   │
└────────────────────────────────────────────┘

3. Networking workflow

  1. Install a mod that provides a core and place the core
  2. Place relays / broadcast towers (or make direct use of existing FE devices)
  3. Aim at a device and Shift + right-click to enter wire-pulling mode (the HUD shows the live distance)
  4. Aim at the target device and Shift + right-click to finish the connection
  5. Devices within a broadcast tower's range are networked automatically; FE devices are bridged automatically
  6. Open http://127.0.0.1:28567/ in a browser to monitor the grid

Device Power Status

  • Devices connected to the core (directly or via relays/broadcast towers) are powered automatically
  • When the grid is shut down (protocol capacity exceeded or manual shutdown) all devices lose power and lasers turn red
  • Connections where both ends are registered but not connected to the core (islanded connections) are rendered as a red laser

Connection System

Manual Wire-Pulling Mode

How to enter:

  • Aim at a device that implements the wire-pulling contract and press Shift + right-click

During wire pulling:

  • The HUD shows the live pulling distance and the maximum distance
  • Beyond the maximum distance (+10 blocks of buffer) the wire is retracted automatically with a notification
  • A dimension change (going through a portal / cross-dimension TP) retracts the wire immediately — old coordinates are meaningless in the new dimension
  • Leaving the world clears the wire-pulling state automatically

Completing the connection:

  • Aim at the target device and press Shift + right-click again
  • The client sends a connection request, and the server re-validates it (legal endpoints, same dimension, distance, duplicates, relay rules) before creating the connection
  • Clicking the starting point itself or a non-device block → cancels wire pulling

Valid Connection Rules

Connection typeValidCondition
Core → Relay✅Within distance, core force-loaded
Core → Broadcast tower✅Within distance
Relay → Relay✅Within 500 blocks
Relay → Broadcast tower✅Uses the smaller distance limit of the two ends
Broadcast tower → Broadcast tower✅Within 50 blocks, automatic or manual
Broadcast tower → FE device✅Automatic bridging (ADAPTER_BRIDGE)
Cross-dimension connection❌Rejected by both client and server (except dimension bridges)
Island-to-island interconnection not connected to the core⚠️Allowed to be created, rendered as a red laser, not powered

Connection Distance Limits

⚠️ The distance limit is the smaller of the distances declared by the two devices at the ends. When nothing is declared, the framework default of 500 blocks is used.

Device combinationMaximum distance
Relay ↔ Relay500 blocks
Broadcast tower ↔ Broadcast tower50 blocks
Broadcast tower ↔ Relay50 blocks
Bridge (FE device ↔ device)Follows the anchoring device

Laser Display

StateColorDescription
Powered connectionYellowAnimated with power flow
Unpowered / islanded connectionRedGrid shut down or not connected to the core
FE bridgeCyan (default)Distinguished from regular connections when colorizeAutoConnect = true
FE bridgeYellow/RedSame color as regular connections when colorizeAutoConnect = false

Rendering features:

  • Beam width gets a screen-space minimum-width compensation based on distance (does not become too thin to see at a distance)
  • Double-sided rendering, visible from any viewing angle
  • Cross-dimension islanded connections are not rendered (direction vector cannot be computed)
  • Drawn as long as either end is within render distance (long connections are not culled as a whole by the frustum)

Protocol Capacity System

What Is Protocol Capacity?

Protocol capacity is the upper limit on the number of device connections the grid can support.

DeviceCapacity used
Relay1
Broadcast tower1
Externally connected deviceDeclared by the device
Core0 (uses none)

Limit: declared by the core at registration time (protocolLimit), adjustable at runtime.

Over-Limit Protection

When used capacity exceeds total capacity:

  1. The grid shuts down automatically
  2. All devices lose power and lasers turn red
  3. /iems status shows the reason for the shutdown

How to recover:

  • Remove some devices (an automatic recovery is triggered after a rescan)
  • Or have the core mod raise the capacity at runtime

Web Monitoring Panel

How to Access

  1. Launch the game and load a world (the panel starts/stops with the server)
  2. Visit in a browser: http://127.0.0.1:28567/
  3. A random token is generated automatically on first launch (written to the config file)

Authentication

  • All /api/* endpoints require a token: request header `X-IEMS-Token: or query parameter?token=`
  • /health and / (home page) need no authentication
  • The token lives in config/DLZstudio/IEMS/APIserve.toml

Config File

# config/DLZstudio/IEMS/APIserve.toml
[APIserve]
enabled = true          # Whether to enable the web panel
host = "127.0.0.1"      # Bind address; for remote access change to "0.0.0.0" (make sure to change the token too and set up a TLS reverse proxy)
port = 28567            # Listening port
token = "a1B2c3D4..."   # API token (randomly generated on first launch)

Endpoint Overview

MethodPathDescription
GET/healthLiveness probe (no envelope)
GET/api/statusGrid overview (core position/energy/capacity/protocol/shutdown status)
GET/api/devicesDevice list (including the core, per-device attributes)
GET/api/connectionsConnection list (reachable main grid + boundary connections)
GET/api/topologyTopology snapshot (aggregated main grid/islands/boundary views)
GET/api/metricsTime-series metrics (ring buffer, sampled energy/capacity/protocol/device count)
POST/api/grid/activeManually enable/disable the grid (maps to IEMSAPI.setGridActive)

Data Envelope

{
  "schema": 1,
  "ts": 1727073600000,
  "data": { }
}
  • BigInteger fields such as energy/capacity/rates are transmitted as decimal strings (to avoid precision loss)
  • Dimensions use resource-key strings (e.g. "minecraft:overworld")
  • With no core, energy returns "0" and corePos is null

curl Examples

# Read-only endpoint
curl -H "X-IEMS-Token: <token>" http://127.0.0.1:28567/api/status

# Write endpoint (shut down the grid)
curl -X POST -H "X-IEMS-Token: <token>" \
     -H "Content-Type: application/json" \
     -d '{"active": false}' \
     http://127.0.0.1:28567/api/grid/active

💡 In Windows PowerShell, inline JSON gets its quotes mangled by argument passing; write the request body to a file and submit it with --data-binary @body.json instead.


Energy Exchange Rate Configuration

The exchange rate between SE (the grid's internal standard unit) and FE determines "how large an energy shortfall justifies calling on FE-tier devices", and can be tuned to the energy scale of your modpack.

config/DLZstudio/IEMS/Energy.toml:

# IEMS energy exchange rate configuration
[energy]
# How many FE 1 SE converts to (i.e. SE:FE = 1:N).
# Default 10; range [1, 900000000000000000000000000] (the upper bound is the old fixed value, so old behavior can be restored in one step).
# After editing, run /iems reload in-game for it to take effect immediately (no need to restart the game or leave the world).
# Note: the change reinterprets the existing SE values in the grid (the FE equivalent of 1 SE is redefined), so adjust with care.
fePerSe = 10
  • Default: 1 SE = 10 FE: matched to the scale of mainstream FE devices, so FE-bridged devices can take part in grid throughput normally
  • Lower bound 1 (1 SE = 1 FE), upper bound 9×10²⁶ (the old hard-coded default; set it to this value to restore old behavior)
  • Out-of-range values are clamped to the bounds automatically, and non-numeric values fall back to the default
  • Manual reload: after editing the file, run /iems reload in-game (permission level 2) for it to take effect immediately — no need to restart the game, and no need to leave the world
  • If the whole key is deleted while editing, the currently effective value is kept rather than falling back to the default (partial edits won't cause accidental damage)

/iems reload

One command reloads all IEMS config files (manually triggered, no automatic polling):

Config fileReload effect
Energy.tomlRe-parses the exchange rate and injects it into the converter, effective immediately
APIserve.tomlRebuilds the web panel, applying enabled / host / port / token
Renderer.tomlInvalidates the client render config cache (effective on the local client's next read; remote clients on a dedicated server need to re-enter the world)

/iems reload requires permission level 2 (same as /iems shutdown and /iems restart).

⚠️ The exchange rate is the definition of SE versus FE; changing it immediately reinterprets all existing SE values in the grid (core energy storage, device capacity, etc.). The SE ratios between devices stay the same and settlement remains conservative, but the FE equivalents presented externally scale overall — set it once according to your modpack's energy scale and avoid adjusting it frequently.

⚠️ When the exchange rate is set high, the real rate of FE-scale devices may convert to less than 1 SE/tick; the bridge layer already adapts its declaration granularity to the "amount delivered in one tick", so throughput will never be crushed down to fePerSe FE/tick no matter how high or low the rate is.


Render Configuration

config/DLZstudio/IEMS/Renderer.toml:

# IEMS render configuration
[renderer]
colorizeAutoConnect = true   # true: automatic bridge connections use cyan; false: same color as regular connections (yellow/red)
  • Zero-IO lazy cache: config is read on demand and cached, and invalidated automatically when leaving the world
  • After changing the config, re-entering the world applies it, with no game restart needed

Persistent Storage

Grid Data Saving

Storage location:

world save/data/iems_grid.dat

Persisted content:

  • Device list (indexed by factory ID, including position/type/parameters)
  • Core information
  • All connections (including islanded connections and bridge connections)

Simulation-Style Rebuild (M9)

  • Devices are persisted as a factory ID + parameters, rather than relying on the BlockEntity staying alive
  • On server startup, iems_grid.dat is traversed: factory rebuild → restoreState → grid recovery
  • The grid keeps simulating even when the chunk a device is in is not loaded (the BlockEntity is only the appearance/view)
  • The chunk the core is in is force-loaded automatically when registered

Automatic Save Points

  • When a connection is created / removed
  • When the world is saved
  • When the server stops

Data Safety

  • Breaking a device unregisters it automatically and cleans up its connections
  • Chunk unloading no longer unregisters devices (fix in BUILD.00000110: setRemoved mistakenly unregistered the core, causing connections to be lost after a restart)
  • Connections are fully preserved after a save restart

Advanced Gameplay

Networking Tips

  • Height advantage: build broadcast towers high up to extend effective coverage
  • Relay backbone: use relays (500 blocks) for long-distance backbone links and broadcast towers (50 blocks) for end-point coverage
  • FE device reuse: existing tech-mod devices are bridged automatically, with no need to disassemble or modify anything
  • Island pre-wiring: devices not yet connected to the core can be interconnected first (a red laser indicates no power), and the whole network powers up once the core is in place
  • Core siting: the core's chunk is force-loaded, so put it in the center of your main base to shorten the backbone

Energy Management Strategies

  • Peak/valley balancing: rely on energy storage devices to discharge during peak usage
  • Capacity planning: keep a 20% protocol capacity margin; exceeding the limit shuts down the whole grid
  • Monitoring and alerts: /api/metrics provides time-series samples that can feed an external dashboard
  • Zoned power: give important devices their own core/subnet

Technical Details

Architecture: Full Logic-Presentation Separation

External mod (device provider)
│
└── Block / BlockEntity (registered with Minecraft, appearance/view only)
    │
    ├── new the logic instance in the constructor/loadAdditional() (pure POJO, no Level needed)
    ├── hook up in onLoad() via IEMSAPI.attachOrRegisterDevice() (server side only)
    └── persist parameters in saveAdditional()
                    │
                    ▼
┌─────────────────────────────────────────────┐
│            IEMS logic layer (com.iems)       │
│                                             │
│  CoreDevice (unique instance, force-loaded)  │
│  Device pool DeviceRegistry (N instances)    │
│                                             │
│  GridTopology (BFS/topology snapshot)        │
│  EnergyDispatcher (per-tick energy allocation + frame-sliced scheduling) │
│  ProtocolCalculator (capacity calculation/over-limit detection) │
│  FEDA (FE device discovery and bridge adaptation) │
└─────────────────────────────────────────────┘

Design philosophy: instance autonomy — every device instance is fully independent, holds no references to other instances, and interacts with the grid only through the dispatcher; it supports independent new / destroy / parameter changes and naturally supports multi-core parallelism.

Module Breakdown

PackageResponsibility
com.iems.apiPublic facade (IEMSAPI / IIemsInteractable / SubSeAccumulator)
com.iems.coreGrid kernel (grid / node / dispatch / protocol)
com.iems.edsDevice Discovery System EDS (scanner + identity axis, discovery only, no bridging)
com.iems.adapterAdapter layer (DA: FEDA disguises external FE devices as nodes and hooks them into the grid)
com.iems.networkC2S/S2C payloads (connection requests, full sync, shutdown sync)
com.iems.webpanelWeb panel (JDK HttpServer, port 28567)
com.iems.exampleExample devices (relay/broadcast tower, depending only on the api facade)

Threading Model

  • All grid state is owned exclusively by the server tick thread
  • External threads (web panel HTTP threads, etc.) submit tasks through IEMSAPI.runOnServerThread() / callOnServerThread(), eliminating data races
  • The web panel thread pool is stopped manually on world reload to prevent thread leaks

Network Sync

  • GridSyncPayload — full topology sync (three lists for main grid/islands/bridges, with size validation to prevent OOM)
  • ConnectionRequestPayload — C2S wire-pulling connection request (server re-validation + proximity check + rate limiting)
  • Shutdown status / protocol capacity sync along with snapshots; the HUD shows three states

Laser Rendering Details

  • Billboard width direction: width = beam direction × (camera→beam), so side views don't vanish
  • Screen-space minimum width: max(0.03, distance × 0.0015), so distant beams don't thin out and disappear
  • Degenerate triangles separate adjacent strips, eliminating "ghost diagonals"
  • Client cache (ClientGridCache) handles the three lists (main grid + islands + bridges), with quadrant statistics and EMA smoothing

Device Discovery System

The Device Discovery System (EDS) answers one question: which external energy devices are nearby, and which energy system does each of them belong to?

Its boundary is very clear — it only discovers and classifies; it does not register, create connections, or convert. All bridging decisions are left to the downstream adapter layer.

Scan Entry Points

IEMSAPI.EDS.scan(level, center, radius)   // synchronous one-shot scan (server main thread)
IEMSAPI.EDS.addListener(listener)         // register a consumer (can be unregistered)
IEMSAPI.EDS.registerFlavor(flavor)        // declare your own energy system
  • Radius is in blocks, clamped to [1, 128] (EDSScanner.MAX_RADIUS = 128)
  • Global entry points: IEMSAPI.EDS is a static facade (equivalent to global functions); the scanner's listener table and identity table are also static
  • Only loaded chunks are enumerated, then clipped to a spherical range
  • Already registered IEMS devices (including the core) are skipped, and counted in the report's skippedIemsDevices
  • Executed synchronously, no async, no rate limiting — call frequency is up to the caller (the built-in adapter does it once every 20 ticks)

Single-Device Probing

Each block entity is probed by taking the union of 7 directional contexts and reading the NeoForge IEnergyStorage capability:

ReadingPurpose
canExtractClassified as a producer
canReceiveClassified as a consumer
stored / capacityStored amount and capacity snapshot
Exposed sidesRecords from which side energy can be drawn (exposedSides; null means no directional context)

Identity Axis: EnergyFlavor

The device's energy system is resolved from the namespace of its block ID:

FieldMeaning
namespaceThe mod's namespace (e.g. appliedenergistics2)
unitThat system's energy unit (determines the conversion basis for bridging)
displayNameDisplay name of the identity (e.g. Applied Energistics)
  • External mods declare their own system via IEMSAPI.EDS.registerFlavor
  • Unregistered namespaces are treated as FE by default, using the namespace itself as the display name

Discovery Report: EDSReport

One scan produces an immutable report (EDS, v1) that is pushed to all listeners:

FieldDescription
origin / radius / scanTickScan origin, clamped radius, scan moment (level.getGameTime())
devicesList of discovered devices (EDSDevice, stable order)
chunksScannedNumber of loaded chunks actually enumerated
blockEntitiesProbedTotal number of block entities probed (including those without a matching capability)
skippedIemsDevicesNumber of registered IEMS devices skipped (including the core)

Convenience subset methods: producers() / consumers() / storage() / byNamespace(ns).

Consumer Contract: IEDSListener

void onDiscovery(EDSReport report);
  • The callback runs on the server main thread
  • Mental model: the discovery layer only says "this is an FE device, that is an AE device"; whether, with whom, and how to bridge is entirely up to the listener
  • Registering the same listener twice means it receives two copies of every report

⚠️ EDSReport is a snapshot at scan time, not live state. Do not rely on it to decide whether an existing device is alive — the discovery layer classifies registered positions as skippedIems and skips them, so a rescan will inevitably not see them (for the correct approach, see sync in the adapter layer).


Adapter Layer

The adapter layer (denoted DA; also called EDA when referring to the set of all DAs) is a pluggable execution layer: it registers external devices found by the discovery layer into the grid disguised as IEMS nodes, and performs bidirectional SE ↔ target-unit read/write conversion every tick.

There is one DA implementation per energy system, named "system name + DA" — the only implementation in this version is FEDA (the DA for the FE system); AE / EU and others are future extension points.

Why an Adapter Layer Is Needed

The dispatcher only recognizes the node interfaces and does not distinguish between "native SE devices" and "adapter-disguised nodes":

IEnergyProducer / IEnergyConsumer / StorageDevice

A DA is merely an executor that translates SE instructions into an external protocol — adding a new energy system means adding one DeviceAdapter implementation, with no kernel changes required.

The DeviceAdapter Interface

Every adapter is bound to one auto-connectable TransferDevice (such as an energy broadcast tower):

MethodWhen calledResponsibility
unit()—The energy system unit it adapts to (FE / AE…)
scan(level, center, radius)PeriodicRequests a discovery-layer scan and returns the device list this adapter cares about
sync(level)Every 20 ticksDiffs the report against registered nodes: register new ones, unregister gone ones
tick(level)Every tickPerforms actual reads/writes on the external capabilities of its nodes (extract / measure remaining receive capacity / deliver)
detach()Host invalidatedUnregisters all of its nodes

⚠️ sync decides existence by probing the block capability of existing devices directly, not relying on the scan report — because the discovery layer classifies registered positions as skippedIems and skips them; if only the report were consulted, a rescan would mistake existing devices for gone ones.

Dispatcher: FeBridgeTicker

PeriodAction
Every tickIterates auto-connected relays → DeviceAdapter.tick; also sweeps orphan nodes
Every 20 ticksDeviceAdapter.sync rescan (diff sync)

Order within the main loop (IEMSEvents): FeBridgeTicker.tick / tickRescan → EnergyDispatcher.dispatchAtTick, i.e. sync external devices first, then perform this tick's energy allocation.

Disguised Nodes and Orphan Sweeping

Nodes registered into the grid by adapters all implement the marker interface IAdapterNode:

  • owner() — ownership chain: host relay → per-device disguised node
  • isOrphaned() — whether the host has been unregistered (the position in the registry is no longer the original instance)

Two uses:

  1. Auto-connect exclusion — IemsAutoConnector skips RELAY_TO_DEVICE automatic connections for disguised nodes; their access goes through ADAPTER_BRIDGE only, avoiding double-connection conflicts
  2. Orphan sweeping — after the host relay is unregistered, the disguised node becomes a connectionless orphan, which FeBridgeTicker detects and unregisters every tick

Built-in Implementation: FEDA

FEDA is the only DeviceAdapter implementation in this version; it binds to auto-connect relays (broadcast towers) and registers by classifying external device capabilities:

External capabilityDisguised node typeScenario
Can extractFeProducerAdapterExternal generator → feeds power into the grid
Can receiveFeConsumerAdapterExternal consumer → draws power from the grid
Has capacityFeBufferAdapterExternal storage → bidirectional throughput
  • Registers external devices as independent disguised nodes via silentRegister
  • Establishes bridge connections via IEMSAPI.addConnection(..., ConnectionType.ADAPTER_BRIDGE) (rendered as a cyan laser; coloring can be disabled with colorizeAutoConnect)
  • On host invalidation (relay broken / unregistered) it calls detach() and cleans up its nodes

Conversion Buffer: FeConversionBuffer

Maintains per-device extraction-side and push-side buffers for FE ↔ SE; it is the core state machine of energy conversion in the DA layer:

  • Computes the SE demand declaration from the external receive headroom and maxFePerTick
  • SE allocated by the grid is converted to FE at the current fePerSe into the push pool, then delivered to the external device
  • The demand declaration granularity adapts to the exchange rate: when the amount delivered in one tick is less than 1 SE, the declaration is rounded up, so raising the exchange rate does not choke throughput (see Energy Exchange Rate Configuration for details)

Developer API

Quick Start

IEMS is integrated into external mods as a Jar-in-Jar / libs dependency:

Gradle dependency (Groovy DSL):

dependencies {
    // After copying the IEMS build artifact into libs/:
    implementation files('libs/IEMS-0.8.0-beta-BUILD.00000120.jar')
}

neoforge.mods.toml dependency declaration:

[[dependencies.yourmod]]
    modId="iems"
    type="required"
    versionRange="[0.8.0-beta,)"   # ⚠️ The -beta suffix is mandatory; "[0.8.0,)" compares as unsatisfied and crashes on load
    ordering="AFTER"
    side="BOTH"

Device Integration: Three Logical Base Classes

An external mod's BlockEntity holds a logic instance (a pure POJO):

// 1. Register the factory during mod loading (key to M9 persistence rebuild)
IEMSAPI.registerDeviceFactory("mymod:my_device", MyDevice::new);

// 2. Hook up in BlockEntity.onLoad() (server side only)
GlobalPos pos = new GlobalPos(level.dimension(), blockPos);
MyDevice device = new MyDevice("My Device");
IEMSAPI.attachOrRegisterDevice(pos, device, "mymod:my_device");
// Devices with a factoryId are persisted to iems_grid.dat and rebuilt by the factory after a restart, even without chunk loading

// 3. Unregister in BlockEntity.setRemoved()
IEMSAPI.unregisterDevice(pos);

Core integration:

CoreDevice core = new CoreDevice("My Core",
        BigInteger.valueOf(1000),   // protocolLimit protocol capacity limit
        BigInteger.valueOf(100000), // energyCapacity total energy capacity (SE)
        BigInteger.ZERO);           // powerGenRate self-generated energy per tick
IEMSAPI.attachOrRegisterCore(pos, core, "mymod:my_core");
// The chunk it is in is force-loaded automatically on registration; released on unregister

Wire-Pulling Contract: IIemsInteractable

A BlockEntity can take part in the framework's built-in Shift+right-click wire-pulling interaction simply by implementing this interface:

public class MyDeviceBlockEntity extends BlockEntity implements IIemsInteractable {
    @Override
    public boolean canBeConnectionEndpoint() {
        return true;
    }

    @Override
    public int getMaxConnectionDistance() {
        return 500;  // framework default of 500 blocks when not declared
    }
}
  • A purely client-side discovery mechanism (instanceof detection); the server does not rely on this interface for security decisions
  • The wire-pulling HUD, over-distance retraction, and dimension-change retraction are all handled by the framework
  • Server-side connection creation goes through ConnectionRequestPayload re-validation (endpoints / same dimension / distance / duplicates / relay rules)

IEMSAPI Static Facade (Method Overview)

CategoryMethodDescription
Thread safetyrunOnServerThread(Runnable)Submit a task asynchronously from an external thread
Thread safetycallOnServerThread(Supplier, timeoutMs)Wait synchronously for a result from an external thread
FactoryregisterDeviceFactory(id, factory)Register a device factory (M9 rebuild)
DeviceattachOrRegisterDevice(pos, node, factoryId)Hook up a device (persisted if it has a factory)
DeviceunregisterDevice(pos)Unregister a device
CoreattachOrRegisterCore(pos, core, factoryId)Hook up a core (chunk force-loaded)
CoreunregisterCore(pos)Unregister a core
QuerygetCurrentEnergy() / getTotalCapacity()Energy pool (BigInteger)
QuerygetProtocolUsed() / getProtocolTotal()Protocol capacity
QuerygetSnapshot()Topology snapshot (main grid/islands/boundary)
QueryisDeviceConnected(pos)Whether the device is connected to the main grid
ConnectionaddConnection(a, b, type) / removeConnection(...)Connection management
ControlsetGridActive(boolean) / forceRescan()Grid on/off / force rescan
PowerregisterPowerInput(id, rate) / unregisterPowerInput(id)Power source registration
EDSEDS.scan(level, center, radius)Nearby device scan (radius clamped to [1,128])
EDSEDS.addListener(l) / EDS.removeListener(l)Register/unregister a discovery listener
EDSEDS.registerFlavor(flavor)Register an energy system identity (namespace → unit/display name)

For the full design of the discovery and adapter layers (scan boundaries, report structure, DeviceAdapter lifecycle, disguised nodes and orphan sweeping), see Device Discovery System and Adapter Layer.

Web Panel HTTP API (Complete)

Key points:

  • All /api/* endpoints require a token (X-IEMS-Token header or ?token= parameter)
  • Uniform envelope {schema, ts, data}, with BigIntegers stringified
  • Error codes: 400 (parameter/JSON error), 401 (unauthorized), 404 (route not found), 405 (method not allowed), 409 (state conflict such as no core), 500 (internal error)

Reference Implementation: IEMS-TestDevices

The test mod IEMS-TestDevices (modid iemstest) demonstrates every integration pattern:

DeviceWhat it demonstrates
test_core test coreCoreDevice integration + protocol capacity declaration
auto_relay / manual_relayAutomatic/manual relay devices (TransferDevice)
fe_batteryFE storage block (automatically bridged by FEDA)
arc_furnace arc furnaceA complete example of a power-consuming device with GUI/Menu

Building and Development

BUILDID Build System

This mod is built using the DLZ Studio BUILDID convention; the only legal build entry points are:

.DLZstudio/buildid/
├── BUILDID.txt    # Iteration counter (8-digit zero-padded)
├── build.ps1      # Windows build entry point
└── build.sh       # Unix/Linux/macOS build entry point

Windows:

# ⚠️ Set JAVA_HOME first (the script environment does not inherit it)
$env:JAVA_HOME="D:\Java\jdk-21"
$env:Path="D:\Java\jdk-21\bin;"+$env:Path
powershell -ExecutionPolicy Bypass -File .\.DLZstudio\buildid\build.ps1

Unix:

./.DLZstudio/buildid/build.sh

Release mode (version number synced to neoforge.mods.toml):

  • build.ps1 -Release / build.sh --release

Artifact naming: IEMS-0.8.0-beta-BUILD.00000120.jar (normal) / iems-1.21.1-neoforge-0.8.0-beta.120.jar (release, version number written back to neoforge.mods.toml)

Testing

.\gradlew test        # webpanel + client unit tests (including RendererConfigTest, etc.)
.\gradlew compileJava # quick compile check

Environment Requirements

  • JDK 21
  • NeoForge 21.1.x (dependency range [21.1.0,))
  • The test runtime classpath has been synced to a pure ASCII directory (to work around GBK decoding issues with Chinese paths)

Requirements

Required Dependencies

ModVersionDescription
NeoForge21.1.0+Mod loader (dependency range [21.1.0,))
Minecraft1.21.1—

Bundled Components

ComponentDescription
GeckoLib 4.8.4Bundled via Jar-in-Jar (META-INF/jarjar/); players do not need to install it separately

Recommended Companions

ModDescription
IEMS-TestDevicesOfficial test mod: test core/relay/FE battery/arc furnace (the recommended reference implementation)
Any FE tech modDevices are discovered and bridged automatically by FEDA
ZCSMSS (matrix sub-node server)⚠️ No longer maintained: only compatible with the old IEMS and has not kept up with the new API

⚠️ ZCSMSS is discontinued: it no longer adapts to updated versions of IEMS, and therefore does not support the new IEMS. On the new version, use the official test mod IEMS-TestDevices instead, or provide a core yourself following the Developer API.

Installation Steps

  1. Install NeoForge 21.1+
  2. Download the IEMS JAR and put it in the mods folder
  3. (Optional) Add a mod that provides a core (the official test mod IEMS-TestDevices is recommended)
  4. Launch the game

FAQ

Q: Why is there no core block?

A: IEMS is an energy management framework; the core is provided by external mods to avoid duplicated functionality. You can install the official test mod IEMS-TestDevices.

Q: Does ZCSMSS still work?

A: Not recommended. ZCSMSS is no longer maintained and is only compatible with the old IEMS without keeping up with the new API — under the new IEMS it is no longer supported. Use the official test mod IEMS-TestDevices instead, or provide a core yourself following the Developer API.

Q: How do I know whether the core is working?

A: Use /iems status to check grid status, or visit the web panel at http://127.0.0.1:28567/ (token required).

Q: Connections are lost after restarting the save?

A: This was fixed in BUILD.00000110 (chunk unloading mistakenly unregistered the core). Grid data is stored in iems_grid.dat and fully preserved across restarts; if losses still occur, make sure BUILD ≥ 110.

Q: The lasers turned red?

A: Two situations — the grid is shut down (protocol capacity exceeded or manual /iems shutdown), or the connection is islanded (not connected to the core; always red and never powered).

Q: What happens if I teleport away halfway through pulling a wire?

A: A dimension change (portal/cross-dimension TP) retracts the wire immediately with a notification; leaving the world also clears the wire-pulling state.

Q: How do FE devices from other mods get connected?

A: No action needed — FEDA automatically scans and bridges FE devices in range every 20 ticks (cyan laser).

Q: I don't like the cyan bridge laser?

A: Set colorizeAutoConnect = false in config/DLZstudio/IEMS/Renderer.toml and re-enter the world for it to take effect.

Q: I want to adjust the SE-to-FE exchange rate?

A: Change fePerSe in config/DLZstudio/IEMS/Energy.toml (default 10, range 1 ~ 9×10²⁶), then run /iems reload in-game for it to take effect immediately, with no restart needed. Note that changing the rate immediately reinterprets the existing SE values in the grid.

Q: The web panel is unreachable?

A: Check: whether the game has a world loaded, whether enabled is true in APIserve.toml, whether port 28567 is occupied, and the firewall. Remote access requires changing host = "0.0.0.0" and must be accompanied by a new token and a TLS reverse proxy.

Q: How should an external mod write its version range when depending on IEMS?

A: "[0.8.0-beta,)". You must not write "[0.8.0,)" — in semantic comparison 0.8.0-beta < 0.8.0, so the required dependency would be judged unsatisfied and the game would crash on load.

Q: How do I develop my own device?

A: See the Developer API section of this document and refer to the IEMS-TestDevices source (the arc furnace is a complete example with a GUI).


Debug Commands

CommandPermissionDescription
/iems statusnoneGrid status (core/energy/main grid/islands/connections/shutdown reason)
/iems protocolnoneProtocol capacity usage and over-limit state
/iems scannoneForce a BFS rescan and report the result
/iems shutdown2Manually shut down the grid (device add/remove does not auto-recover)
/iems restart2Restore power
/iems reload2Reload all IEMS config files (Energy / APIserve / Renderer)

Changelog

Improvements over the Old IEMS (new 0.8.0-beta / IEMS0930 ← old v0.6.0 ~ v0.8.0-BUILD.00000160)

The new version is a complete rewrite of the old IEMS: from a monolithic implementation where "the block entity is the grid" to an energy management framework with "full logic-presentation separation + factory-based persistence". The main improvements and behavior differences are listed below by dimension (current build BUILD.00000120).

1. Architecture: Full Separation of Logic and Presentation
DimensionOldNew
Where grid logic livesWritten inside BlockEntity, tightly coupled to LevelA separate logic layer (pure POJO) that does not depend on Level
Device identityHard-coded type enumFactory ID + parameters, registrable by external mods
Relations between devicesHold references to each otherInstance autonomy, interacting with the grid only through the dispatcher
Grid operationStops when chunks are unloadedKeeps simulating even without chunk loading
  • ✅ External mods only need to new a logic instance + IEMSAPI.attachOrRegisterDevice(), without extending framework base classes
  • ✅ Instances can be independently created / destroyed / re-parameterized, naturally suited to multi-core parallelism
  • ✅ The device factory mechanism makes "devices that exist even without their block" possible
2. Persistence: From "connections only" to a "complete grid snapshot"
DimensionOldNew
Storage filedata/DLZstudio/IEMS/iems_connections.datdata/iems_grid.dat
Stored contentConnections only (coordinates + type enum)Devices (factory ID + parameters) + core + all connections
Rebuild methodRelies on BEs re-registering one by one, order-sensitiveRebuilt by factories on server startup → restoreState
Chunk unloadUnload means unregister + clean up connectionsUnloading does not unregister devices; connections are fully preserved after a restart
CoverageMain grid connections onlyFull coverage of main grid + islands + bridges
  • ✅ Fixes the old order-sensitivity defect where "a device loads before the core → onLoad() registration has no effect → the grid is forever empty"
  • ✅ Fixes "chunk unload mistakenly unregisters the core → core connections are lost after a restart" (BUILD.00000110)
3. Energy System: From "hard-coded conversion of three units" to "unified SE basis + configurable exchange rate"
DimensionOldNew
Unit systemSE / FE / GE (EnergyValue.EnergyUnit)FE / AE / SE, with SE as the internal settlement basis
Unit conversionHard-coded (1 SE = 1 FE, 1 SE = 10⁸ GE)Configurable rate: fePerSe in Energy.toml (default 10)
Conversion carrierRequires placing an extra "energy converter" blockFE devices are converted automatically by the bridge layer, no converter needed
Settlement tickSE/2 ticks (once every 2 ticks)SE/tick (settled every tick)
Legacy unitGE threaded through the whole codebaseGE removed (along with its display-mode API)
  • ✅ fePerSe supports hot reload (/iems reload), clamps out-of-range values, and falls back to the default for non-numeric values
  • ✅ FE bridge declaration granularity adapts to the "amount delivered in one tick"; under a high exchange rate throughput is no longer crushed down to fePerSe FE/tick
4. External Device Integration: From "requiring adaptation by the other side" to "zero-adaptation automatic bridging"
  • Old: devices from other mods had to implement the IEMS API or extend framework blocks to join the grid
  • New: responsibilities are split across two layers — the Device Discovery System (EDS) handles scanning and identity recognition (discovery only, no bridging), while the adapter layer (EDA) uses FEDA to disguise each device as a node; it rescans any NeoForge FE device in range every 20 ticks (generators / consumers / storage) and establishes a bridge connection automatically on discovery (cyan laser, configurable), with zero changes required in the other mod
  • ✅ This finally unlocked the external FE device interconnection that had never worked before (since BUILD.00000091)
5. Web Panel: From "unauthenticated read-only page on 8080" to "token-authenticated REST API"
DimensionOldNew
Port / binding8080, local page only28567, default 127.0.0.1, remote access can be explicitly enabled
AuthenticationNoneAll /api/* require a token (header or query parameter)
FormFixed page (status + device toggles)REST API: status / devices / connections / topology / metrics / grid/active
Data formatPage reads memory directlyUniform envelope {schema, ts, data}, BigIntegers stringified to prevent precision loss
Time-series dataNoneMetrics ring buffer, can feed an external dashboard
Write operationsDevice power togglesPOST /api/grid/active to toggle the grid
  • ✅ Thread safety: HTTP thread tasks are queued onto the tick thread, eliminating data races with CoreDevice
  • ✅ The thread pool is explicitly stopped on world reload, and the metrics buffer is cleared per session, avoiding thread leaks and cross-save interference
6. Grid Topology: New "main grid / island / bridge" tri-state
  • Old: anything not connected to the core was judged invalid (broadcast towers not connected to the core simply refused connections)
  • New: devices not yet connected to the core are allowed to interconnect first (islands), rendered with a red laser to indicate no power, and powered automatically once the core is in place
  • ✅ BFS reachability determination + topology snapshot (aggregated main grid / island / boundary views)
  • ✅ Core↔device connections turn red rather than disappearing when the device leaves the main grid (core-side exemption filtering)
7. Connection Interaction: From "simple two-point lines" to a "wire-pulling contract with re-validation"
DimensionOldNew
Interaction detectioninstanceof on concrete block classesThe IIemsInteractable contract (decoupled from block type)
Distance feedbackTop text prompt, silently cancelled when too farHUD live distance + maximum distance, automatic retraction when too far (+10 buffer)
Server validationWeak (trusted the client)C2S request + server re-validation (endpoints / same dimension / distance / duplicates / relay rules)
SecurityNoneProximity check + rate limiting (prevents remote arbitrary connections via forged packets)
Leftover stateCould linger across dimension changes / world exitWire retracted immediately on dimension change, forcibly cleared on world exit
8. Laser Rendering: Triple Robustness for Viewing Angle, Distance, and Topology
  • ✅ Billboard width direction (width = beam direction × (camera→beam)) — side views are no longer compressed into a thin line
  • ✅ Screen-space minimum width max(0.03, distance × 0.0015) — distant beams do not thin out and vanish
  • ✅ Back-face culling disabled for double-sided rendering, visible from any angle; depth testing retained (still occluded by blocks)
  • ✅ Degenerate triangles inserted between adjacent strips to eliminate "ghost diagonals"
  • ✅ New colorizeAutoConnect in Renderer.toml: the cyan bridge laser can be toggled off
  • ✅ The ClientGridCache client cache handles all three lists (main grid / islands / bridges), with quadrant statistics and EMA smoothing
9. Concurrency Model: Explicit "tick thread ownership"
  • Old: public APIs read/write grid state directly, with web threads and the game thread accessing concurrently
  • New: grid state is owned exclusively by the server tick thread; external threads all submit through IEMSAPI.runOnServerThread() / callOnServerThread()
  • ✅ GridSyncPayload size validation to prevent oversized packets from causing client OOM
10. Commands and Operations
OldNew
/iems_debug add_connection/iems status grid overview
/iems_debug list_connections/iems protocol protocol capacity
/iems_debug clear_connections/iems scan force a BFS rescan
—/iems shutdown / /iems restart grid on/off (permission 2)
—/iems reload hot reload all config (permission 2)
11. Build and Dependencies
  • ✅ Adopted the DLZstudio BUILDID convention: the only legal build entry points are build.ps1 / build.sh, with the build number embedded in the artifact (the old version used a hand-written build_v3.bat)
  • ✅ GeckoLib 4.8.4 is bundled via Jar-in-Jar, so players do not need to install it separately (the old version listed it as a required external dependency)
  • ✅ The NeoForge dependency range was relaxed from a fixed 21.1.228+ to [21.1.0,)
  • ✅ Config is centralized in config/DLZstudio/IEMS/ (Energy / APIserve / Renderer), auto-generated with comments on first launch
12. Framework Boundary Changes and Behavior Differences (Migration Reference)

The following are behavior changes, not all improvements; be aware of them when upgrading.

  • Block consolidation: the old version shipped relays / broadcast towers / standard storage / general storage / converters / marker blocks; the new framework keeps only the example devices (relay / broadcast tower), leaving cores and storage to external mods (e.g. IEMS-TestDevices; ZCSMSS is no longer maintained and does not follow the new IEMS)
  • Core connection distance: fixed at 1500 blocks in the old version → declared by the core at registration in the new version, with a framework default of 500 blocks when not declared
  • Protocol capacity: defaulted to 1000 in the old version, increased/decreased by the device side via requestProtocolCapacity / releaseProtocolCapacity → declared by the core as protocolLimit in the new version, with the framework performing unified calculation and over-limit detection
  • Line-of-sight occlusion check: old broadcast towers had a "cannot connect if blocked by ≥3 layers of full blocks" rule → the new version uses pure distance determination
  • Time display mode API: old standard / coordinated → removed in the new version, unified as SE/tick
  • API shape: old IEMSApi.getInstance() instance facade + EnergyValue wrapper → new static facade IEMSAPI + raw BigInteger

IEMS0930 (2026-09-30, BUILD.00000114)

Development codename IEMS0930 adopted; this entry corresponds to the latest build of the 0.8.0-beta rewrite mainline.

Fixes (connection persistence):

  • ✅ setRemoved mistakenly unregistering the core device on chunk unload, causing core connections to be lost after a restart — the unload path now marks and skips unregistration, while a block that truly disappears is still unregistered normally
  • ✅ Core-side exemption for island filtering: after disconnecting from the core, the connection is rendered as a red laser instead of simply disappearing (aligned with old semantics)

Fixes (laser rendering):

  • ✅ Degenerate triangles separate adjacent strips, eliminating "ghost diagonals"
  • ✅ A series of rendering robustness fixes: billboard width direction (doesn't vanish from the side), screen-space minimum width (doesn't thin out at a distance), double-sided rendering (prevents a whole beam from disappearing at certain angles), and defense against abnormal cross-dimension connections

Fixes (lighting):

  • ✅ Example devices let skylight pass straight through (propagatesSkylightDown override + documented mechanism), so newly placed devices no longer appear as "completely black models"

New (render config):

  • ✅ colorizeAutoConnect toggle in Renderer.toml: the cyan FE bridge laser can be turned off
  • ✅ Zero-IO lazy cache for render config, effective on re-entering the world

New (energy exchange rate config):

  • ✅ fePerSe rate entry in Energy.toml (default 1 SE = 10 FE, range 1 ~ 9×10²⁶)
  • ✅ /iems reload command: manually reload all config (Energy / APIserve / Renderer) with no game restart needed
  • ✅ FE bridge demand declaration adapts to the "amount delivered in one tick"; under a low exchange rate throughput is no longer crushed down to fePerSe FE/tick
  • ✅ Removed the legacy GE unit from the old version (zero references in the project; the new unit system is FE / AE / SE)

Fixes (WebPanel / thread safety):

  • ✅ Data race between HTTP threads and the tick thread over CoreDevice — external thread tasks are now queued (H-01)
  • ✅ Thread pool leak on world reload (M-01), metrics ring buffer cross-session interference (M-02)
  • ✅ Proximity check + rate limiting for C2S connection requests (H-02), GridSyncPayload size validation to prevent client OOM (M-03)
  • ✅ No more bridges created when FEDA silently skips registration under overlapping multi-host radii (M-04)
  • ✅ Leftover wire-pulling state across dimensions / on world exit (M-06)

0.8.0-beta Rewrite Mainline (2026-08 ~ 2026-09)

  • M1-M4 Grid kernel: device registration, BFS topology, protocol capacity, energy dispatch
  • M5-M7 Network sync and laser rendering: full snapshot sync, island/bridge rendering, quadrant statistics
  • M8/M8.1 Wire-pulling interaction: the IIemsInteractable contract, C2S requests, and server re-validation
  • M9 simulation-style device factory persistence; keeps running after a restart without chunk loading
  • M10 WebPanel JDK HttpServer panel (port 28567, token authentication, metrics ring buffer)
  • M11 review fixes minimized fixes for the H/M/L series of potential issue reports + render config
  • External FE bridging (FEDA) working for the first time: IEMS and NeoForge FE devices successfully interconnected (since BUILD.00000091)

Acknowledgments

  • The GeckoLib team — an excellent 3D model rendering library (distributed via Jar-in-Jar)
  • The NeoForge team — a powerful mod loader
  • 北山_Besson — provided some device models
  • [EI] 终末地工业 (Endfield Industries) — source of reference for some models

License

MIT License

This mod is open source; contributions and derivative works are welcome!

The bundled GeckoLib 4.8.4 is likewise distributed under the MIT License; its notice can be found in the LICENSE file inside the nested JAR.


等离子工作室 (DLZstudio) © 2026 · Development codename IEMS0930

Частые вопросы

Как установить IEMS?

Установите NeoForge под свою версию Minecraft, скачайте IEMS под ту же версию и загрузчик, положите файл в папку mods и запустите игру с профилем загрузчика.

Для каких версий Minecraft есть IEMS?

У IEMS есть сборки для Minecraft 1.21.1.

Нужен ли IEMS на сервере?

Нужен и в игре, и на сервере

Лицензия и источник
MIT Licenseможно свободно использовать и распространять с указанием автора
Оригинал — Modrinth↗Файлы — без изменений, проверены по SHA-512Это ваш мод? Правообладателям

Сайт использует cookie: необходимые — для входа и темы, а также счётчики посещений Яндекс Метрика и LiveInternet — по ним мы видим, как пользуются сайтом. Рекламных cookie у нас нет. Подробнее