-
Notifications
You must be signed in to change notification settings - Fork 2
Grid Status Mechanism_EN
Grid status calculation relies on fixed-interval energy sampling. The MTE (Wireless Energy Monitor) and HUD (Portable Monitor) use synchronized sampling parameters:
- Detection interval: 100 ticks (5 s), synchronized between MTE and HUD
- Window duration: 300 seconds
- Sample count: 61 samples (1 initial sample + 60 interval samples)
-
Dataset:
EUDataSet, fixed capacity 61, FIFO aging - Rolling window: when a new sample is pushed and the dataset is full, the oldest sample is removed, maintaining a rolling 300 s window
Design note: The fixed capacity of 61 plus FIFO aging ensures the window always covers the most recent 300 seconds, regardless of how long the grid has been running, with constant memory usage.
The slope (EU/t) calculation uses BigDecimal exact division to avoid floating-point loss:
-
Precision: 6 decimal places,
RoundingMode.HALF_UP - Purpose: avoids precision loss in double arithmetic for large EU values (up to 1018)
- Operation: (newest.value - oldest.value) / (newest.tick - oldest.tick) is performed entirely with BigDecimal
Precision choice: 6 decimal places is more than sufficient for EU/t display and redstone decisions, and the BigDecimal overhead is negligible at a 100-tick interval.
EU/t calculation is split into two phases, switched by the current dataset size:
| Phase | Trigger | Formula |
|---|---|---|
| Cold start | Dataset size < 61 | (newest - oldest) / ((size - 1) × 100t) |
| Steady state | Dataset size == 61 | (newest - oldest) / 6000t |
Mathematical equivalence: When size == 61, (size - 1) × 100t = 60 × 100t = 6000t, so the two formulas are essentially equivalent, unified as
(newest.value - oldest.value) / (newest.tick - oldest.tick). The cold-start formula allows a usable EU/t estimate even when fewer than 61 samples are available.
When the grid is in a special state, the EU/t display line is replaced with status text:
| Trigger | Display Text | Color |
|---|---|---|
| |eut| < 1 | 0 (<1EU) | Gray |
| eut == 0 (all values equal) | 0 (Silent) | Gray |
| Silent ≥ 300 s | 0 (Long-Silent) | Dark gray |
| MTE reload delay | Reload in progress, redstone logic held | Red |
| HUD cold start (size < 2) | Network status: Calculating... | Cyan title + orange value |
When the grid remains silent (all sampled values identical) for 300 seconds (6000 ticks), the long-silent mechanism is triggered:
- Grid silent (all sampled values identical) for ≥ 300 seconds (6000 ticks)
- Status label switches from "Silent" to "Long-Silent"
- Dataset is compressed to 2 data points (first and last), saving memory
- On the next sample, if the value differs, the last point is retained as the new dataset start (size=2, eut can be computed immediately)
- If the value is still the same, only the last point's tick is updated
- The
longTermSilentflag is persisted to NBT (MTE) / memory (HUD) - v1.3.2 fix: retaining the last point avoids size=1 triggering a "Calculating..." loop
v1.3.2 fix note: Previously, when the first differing sample arrived after long-silent, the dataset could be reset to size=1, triggering a "Calculating..." display loop. After the fix, the last point is retained so size=2 and the slope can be computed immediately.
Grid reloads (chunk reload, server restart, etc.) are handled differently based on reload duration:
| Reload Type | Criterion | Handling |
|---|---|---|
| Short reload | ≤ 10 s | Dataset retained, calculation continues directly (≤ 3.3% slope error, acceptable) |
| Long reload | > 10 s | Dataset cleared, cold start triggered |
-
MTE long reload: enables a 30-second redstone buffer (
redstoneReloadDelay = 600t) to maintain redstone output - Gap detection: when gap > 200L (200 ticks) the dataset is cleared
Source of the 3.3% error: A short reload loses at most 10 seconds (100 ticks) of data, which is about 1.67% of the 300-second (6000-tick) window; the upper bound on slope error is about 3.3%, which is acceptable, so the dataset is not cleared on short reloads.
Portable devices (HUD) handle the dataset differently from MTE, because the portable dataset is not persisted across saves:
- Not persisted: the portable device dataset is not persisted across saves
- Reset timing: the dataset is reset when the player rejoins/exits
-
Real-time gap detection: uses
System.currentTimeMillis(), threshold 10000 ms (10 s) -
Reason:
getTotalWorldTime()does not advance while the player is offline, so world time cannot detect the exit
Design note: The MTE lives in the world, where world time keeps advancing, so tick gap can detect reloads; the HUD follows the player, and world time no longer advances for that player after they exit, so real time must be used to detect whether the player has left the game.
The system computes both EU/t values for different scenarios:
| Type | Method | Characteristics |
|---|---|---|
| Realtime EU/t | calculateRecentEUT(), slope of the latest 2 samples | Fast response but noisy |
| Average EU/t | calculateEUT(), slope of first and last points (300 s window) | Smooth but delayed |
- GUI display: both are shown in the GUI (realtime status line + average status line)
- HUD display: the HUD also shows both lines (realtime EU/t line + average EU/t line)
Use cases: Realtime EU/t is suitable for observing short-term fluctuations (e.g. machine start/stop); average EU/t is suitable for assessing long-term trends (e.g. overall grid balance). Redstone modes 1/2 can be anchored to either the average or realtime EU/t.