The complexity of industrial automation games has long surpassed the limits of human mental calculation. When your Minecraft GregTech production line involves 40+ multiblock machines, cross-dimensional fluid supply, multiple energy hatch parallels, and directed overclocking, any spreadsheet or dedicated calculator collapses under the following dilemmas:
Hardcoded Hell — Existing tools are deeply tied to specific mod versions, unable to adapt to custom modpacks or cross-game scenarios.
Contextual Ambiguity — The same resource (like water) is consumed per-cycle as a recipe ingredient, yet consumed per-tick as a coolant in machine bases. Traditional single-dimensional data models cannot express this orthogonal relationship between nature and usage.
Computational Bottleneck — Manual enumeration or iterative approximation either diverges or yields unacceptable precision when facing multi-objective coupling such as nonlinear overclocking, probabilistic byproducts, and global bus sharing.
OmniFlow combines simplex matrix solving from operations research with the node graph paradigm of industrial control consoles, providing a WYSIWYG, game-agnostic, math-driven industrial production line scheduling engine.
OmniFlow's foundation contains no hardcoded game logic. The system maps all physical entities through a configurable Global Resource Registry (powered by Zustand). Switching from Minecraft to Factorio or Dyson Sphere Program only requires changing the resource configuration — the core solving pipeline needs zero code modification.
Resource Registry → Category: 'gt:eu' | DisplayName: 'Greg Power' | Unit: 'EU/t' | Routing: global
→ Category: 'item' | DisplayName: 'Item' | Unit: 'pcs' | Routing: wired
→ Category: 'fluid' | DisplayName: 'Fluid' | Unit: 'mB' | Routing: wired
This is OmniFlow's core data modeling breakthrough:
| Dimension | Storage Location | Description |
|---|---|---|
| Nature | ResourceRegistry global dictionary |
Physical identity of matter: water, EU power, iron ingots; UI color and base unit |
| Context | Machine Archetype's fixed_utilities and recipe port's measure_mode |
How this resource is measured in the current business flow: per-cycle (per_cycle), per-tick (rate_per_tick), per-second (rate_per_sec), and whether it's a read-only catalyst (consumable: false) |
This design completely solves the industry modeling pain point of "the same water being both a recipe ingredient and a coolant" — the material nature is defined once, while usage semantics attach to the machine base and recipe slots, orthogonally decoupled.
The frontend handles all business logic (overclock cascading, parallelism, threshold judgment, probabilistic output). Before the request reaches the backend, a Pre-compilation Pipeline normalizes all discrete cycle amounts and continuous rate amounts into pure Rate/s (per-second rate). The backend only needs to solve a standard form linear programming problem with scipy.optimize.linprog:
minimize c^T x
subject to A_ub x ≤ b_ub
A_eq x = b_eq
x ≥ 0
The backend is stateless, mod-agnostic, receiving only normalized vectors and matrices, returning optimal solutions within 30ms.
Thoroughly separates inherent machine properties (energy type, cooling medium, routing lock) from recipe I/O:
// gtElectric.ts — GregTech Electric Machine Archetype
{
id: 'gt_electric',
fixed_utilities: {
'gt:eu': {
type: 'gt:eu',
routing_mode: 'global', // Power goes through global bus, no manual wiring
routing_locked: true, // User cannot change routing type
measure_mode: 'rate_per_tick' // EU consumed per tick
}
},
default_modifiers: ['gt_overclocker'] // Activate overclocker modifier by default
}Fixed utilities reference the ResourceRegistry via foreign keys, enabling dynamic suffix splicing (e.g., EU/t, mB/s) and visual noise reduction (globally-routed ports auto-hide connection lines) in the UI.
Abandons tedious full-manual wiring, supporting two routing paradigms:
| Routing Mode | Semantics | Example |
|---|---|---|
wired |
Must establish physical topology connections | Items, fluid pipes |
global |
Global implicit shared network | Power bus (gt:eu), Stress network (create:su) |
When building topological networks, the calculation engine automatically generates virtual source nodes (Virtual_Global_Source) and virtual sink nodes (Virtual_Global_Target) for global routed resources, eliminating the need for manual power input nodes and drastically reducing canvas complexity.
Implements strict multi-stage modifier scope isolation, perfectly compatible with cross-mod hybrid energy machines:
Phase 1: Collect Effects — Iterate activated modifiers, gather their ModifierEffects
Phase 2: Parallel — Lossless parallel first: uniformly multiply by parallelMultiplier
Phase 3: Targeted Overclock — Targeted exponential overclock: only matching utility_type gets multiplied
Example: Hybrid machine consuming both gt:eu and create:su
• gt:eu gets overclock-multiplied (×4^n)
• create:su remains unaffected by overclock
Phase 4: Output Probability — Probabilistic output (e.g., 5% byproduct chance)
Phase 5: Duration & Rate — Normalize to Rate/s
For GregTech multiblocks, the gt_overclocker modifier strictly executes:
- Calculate total input EU/t based on energy hatch configuration
- Lossless parallel =
min(floor(total_eu / recipe_eu), parallelLimit) - If remaining power is sufficient, execute overclocking (voltage ×4, perfect overclock duration ÷4, normal overclock ÷2)
The global resource category registry uses Zustand for fine-grained subscription. React components only re-render when the specific resource category they reference changes, avoiding the full-update disaster of React Context. Combined with React Flow's built-in useNodesState / useEdgesState for canvas state management, it ensures smooth 60fps dragging experience.
Full data normalization pipeline executed before every request:
normalizeCanvasNode— Compatible with legacy field migration (is_virtual→is_auto), fill default modeensureRecipeDataShape— Apply Archetype, filter incompatible modifiers, fill default UI statebuildTopologicalNets— Build topological networks, separate wired/global edges, generate implicit routinggetCalculatedRates— Execute modifier pipeline, normalize all resources to Rate/s
┌─────────────────────────────────────────────────┐
│ React Flow Canvas │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Source │───▶│ Recipe │───▶│ Target │ │
│ │ water ∞ │ │ Electrolyzer│ │ H₂ 1.0 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │
│ Physical Wires Global Bus (gt:eu) │
└───────┼───────────────┼───────────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────┐
│ Pre-compilation Pipeline │
│ normalizeCanvasNode → ensureRecipeDataShape │
│ → buildTopologicalNets → getCalculatedRates │
│ │
│ All amounts → Rate/s (pure float vector) │
└──────────────────────┬──────────────────────────┘
│ POST /api/calculate
▼
┌─────────────────────────────────────────────────┐
│ FastAPI + SciPy LP Solver │
│ │
│ Pydantic validation → Node classification │
│ → Stoichiometric matrix A construction │
│ → Constraints c, bounds construction │
│ → scipy.optimize.linprog (highs method) │
│ → Result aggregation & rounding │
└──────────────────────┬──────────────────────────┘
│ Results
▼
┌─────────────────────────────────────────────────┐
│ Result Mapping & UI Update │
│ │
│ machines_exact / machines_actual / utilization │
│ actual_amounts per node / per port │
│ system_inputs / system_outputs summary │
│ total_eu_tick │
└─────────────────────────────────────────────────┘
Variable vector: x = [x_recipes | x_sources | x_sinks]
Stoichiometric matrix: Columns = Recipes, Rows = Items. Outputs positive, inputs negative.
Objective modes:
| Target Mode | Objective Coefficient | Constraint |
|---|---|---|
demand |
c = 0 |
b_eq = amount (exact demand) |
maximize |
c = -10000 |
b_ub ≥ 0 (strong maximization) |
overflow |
c = 0.001 |
b_eq = 0 (overflow discharge) |
Constraints: Ax >= b for non-target items (allow byproduct overflow). Target items enforce strict mass conservation.
- Node.js >= 18
- Python >= 3.10
# Install dependencies
npm install
# Start dev server (http://localhost:5173)
npm run dev
# Type-check & build
npm run build
# Lint
npm run lint
# Preview production build
npm run previewcd backend
# Create & activate virtual environment (Windows)
python -m venv venv
venv\Scripts\activate
# Install dependencies
pip install fastapi uvicorn numpy scipy pydantic
# Start backend (http://localhost:8000)
uvicorn main:app --reloadAPI docs available at http://localhost:8000/docs (Swagger UI).
Canvas state is persisted to localStorage under key omniflow.canvas.v1. Export/import as .json files is supported via the file I/O controls.
OmniFlow/
├── src/
│ ├── App.tsx # Root — React Flow canvas
│ ├── main.tsx # Entry point
│ ├── index.css # Dark industrial global styles (pure CSS)
│ ├── flowConfig.ts # Node type registration (recipeNode / sourceNode / targetNode)
│ ├── components/ # React UI components
│ │ ├── RecipeNode.tsx # Polymorphic recipe node (gregtech / vanilla / enderio)
│ │ ├── SourceNode.tsx # Input source node
│ │ ├── TargetNode.tsx # Output target node
│ │ ├── RecipeEditorModal.tsx # Recipe editor modal
│ │ ├── EndpointEditorModal.tsx # Endpoint editor modal
│ │ ├── SystemHUD.tsx # System status heads-up display
│ │ ├── MenuBar.tsx # Top menu bar
│ │ └── SegmentedControl.tsx # Segmented control primitive
│ ├── hooks/ # Custom React hooks
│ │ ├── useCanvasState.ts # Nodes/edges state (React Flow)
│ │ ├── useCanvasOperations.ts # Add / delete / connect operations
│ │ ├── useCalculation.ts # Pre-compile → POST → result mapping pipeline
│ │ ├── useClipboard.ts # Copy / paste / duplicate
│ │ ├── useFileIO.ts # File import / export + localStorage
│ │ ├── useKeyboardShortcuts.ts # Global keyboard shortcuts
│ │ ├── useNodeEditor.ts # Node editing modal state
│ │ ├── useNodeOperations.ts # Auto-fill endpoints, node data updates
│ │ ├── useUndoRedo.ts # Snapshot-based undo / redo (max 20)
│ │ └── useTheme.ts # Dark / light theme toggle
│ ├── domain/canvas/
│ │ ├── initialState.ts # Demo canvas (GregTech steel line)
│ │ └── validators.ts # Data normalization & migration
│ ├── modifiers/ # Modifier engine
│ │ ├── calculate.ts # Core 5-phase modifier pipeline + rate normalization
│ │ ├── gtOverclocker.ts # GT overclock logic
│ │ ├── chanceOutput.ts # Probabilistic output modifier
│ │ ├── registry.ts # Modifier registry (ID → IMachineModifier)
│ │ ├── state.ts # Default UI state factory
│ │ ├── types.ts # IMachineModifier & ModifierEffect interfaces
│ │ └── index.ts # Barrel export
│ ├── data/archetypes/ # Machine archetype definitions
│ │ ├── index.ts # Registry + applyArchetypeToInputs
│ │ ├── gtElectric.ts # GT electric (fixed gt:eu utility + global routing)
│ │ ├── fluidNetworked.ts # Fluid-cooled (utility:water per second)
│ │ ├── customGeneric.ts # Blank archetype
│ │ └── shared.ts # Utility amount derivation helpers
│ ├── registry/ # Global resource category registry
│ │ ├── resourceRegistry.ts # Zustand store (categories CRUD + localStorage)
│ │ ├── defaults.ts # Built-in categories (item / fluid / energy / gt:eu / create:su …)
│ │ ├── types.ts # ResourceCategoryDef type
│ │ ├── units.ts # Unit definitions
│ │ └── index.ts # Barrel export
│ ├── types/
│ │ ├── recipe.ts # RecipeNodeData / SourceNodeData / TargetNodeData
│ │ ├── api.ts # CalculateResponse type
│ │ └── types.ts # Resource / MachineArchetype / UtilityDef / RoutingMode
│ └── utils/
│ └── topologicalNets.ts # Topological network analysis + global routing
├── backend/
│ └── main.py # FastAPI app + Pydantic models + SciPy LP solver
├── public/ # Static assets
├── vite.config.ts
├── tsconfig.json # TypeScript project references root
├── tsconfig.app.json # Frontend TS config
├── tsconfig.node.json # Node-side TS config (vite.config)
├── eslint.config.js # ESLint 10 flat config
└── package.json
GPL-3.0 license