From 2996b3fc8da009c4dca99b585414458d6b50cf12 Mon Sep 17 00:00:00 2001
From: Gate Guardian <xtzcy76040108@163.com>
Date: Thu, 8 Aug 2024 20:14:30 +0800
Subject: [PATCH 1/4] refactor backfiller

---
 .../epimorphism/common/data/EPMachines.java   |  19 ++-
 .../common/data/EPRecipeTypes.java            |   6 +
 .../electric/ConcreteBackfillerMachine.java   | 133 ++++++------------
 .../trait/ConcreteBackfillerLogic.java        | 116 ++++++++++-----
 .../misc/ConcreteBackfillerRecipes.java       |  23 +++
 .../epimorphism/utils/EPMath.java             |  16 +++
 .../epimorphism/utils/EPUtil.java             |  13 ++
 7 files changed, 186 insertions(+), 140 deletions(-)
 create mode 100644 src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java
 create mode 100644 src/main/java/com/epimorphismmc/epimorphism/utils/EPMath.java

diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java
index 08bf6db..e95556b 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java
@@ -116,6 +116,7 @@
 import static com.epimorphismmc.epimorphism.EpimorphismCommon.registrate;
 import static com.epimorphismmc.epimorphism.api.pattern.EPPredicates.direction;
 import static com.epimorphismmc.epimorphism.common.block.BlockMaps.*;
+import static com.epimorphismmc.epimorphism.common.data.EPRecipeTypes.*;
 import static com.epimorphismmc.monomorphism.block.MOBlockMaps.ALL_COIL_BLOCKS;
 import static com.epimorphismmc.monomorphism.block.MOBlockMaps.ALL_MACHINE_CASINGS;
 import static com.epimorphismmc.monomorphism.pattern.MOPredicates.*;
@@ -2220,7 +2221,7 @@ public class EPMachines {
                                     ((int) Math.pow(2, tier - 1)) * 16 + 1,
                                     ((int) Math.pow(2, tier - 1)) * 16 + 1))
                     .rotationState(RotationState.NON_Y_AXIS)
-                    .recipeType(DUMMY_RECIPES)
+                    .recipeType(CONCRETE_BACKFILLER_RECIPES)
                     .appearanceBlock(() -> ConcreteBackfillerMachine.getCasingState(tier))
                     .pattern(definition -> FactoryBlockPattern.start()
                             .aisle("XXX", "#F#", "#F#", "#F#", "###", "###", "###")
@@ -2307,19 +2308,18 @@ public class EPMachines {
                                 Collectors.toMap(entry -> entry.getKey().tier(), Map.Entry::getValue, (a, b) -> a));
                 TreeMap<Integer, Supplier<Block>> glasses = new TreeMap<>(glass);
                 for (int i = 0; i < fluidCells.size(); i++) {
-                    var info = builder
-                            .aisle("CCCCC", "CEEEC", "CEEEC", "CEEEC", "CCCCC")
-                            .where('C', glasses.ceilingEntry(i + 3).getValue())
-                            .where('E', fluidCells.get(i))
-                            .shallowCopy()
+                    var info = builder.aisle("CCCCC", "CEEEC", "CEEEC", "CEEEC", "CCCCC");
+                    var entry = glasses.ceilingEntry(i + 3);
+                    if (entry != null) {
+                        info.where('C', entry.getValue()).where('E', fluidCells.get(i));
+                    }
+                    shapeInfo.add(info.shallowCopy()
                             .aisle("AAAAA", "AGGGA", "AGGGA", "AGGGA", "AAAAA")
                             .aisle("DDDDD", "D   D", "D   D", "D   D", "DDDDD")
-                            .build();
-                    shapeInfo.add(info);
+                            .build());
                 }
                 return shapeInfo;
             })
-            .partSorter(Comparator.comparingInt(a -> a.self().getPos().getY()))
             .sidedWorkableCasingRenderer(
                     "block/casings/yotta_fluid_tank_casing",
                     Epimorphism.id("block/multiblock/yotta_fluid_tank"),
@@ -2359,7 +2359,6 @@ public class EPMachines {
                     .build())
             .shapeInfos(definition -> new ArrayList<>(StructureUtil.getMatchingShapes(
                     (MOBlockPattern) definition.getPatternFactory().get(), ALL_FIELD_BLOCKS.size())))
-            .partSorter(Comparator.comparingInt(a -> a.self().getPos().getY()))
             .workableCasingRenderer(
                     Epimorphism.id("block/casings/solid/tfft_casing"),
                     Epimorphism.id("block/multiblock/tfft"),
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipeTypes.java b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipeTypes.java
index 2b8c666..b3ab81d 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipeTypes.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipeTypes.java
@@ -237,6 +237,12 @@ public class EPRecipeTypes {
             })
             .setSound(GTSoundEntries.FURNACE);
 
+    public static final GTRecipeType CONCRETE_BACKFILLER_RECIPES = register(
+                    "concrete_backfiller", MULTIBLOCK)
+            .setMaxIOSize(0, 1, 1, 0)
+            .setEUIO(IO.IN)
+            .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW, LEFT_TO_RIGHT);
+
     //  Universal Processing Plant Recipemaps (Fake Recipemap)
     public static final GTRecipeType GENERAL_RECIPES_A = registerGeneralRecipeType(
                     "general_recipes_a", MULTIBLOCK, RECIPE_MAP[0], RECIPE_MAP[1], RECIPE_MAP[2])
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/machine/multiblock/electric/ConcreteBackfillerMachine.java b/src/main/java/com/epimorphismmc/epimorphism/common/machine/multiblock/electric/ConcreteBackfillerMachine.java
index 85fa9d2..e731653 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/machine/multiblock/electric/ConcreteBackfillerMachine.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/machine/multiblock/electric/ConcreteBackfillerMachine.java
@@ -3,28 +3,17 @@
 import com.epimorphismmc.epimorphism.common.machine.trait.ConcreteBackfillerLogic;
 
 import com.gregtechceu.gtceu.api.GTValues;
-import com.gregtechceu.gtceu.api.capability.IEnergyContainer;
-import com.gregtechceu.gtceu.api.capability.recipe.EURecipeCapability;
-import com.gregtechceu.gtceu.api.capability.recipe.FluidRecipeCapability;
-import com.gregtechceu.gtceu.api.capability.recipe.IO;
 import com.gregtechceu.gtceu.api.data.chemical.material.Material;
 import com.gregtechceu.gtceu.api.machine.IMachineBlockEntity;
-import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMultiPart;
+import com.gregtechceu.gtceu.api.machine.feature.IDataInfoProvider;
 import com.gregtechceu.gtceu.api.machine.multiblock.MultiblockDisplayText;
 import com.gregtechceu.gtceu.api.machine.multiblock.WorkableElectricMultiblockMachine;
-import com.gregtechceu.gtceu.api.machine.multiblock.WorkableMultiblockMachine;
 import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic;
-import com.gregtechceu.gtceu.api.misc.EnergyContainerList;
 import com.gregtechceu.gtceu.common.data.GTBlocks;
 import com.gregtechceu.gtceu.common.data.GTMaterials;
-import com.gregtechceu.gtceu.utils.GTTransferUtils;
+import com.gregtechceu.gtceu.common.item.PortableScannerBehavior;
 import com.gregtechceu.gtceu.utils.GTUtil;
 
-import com.lowdragmc.lowdraglib.misc.FluidTransferList;
-import com.lowdragmc.lowdraglib.side.fluid.FluidStack;
-import com.lowdragmc.lowdraglib.side.fluid.IFluidTransfer;
-import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder;
-
 import net.minecraft.ChatFormatting;
 import net.minecraft.MethodsReturnNonnullByDefault;
 import net.minecraft.core.Direction;
@@ -35,32 +24,24 @@
 import net.minecraft.world.level.block.Block;
 import net.minecraft.world.phys.BlockHitResult;
 
-import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
 import lombok.Getter;
-import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
 import javax.annotation.ParametersAreNonnullByDefault;
 
 @ParametersAreNonnullByDefault
 @MethodsReturnNonnullByDefault
-public class ConcreteBackfillerMachine extends WorkableElectricMultiblockMachine {
-
-    public static final ManagedFieldHolder MANAGED_FIELD_HOLDER = new ManagedFieldHolder(
-            ConcreteBackfillerMachine.class, WorkableMultiblockMachine.MANAGED_FIELD_HOLDER);
+public class ConcreteBackfillerMachine extends WorkableElectricMultiblockMachine
+        implements IDataInfoProvider {
 
     public static final int CHUNK_LENGTH = 16;
 
     @Getter
     private final int tier;
 
-    @Nullable protected EnergyContainerList energyContainer;
-
-    @Nullable protected FluidTransferList inputFluidInventory;
-
     public ConcreteBackfillerMachine(
             IMachineBlockEntity holder, int tier, int speed, int maximumChunkDiameter) {
         super(holder, speed, maximumChunkDiameter);
@@ -72,18 +53,13 @@ public ConcreteBackfillerMachine(
     //////////////////////////////////////
 
     @Override
-    protected RecipeLogic createRecipeLogic(Object... args) {
-        if (args[args.length - 2] instanceof Integer speed
-                && args[args.length - 1] instanceof Integer maxRadius) {
-            return new ConcreteBackfillerLogic(this, speed, maxRadius * CHUNK_LENGTH / 2);
-        } else {
-            throw new IllegalArgumentException("ConcreteBackfiller need args [speed, maxRadius]");
-        }
-    }
-
-    @Override
-    public ConcreteBackfillerLogic getRecipeLogic() {
-        return (ConcreteBackfillerLogic) super.getRecipeLogic();
+    public void onStructureFormed() {
+        super.onStructureFormed();
+        getRecipeLogic().setVoltageTier(GTUtil.getTierByVoltage(energyContainer.getInputVoltage()));
+        getRecipeLogic()
+                .setOverclockAmount(Math.max(
+                        1, GTUtil.getTierByVoltage(this.energyContainer.getInputVoltage()) - this.tier));
+        getRecipeLogic().initPos();
     }
 
     //////////////////////////////////////
@@ -100,51 +76,38 @@ public static Block getCasingState(int tier) {
     }
 
     @Override
-    public long getMaxVoltage() {
-        return GTValues.V[getEnergyTier()];
+    public List<Component> getDataInfo(PortableScannerBehavior.DisplayMode mode) {
+        if (mode == PortableScannerBehavior.DisplayMode.SHOW_ALL
+                || mode == PortableScannerBehavior.DisplayMode.SHOW_MACHINE_INFO) {
+            int workingArea = getRecipeLogic().getCurrentRadius() * 2 + 1;
+            return Collections.singletonList(
+                    Component.translatable("gtceu.universal.tooltip.working_area", workingArea, workingArea));
+        }
+        return new ArrayList<>();
     }
 
     //////////////////////////////////////
     // ******        Logic       ****** //
     //////////////////////////////////////
-    @Override
-    public void onStructureFormed() {
-        super.onStructureFormed();
-        initializeAbilities();
-    }
 
-    private void initializeAbilities() {
-        List<IEnergyContainer> energyContainers = new ArrayList<>();
-        List<IFluidTransfer> fluidTanks = new ArrayList<>();
-        Map<Long, IO> ioMap =
-                getMultiblockState().getMatchContext().getOrCreate("ioMap", Long2ObjectMaps::emptyMap);
-        for (IMultiPart part : getParts()) {
-            IO io = ioMap.getOrDefault(part.self().getPos().asLong(), IO.BOTH);
-            if (io == IO.NONE) continue;
-            for (var handler : part.getRecipeHandlers()) {
-                if (io != IO.BOTH && handler.getHandlerIO() != IO.BOTH && io != handler.getHandlerIO())
-                    continue;
-                var handlerIO = io == IO.BOTH ? handler.getHandlerIO() : io;
-                if (handlerIO == IO.IN
-                        && handler.getCapability() == EURecipeCapability.CAP
-                        && handler instanceof IEnergyContainer container) {
-                    energyContainers.add(container);
-                } else if (handlerIO == IO.IN
-                        && handler.getCapability() == FluidRecipeCapability.CAP
-                        && handler instanceof IFluidTransfer fluidTransfer) {
-                    fluidTanks.add(fluidTransfer);
-                }
-            }
+    @Override
+    protected RecipeLogic createRecipeLogic(Object... args) {
+        if (args[args.length - 2] instanceof Integer speed
+                && args[args.length - 1] instanceof Integer maxRadius) {
+            return new ConcreteBackfillerLogic(this, speed, maxRadius * CHUNK_LENGTH / 2);
+        } else {
+            throw new IllegalArgumentException("ConcreteBackfiller need args [speed, maxRadius]");
         }
+    }
 
-        this.energyContainer = new EnergyContainerList(energyContainers);
-        this.inputFluidInventory = new FluidTransferList(fluidTanks);
+    @Override
+    public ConcreteBackfillerLogic getRecipeLogic() {
+        return (ConcreteBackfillerLogic) super.getRecipeLogic();
+    }
 
-        getRecipeLogic().setVoltageTier(GTUtil.getTierByVoltage(energyContainer.getInputVoltage()));
-        getRecipeLogic()
-                .setOverclockAmount(Math.max(
-                        1, GTUtil.getTierByVoltage(this.energyContainer.getInputVoltage()) - this.tier));
-        getRecipeLogic().initPos(getRecipeLogic().getCenterPos(), getRecipeLogic().getCurrentRadius());
+    @Override
+    public long getMaxVoltage() {
+        return GTValues.V[getEnergyTier()];
     }
 
     public int getEnergyTier() {
@@ -154,10 +117,6 @@ public int getEnergyTier() {
                 Math.max(this.tier, GTUtil.getFloorTierByVoltage(energyContainer.getInputVoltage())));
     }
 
-    public boolean drainInput(boolean simulate) {
-        return drainEnergy(simulate) && drainFluid(getRecipeLogic().getOverclockAmount(), simulate);
-    }
-
     public boolean drainEnergy(boolean simulate) {
         if (energyContainer != null && energyContainer.getEnergyStored() > 0) {
             long energyToDrain = GTValues.VA[getEnergyTier()];
@@ -175,23 +134,11 @@ public boolean drainEnergy(boolean simulate) {
         }
     }
 
-    public boolean drainFluid(int times, boolean simulate) {
-        if (inputFluidInventory != null && inputFluidInventory.transfers.length > 0) {
-            FluidStack concreteFluid = GTMaterials.Concrete.getFluid(times * 144L);
-            FluidStack fluidStack = inputFluidInventory.getFluidInTank(0);
-            if (!fluidStack.isEmpty()
-                    && fluidStack.isFluidEqual(concreteFluid)
-                    && fluidStack.getAmount() >= concreteFluid.getAmount()) {
-                if (!simulate) {
-                    GTTransferUtils.drainFluidAccountNotifiableList(
-                            inputFluidInventory, concreteFluid, false);
-                }
-                return true;
-            } else {
-                return false;
-            }
-        } else {
-            return false;
+    @Override
+    public void setWorkingEnabled(boolean isWorkingAllowed) {
+        super.setWorkingEnabled(isWorkingAllowed);
+        if (getRecipeLogic().isDone()) {
+            getRecipeLogic().resetArea();
         }
     }
 
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/machine/trait/ConcreteBackfillerLogic.java b/src/main/java/com/epimorphismmc/epimorphism/common/machine/trait/ConcreteBackfillerLogic.java
index 280866e..29e9a5a 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/machine/trait/ConcreteBackfillerLogic.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/machine/trait/ConcreteBackfillerLogic.java
@@ -2,26 +2,36 @@
 
 import com.epimorphismmc.epimorphism.common.data.EPTags;
 import com.epimorphismmc.epimorphism.common.machine.multiblock.electric.ConcreteBackfillerMachine;
+import com.epimorphismmc.epimorphism.utils.EPUtil;
 
+import com.gregtechceu.gtceu.api.capability.recipe.IO;
 import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic;
+import com.gregtechceu.gtceu.api.recipe.GTRecipe;
+import com.gregtechceu.gtceu.api.recipe.RecipeHelper;
+import com.gregtechceu.gtceu.api.recipe.modifier.ParallelLogic;
 import com.gregtechceu.gtceu.common.block.SurfaceRockBlock;
-import com.gregtechceu.gtceu.common.data.GTBlocks;
 
 import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted;
 import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder;
 
+import net.minecraft.MethodsReturnNonnullByDefault;
 import net.minecraft.core.BlockPos;
 import net.minecraft.server.level.ServerLevel;
-import net.minecraft.world.level.Level;
+import net.minecraft.world.item.BlockItem;
 import net.minecraft.world.level.block.state.BlockState;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.jetbrains.annotations.NotNull;
 
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.Objects;
 
+import javax.annotation.Nullable;
+import javax.annotation.ParametersAreNonnullByDefault;
+
+@ParametersAreNonnullByDefault
+@MethodsReturnNonnullByDefault
 public class ConcreteBackfillerLogic extends RecipeLogic {
 
     public static final ManagedFieldHolder MANAGED_FIELD_HOLDER =
@@ -108,7 +118,6 @@ public ConcreteBackfillerLogic(ConcreteBackfillerMachine machine, int speed, int
         this.duration = speed;
         this.maximumRadius = maximumRadius;
         this.currentRadius = maximumRadius;
-        this.isDone = false;
     }
 
     @Override
@@ -127,6 +136,15 @@ public void resetRecipeLogic() {
     public void serverTick() {
         // main logic
         if (!isSuspend() && filler.getLevel() instanceof ServerLevel level && checkCanFill()) {
+
+            var matches = searchRecipe();
+            while (matches != null && matches.hasNext()) {
+                GTRecipe match = matches.next();
+                if (match == null) continue;
+
+                int parallel = ParallelLogic.getMaxRecipeMultiplier(match, filler, getOverclockAmount());
+            }
+
             // checkCanFill already check energy, needn't simulate
             filler.drainEnergy(false);
             setStatus(Status.WORKING);
@@ -166,6 +184,7 @@ public void serverTick() {
                 y = fillY;
                 z = fillZ;
 
+                // blocks may change during machine working, so let's check again
                 posesToFill.addAll(getPosesToFill());
                 if (posesToFill.isEmpty()) {
                     isDone = true;
@@ -183,14 +202,57 @@ public void serverTick() {
     }
 
     private void fillAndDrainFluid(BlockPos pos, ServerLevel level) {
-        filler.drainFluid(1, false);
-        level.setBlockAndUpdate(pos, GTBlocks.LIGHT_CONCRETE.getDefaultState());
-        fillX = pos.getX();
-        fillY = pos.getY();
-        fillZ = pos.getZ();
+        var matches = searchRecipe();
+        while (matches != null && matches.hasNext()) {
+            GTRecipe match = matches.next();
+            if (match == null) continue;
+
+            if (match.matchRecipeContents(IO.IN, machine, match.inputs).isSuccess()) {
+                if (handleRecipeIO(match, IO.IN)) {
+                    var item = RecipeHelper.getOutputItems(match).get(0).getItem();
+                    if (item instanceof BlockItem blockItem) {
+                        level.setBlockAndUpdate(pos, blockItem.getBlock().defaultBlockState());
+                        fillX = pos.getX();
+                        fillY = pos.getY();
+                        fillZ = pos.getZ();
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    protected @Nullable Iterator<GTRecipe> searchRecipe() {
+        if (!machine.hasProxies()) return null;
+        var iterator = machine
+                .getRecipeType()
+                .getLookup()
+                .getRecipeIterator(
+                        machine,
+                        recipe -> !recipe.isFuel
+                                && recipe.matchRecipeContents(IO.IN, machine, recipe.inputs).isSuccess()
+                                && recipe.matchRecipeContents(IO.IN, machine, recipe.tickInputs).isSuccess());
+
+        boolean any = false;
+        while (iterator.hasNext()) {
+            GTRecipe recipe = iterator.next();
+            if (recipe == null) continue;
+            any = true;
+            break;
+        }
+        if (any) {
+            iterator.reset();
+            return iterator;
+        }
+        return Collections.emptyIterator();
+    }
+
+    public void initPos() {
+        this.initPos(getCenterPos(), currentRadius);
     }
 
-    public void initPos(@NotNull BlockPos pos, int currentRadius) {
+    public void initPos(BlockPos pos, int currentRadius) {
         if (this.minBuildHeight == Integer.MAX_VALUE) {
             this.minBuildHeight = this.getMachine().getLevel().getMinBuildHeight();
         }
@@ -226,12 +288,12 @@ private static boolean checkStateCanFill(BlockState state) {
     private LinkedList<BlockPos> getPosesToFill() {
         LinkedList<BlockPos> poses = new LinkedList<>();
 
-        double quotient = getQuotient(getMeanTickTime(getMachine().getLevel()));
+        double quotient = getQuotient(EPUtil.getMeanTickTime(getMachine().getLevel()));
         int calcAmount = quotient < 1 ? 1 : (int) (Math.min(quotient, Short.MAX_VALUE));
 
         int calculated = 0;
         while (calculated < calcAmount) {
-            if (y < getCenterPos().getY() - 1) {
+            if (y <= getCenterPos().getY() - 1) {
                 if (z <= startZ + currentRadius * 2) {
                     if (x <= startX + currentRadius * 2) {
                         BlockPos pos = new BlockPos(x, y, z);
@@ -267,41 +329,21 @@ private boolean checkCoordinatesInvalid() {
 
     private boolean checkCanFill() {
         if (!isDone() && checkCoordinatesInvalid()) {
-            initPos(getCenterPos(), currentRadius);
+            initPos();
         }
-        return !isDone && filler.drainInput(true);
+        return !isDone;
     }
 
     public void resetArea() {
-        initPos(getCenterPos(), currentRadius);
+        initPos();
         if (this.isDone) this.setWorkingEnabled(false);
         this.isDone = false;
     }
 
-    /**
-     * @param values to find the mean of
-     * @return the mean value
-     */
-    private static long mean(long[] values) {
-        if (values.length == 0L) return 0L;
-
-        long sum = 0L;
-        for (long v : values) sum += v;
-        return sum / values.length;
-    }
-
-    /**
-     * @param world the {@link Level} to get the average tick time of
-     * @return the mean tick time
-     */
-    private static double getMeanTickTime(@NotNull Level world) {
-        return mean(Objects.requireNonNull(world.getServer()).tickTimes) * 1.0E-6D;
-    }
-
     /**
      * gets the quotient for determining the amount of blocks to mine
      *
-     * @param base is a value used for calculation, intended to be the mean tick time of the world the miner is in
+     * @param base is a value used for calculation, intended to be the mean tick time of the world the filler is in
      * @return the quotient
      */
     private static double getQuotient(double base) {
diff --git a/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java b/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java
new file mode 100644
index 0000000..b627f2b
--- /dev/null
+++ b/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java
@@ -0,0 +1,23 @@
+package com.epimorphismmc.epimorphism.data.recipe.misc;
+
+import net.minecraft.data.recipes.FinishedRecipe;
+
+import java.util.function.Consumer;
+
+import static com.epimorphismmc.epimorphism.common.data.EPRecipeTypes.*;
+import static com.gregtechceu.gtceu.api.GTValues.*;
+import static com.gregtechceu.gtceu.common.data.GTBlocks.*;
+import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
+
+public class ConcreteBackfillerRecipes {
+
+    public static void init(Consumer<FinishedRecipe> provider) {
+        CONCRETE_BACKFILLER_RECIPES
+                .recipeBuilder("concrete")
+                .inputFluids(Concrete.getFluid(144))
+                .outputItems(LIGHT_CONCRETE)
+                .EUt(EV)
+                .duration(20)
+                .save(provider);
+    }
+}
diff --git a/src/main/java/com/epimorphismmc/epimorphism/utils/EPMath.java b/src/main/java/com/epimorphismmc/epimorphism/utils/EPMath.java
new file mode 100644
index 0000000..ffb9d10
--- /dev/null
+++ b/src/main/java/com/epimorphismmc/epimorphism/utils/EPMath.java
@@ -0,0 +1,16 @@
+package com.epimorphismmc.epimorphism.utils;
+
+public class EPMath {
+
+    /**
+     * @param values to find the mean of
+     * @return the mean value
+     */
+    public static long mean(long[] values) {
+        if (values.length == 0L) return 0L;
+
+        long sum = 0L;
+        for (long v : values) sum += v;
+        return sum / values.length;
+    }
+}
diff --git a/src/main/java/com/epimorphismmc/epimorphism/utils/EPUtil.java b/src/main/java/com/epimorphismmc/epimorphism/utils/EPUtil.java
index b36ee2a..5966847 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/utils/EPUtil.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/utils/EPUtil.java
@@ -3,8 +3,13 @@
 import com.lowdragmc.lowdraglib.misc.FluidTransferList;
 import com.lowdragmc.lowdraglib.side.fluid.FluidStack;
 
+import net.minecraft.world.level.Level;
+
+import org.jetbrains.annotations.NotNull;
+
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.function.Predicate;
 
 public class EPUtil {
@@ -19,4 +24,12 @@ public static List<FluidStack> fluidHandlerToList(FluidTransferList fluidTransfe
         }
         return list.stream().filter(Predicate.not(FluidStack::isEmpty)).toList();
     }
+
+    /**
+     * @param world the {@link Level} to get the average tick time of
+     * @return the mean tick time
+     */
+    public static double getMeanTickTime(@NotNull Level world) {
+        return EPMath.mean(Objects.requireNonNull(world.getServer()).tickTimes) * 1.0E-6D;
+    }
 }

From e413a8abab972963ef9985dc02e5dbc248bae632 Mon Sep 17 00:00:00 2001
From: Gate Guardian <xtzcy76040108@163.com>
Date: Fri, 9 Aug 2024 19:23:53 +0800
Subject: [PATCH 2/4] concrete recipes

---
 .../assets/epimorphism/lang/en_ud.json        |  16 ++
 .../assets/epimorphism/lang/en_us.json        |  16 ++
 .../assets/epimorphism/lang/zh_cn.json        |  16 ++
 .../material/info/EPMaterialFlags.java        |   4 +
 .../epimorphism/api/data/tag/EPTagPrefix.java |   2 +-
 .../api/data/tag/TagPrefixAddition.java       |  13 ++
 .../multiblock/stats/ICasingMachine.java      |   2 +-
 .../multiblock/stats/ICoilMachine.java        |   1 +
 .../epimorphism/common/data/EPMaterials.java  |  62 ++++++-
 .../epimorphism/common/data/EPRecipes.java    |   8 +-
 .../materials/EPSecondDegreeMaterials.java    | 170 +++++++++++++++++-
 .../epimorphism/data/lang/MaterialLang.java   |  16 ++
 .../misc/ConcreteBackfillerRecipes.java       |  21 ++-
 .../data/recipe/misc/ConcreteRecipes.java     |  33 ++++
 .../WrapItemRecipes.java}                     |  26 +--
 15 files changed, 382 insertions(+), 24 deletions(-)
 create mode 100644 src/main/java/com/epimorphismmc/epimorphism/api/data/tag/TagPrefixAddition.java
 create mode 100644 src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteRecipes.java
 rename src/main/java/com/epimorphismmc/epimorphism/data/recipe/{handler/WrapItemRecipeHandler.java => misc/WrapItemRecipes.java} (51%)

diff --git a/src/generated/resources/assets/epimorphism/lang/en_ud.json b/src/generated/resources/assets/epimorphism/lang/en_ud.json
index 78e9490..ecd754c 100644
--- a/src/generated/resources/assets/epimorphism/lang/en_ud.json
+++ b/src/generated/resources/assets/epimorphism/lang/en_ud.json
@@ -927,11 +927,13 @@
   "material.epimorphism.bismuth_vanadate": "ǝʇɐpɐuɐΛ ɥʇnɯsıᗺ",
   "material.epimorphism.bismuth_vanadate_solution": "uoıʇnןoS ǝʇɐpɐuɐΛ ɥʇnɯsıᗺ",
   "material.epimorphism.bistrichloromethylbenzene": "ǝuǝzuǝqןʎɥʇǝɯoɹoןɥɔıɹʇsıᗺ",
+  "material.epimorphism.black_concrete": "ǝʇǝɹɔuoƆ ʞɔɐןᗺ",
   "material.epimorphism.black_dwarf_matter": "ɹǝʇʇɐW ɟɹɐʍᗡ ʞɔɐןᗺ",
   "material.epimorphism.black_phosphorus": "snɹoɥdsoɥԀ ʞɔɐןᗺ",
   "material.epimorphism.black_plutonium": "ɯnıuoʇnןԀ ʞɔɐןᗺ",
   "material.epimorphism.black_titanium": "ɯnıuɐʇı⟘ ʞɔɐןᗺ",
   "material.epimorphism.blazing_pyrotheum": "ɯnǝɥʇoɹʎԀ buızɐןᗺ",
+  "material.epimorphism.blue_concrete": "ǝʇǝɹɔuoƆ ǝnןᗺ",
   "material.epimorphism.blue_phosphorus": "snɹoɥdsoɥԀ ǝnןᗺ",
   "material.epimorphism.borane_dimethylsulfide": "ǝpıɟןnsןʎɥʇǝɯıᗡ ǝuɐɹoᗺ",
   "material.epimorphism.borazine": "ǝuızɐɹoᗺ",
@@ -949,6 +951,7 @@
   "material.epimorphism.bromobutane": "ǝuɐʇnqoɯoɹᗺ",
   "material.epimorphism.bromodihydrothiine": "ǝuııɥʇoɹpʎɥıpoɯoɹᗺ",
   "material.epimorphism.brown_algae": "ǝɐbןⱯ uʍoɹᗺ",
+  "material.epimorphism.brown_concrete": "ǝʇǝɹɔuoƆ uʍoɹᗺ",
   "material.epimorphism.butanediol": "ןoıpǝuɐʇnᗺ",
   "material.epimorphism.butanol": "ןouɐʇnᗺ",
   "material.epimorphism.butyl_lithium": "ɯnıɥʇıꞀ ןʎʇnᗺ",
@@ -1016,6 +1019,7 @@
   "material.epimorphism.cubic_boron_nitride": "ǝpıɹʇıN uoɹoᗺ ɔıqnƆ",
   "material.epimorphism.cubic_heterodiamond": "puoɯɐıpoɹǝʇǝH ɔıqnƆ",
   "material.epimorphism.cubic_zirconia": "ɐıuoɔɹıZ ɔıqnƆ",
+  "material.epimorphism.cyan_concrete": "ǝʇǝɹɔuoƆ uɐʎƆ",
   "material.epimorphism.cyanonaphthalene": "ǝuǝןɐɥʇɥdɐuouɐʎƆ",
   "material.epimorphism.cyclooctadiene": "ǝuǝıpɐʇɔooןɔʎƆ",
   "material.epimorphism.cycloparaphenylene": "ǝuǝןʎuǝɥdɐɹɐdoןɔʎƆ",
@@ -1120,7 +1124,9 @@
   "material.epimorphism.gold_trifluoride": "ǝpıɹonןɟıɹ⟘ pןo⅁",
   "material.epimorphism.golden_algae": "ǝɐbןⱯ uǝpןo⅁",
   "material.epimorphism.graphene_oxide": "ǝpıxO ǝuǝɥdɐɹ⅁",
+  "material.epimorphism.gray_concrete": "ǝʇǝɹɔuoƆ ʎɐɹ⅁",
   "material.epimorphism.green_algae": "ǝɐbןⱯ uǝǝɹ⅁",
+  "material.epimorphism.green_concrete": "ǝʇǝɹɔuoƆ uǝǝɹ⅁",
   "material.epimorphism.grignard_reagent": "ʇuǝbɐǝᴚ pɹɐubıɹ⅁",
   "material.epimorphism.grisium": "ɯnısıɹ⅁",
   "material.epimorphism.gst_glass": "ssɐן⅁ ʇs⅁",
@@ -1215,14 +1221,17 @@
   "material.epimorphism.lead_chloride": "ǝpıɹoןɥƆ pɐǝꞀ",
   "material.epimorphism.legendarium": "ɯnıɹɐpuǝbǝꞀ",
   "material.epimorphism.light_bedrock_smoke": "ǝʞoɯS ʞɔoɹpǝᗺ ʇɥbıꞀ",
+  "material.epimorphism.light_blue_concrete": "ǝʇǝɹɔuoƆ ǝnןᗺ ʇɥbıꞀ",
   "material.epimorphism.light_enriched_bedrock_smoke": "ǝʞoɯS ʞɔoɹpǝᗺ pǝɥɔıɹuƎ ʇɥbıꞀ",
   "material.epimorphism.light_enriched_taranium_fuel": "ןǝnℲ ɯnıuɐɹɐ⟘ pǝɥɔıɹuƎ ʇɥbıꞀ",
   "material.epimorphism.light_enriched_taranium_gas": "sɐ⅁ ɯnıuɐɹɐ⟘ pǝɥɔıɹuƎ ʇɥbıꞀ",
+  "material.epimorphism.light_gray_concrete": "ǝʇǝɹɔuoƆ ʎɐɹ⅁ ʇɥbıꞀ",
   "material.epimorphism.light_hyper_fuel": "ןǝnℲ ɹǝdʎH ʇɥbıꞀ",
   "material.epimorphism.light_naquadah_fuel": "ןǝnℲ ɥɐpɐnbɐN ʇɥbıꞀ",
   "material.epimorphism.light_quarks": "sʞɹɐnὉ ʇɥbıꞀ",
   "material.epimorphism.light_taranium_fuel": "ןǝnℲ ɯnıuɐɹɐ⟘ ʇɥbıꞀ",
   "material.epimorphism.light_taranium_gas": "sɐ⅁ ɯnıuɐɹɐ⟘ ʇɥbıꞀ",
+  "material.epimorphism.lime_concrete": "ǝʇǝɹɔuoƆ ǝɯıꞀ",
   "material.epimorphism.lithium_amalgam": "ɯɐbןɐɯⱯ ɯnıɥʇıꞀ",
   "material.epimorphism.lithium_carbonate": "ǝʇɐuoqɹɐƆ ɯnıɥʇıꞀ",
   "material.epimorphism.lithium_fluoride": "ǝpıɹonןℲ ɯnıɥʇıꞀ",
@@ -1237,6 +1246,7 @@
   "material.epimorphism.low_purity_rare_earth_chlorides_solution": "uoıʇnןoS sǝpıɹoןɥƆ ɥʇɹɐƎ ǝɹɐᴚ ʎʇıɹnԀ ʍoꞀ",
   "material.epimorphism.lutetium_oxide": "ǝpıxO ɯnıʇǝʇnꞀ",
   "material.epimorphism.lutetium_thulium_yttrium_chlorides_solution": "uoıʇnןoS sǝpıɹoןɥƆ ɯnıɹʇʇʎ ɯnıןnɥ⟘ ɯnıʇǝʇnꞀ",
+  "material.epimorphism.magenta_concrete": "ǝʇǝɹɔuoƆ ɐʇuǝbɐW",
   "material.epimorphism.magnesium_bromide": "ǝpıɯoɹᗺ ɯnısǝubɐW",
   "material.epimorphism.magnesium_chloride_bromide": "ǝpıɯoɹᗺ ǝpıɹoןɥƆ ɯnısǝubɐW",
   "material.epimorphism.magnetic_chromium_germanium_telluride": "ǝpıɹnןןǝ⟘ ɯnıuɐɯɹǝ⅁ ɯnıɯoɹɥƆ ɔıʇǝubɐW",
@@ -1306,6 +1316,7 @@
   "material.epimorphism.nitryl_fluoride": "ǝpıɹonןℲ ןʎɹʇıN",
   "material.epimorphism.octafluoro_pentanol": "ןouɐʇuǝԀ oɹonןɟɐʇɔO",
   "material.epimorphism.oganesson_breeding_base": "ǝsɐᗺ buıpǝǝɹᗺ uossǝuɐbO",
+  "material.epimorphism.orange_concrete": "ǝʇǝɹɔuoƆ ǝbuɐɹO",
   "material.epimorphism.orichalcum": "ɯnɔןɐɥɔıɹO",
   "material.epimorphism.orichalcum_energized": "pǝzıbɹǝuƎ ɯnɔןɐɥɔıɹO",
   "material.epimorphism.osmium_tetrachloride": "ǝpıɹoןɥɔɐɹʇǝ⟘ ɯnıɯsO",
@@ -1332,6 +1343,7 @@
   "material.epimorphism.phosphoryl_chloride": "ǝpıɹoןɥƆ ןʎɹoɥdsoɥԀ",
   "material.epimorphism.phthalic_anhydride": "ǝpıɹpʎɥuⱯ ɔıןɐɥʇɥԀ",
   "material.epimorphism.pikyonium_64_b": "ᗺ ㄣ9 ɯnıuoʎʞıԀ",
+  "material.epimorphism.pink_concrete": "ǝʇǝɹɔuoƆ ʞuıԀ",
   "material.epimorphism.platinum_group_alloy": "ʎoןןⱯ dnoɹ⅁ ɯnuıʇɐןԀ",
   "material.epimorphism.platinum_group_sludge_solution": "uoıʇnןoS ǝbpnןS dnoɹ⅁ ɯnuıʇɐןԀ",
   "material.epimorphism.platinum_metal": "ןɐʇǝW ɯnuıʇɐןԀ",
@@ -1371,6 +1383,7 @@
   "material.epimorphism.primal_mana": "ɐuɐW ןɐɯıɹԀ",
   "material.epimorphism.propadiene": "ǝuǝıpɐdoɹԀ",
   "material.epimorphism.pure_naquadria_mixture_solution": "uoıʇnןoS ǝɹnʇxıW ɐıɹpɐnbɐN ǝɹnԀ",
+  "material.epimorphism.purple_concrete": "ǝʇǝɹɔuoƆ ǝןdɹnԀ",
   "material.epimorphism.pyridine": "ǝuıpıɹʎԀ",
   "material.epimorphism.pyrocatechol": "ןoɥɔǝʇɐɔoɹʎԀ",
   "material.epimorphism.pyromellitic_dianhydride": "ǝpıɹpʎɥuɐıᗡ ɔıʇıןןǝɯoɹʎԀ",
@@ -1388,6 +1401,7 @@
   "material.epimorphism.rarest_metal_residue": "ǝnpısǝᴚ ןɐʇǝW ʇsǝɹɐᴚ",
   "material.epimorphism.raw_star_matter": "ɹǝʇʇɐW ɹɐʇS ʍɐᴚ",
   "material.epimorphism.red_algae": "ǝɐbןⱯ pǝᴚ",
+  "material.epimorphism.red_concrete": "ǝʇǝɹɔuoƆ pǝᴚ",
   "material.epimorphism.red_phosphorus": "snɹoɥdsoɥԀ pǝᴚ",
   "material.epimorphism.residual_draconium_solution": "uoıʇnןoS ɯnıuoɔɐɹᗡ ןɐnpısǝᴚ",
   "material.epimorphism.resorcinol": "ןouıɔɹosǝᴚ",
@@ -1526,6 +1540,7 @@
   "material.epimorphism.waelz_oxide": "ǝpıxO zןǝɐM",
   "material.epimorphism.waelz_slag": "bɐןS zןǝɐM",
   "material.epimorphism.wet_bromine": "ǝuıɯoɹᗺ ʇǝM",
+  "material.epimorphism.white_concrete": "ǝʇǝɹɔuoƆ ǝʇıɥM",
   "material.epimorphism.white_dwarf_matter": "ɹǝʇʇɐW ɟɹɐʍᗡ ǝʇıɥM",
   "material.epimorphism.white_phosphorus": "snɹoɥdsoɥԀ ǝʇıɥM",
   "material.epimorphism.wollastonite": "ǝʇıuoʇsɐןןoM",
@@ -1533,6 +1548,7 @@
   "material.epimorphism.xenon_hexafluoro_enriched_naquadate": "ǝʇɐpɐnbɐN pǝɥɔıɹuƎ oɹonןɟɐxǝH uouǝX",
   "material.epimorphism.xenon_trioxide": "ǝpıxoıɹ⟘ uouǝX",
   "material.epimorphism.y_tb_dy_ho_oxides_solution": "uoıʇnןoS sǝpıxO oH ʎᗡ q⟘ ʎ",
+  "material.epimorphism.yellow_concrete": "ǝʇǝɹɔuoƆ ʍoןןǝʎ",
   "material.epimorphism.ytterbium_178": "8ㄥƖ ɯnıqɹǝʇʇʎ",
   "material.epimorphism.ytterbium_oxide": "ǝpıxO ɯnıqɹǝʇʇʎ",
   "material.epimorphism.yttrium_oxide": "ǝpıxO ɯnıɹʇʇʎ",
diff --git a/src/generated/resources/assets/epimorphism/lang/en_us.json b/src/generated/resources/assets/epimorphism/lang/en_us.json
index 170403f..91df4f0 100644
--- a/src/generated/resources/assets/epimorphism/lang/en_us.json
+++ b/src/generated/resources/assets/epimorphism/lang/en_us.json
@@ -927,11 +927,13 @@
   "material.epimorphism.bismuth_vanadate": "Bismuth Vanadate",
   "material.epimorphism.bismuth_vanadate_solution": "Bismuth Vanadate Solution",
   "material.epimorphism.bistrichloromethylbenzene": "Bistrichloromethylbenzene",
+  "material.epimorphism.black_concrete": "Black Concrete",
   "material.epimorphism.black_dwarf_matter": "Black Dwarf Matter",
   "material.epimorphism.black_phosphorus": "Black Phosphorus",
   "material.epimorphism.black_plutonium": "Black Plutonium",
   "material.epimorphism.black_titanium": "Black Titanium",
   "material.epimorphism.blazing_pyrotheum": "Blazing Pyrotheum",
+  "material.epimorphism.blue_concrete": "Blue Concrete",
   "material.epimorphism.blue_phosphorus": "Blue Phosphorus",
   "material.epimorphism.borane_dimethylsulfide": "Borane Dimethylsulfide",
   "material.epimorphism.borazine": "Borazine",
@@ -949,6 +951,7 @@
   "material.epimorphism.bromobutane": "Bromobutane",
   "material.epimorphism.bromodihydrothiine": "Bromodihydrothiine",
   "material.epimorphism.brown_algae": "Brown Algae",
+  "material.epimorphism.brown_concrete": "Brown Concrete",
   "material.epimorphism.butanediol": "Butanediol",
   "material.epimorphism.butanol": "Butanol",
   "material.epimorphism.butyl_lithium": "Butyl Lithium",
@@ -1016,6 +1019,7 @@
   "material.epimorphism.cubic_boron_nitride": "Cubic Boron Nitride",
   "material.epimorphism.cubic_heterodiamond": "Cubic Heterodiamond",
   "material.epimorphism.cubic_zirconia": "Cubic Zirconia",
+  "material.epimorphism.cyan_concrete": "Cyan Concrete",
   "material.epimorphism.cyanonaphthalene": "Cyanonaphthalene",
   "material.epimorphism.cyclooctadiene": "Cyclooctadiene",
   "material.epimorphism.cycloparaphenylene": "Cycloparaphenylene",
@@ -1120,7 +1124,9 @@
   "material.epimorphism.gold_trifluoride": "Gold Trifluoride",
   "material.epimorphism.golden_algae": "Golden Algae",
   "material.epimorphism.graphene_oxide": "Graphene Oxide",
+  "material.epimorphism.gray_concrete": "Gray Concrete",
   "material.epimorphism.green_algae": "Green Algae",
+  "material.epimorphism.green_concrete": "Green Concrete",
   "material.epimorphism.grignard_reagent": "Grignard Reagent",
   "material.epimorphism.grisium": "Grisium",
   "material.epimorphism.gst_glass": "Gst Glass",
@@ -1215,14 +1221,17 @@
   "material.epimorphism.lead_chloride": "Lead Chloride",
   "material.epimorphism.legendarium": "Legendarium",
   "material.epimorphism.light_bedrock_smoke": "Light Bedrock Smoke",
+  "material.epimorphism.light_blue_concrete": "Light Blue Concrete",
   "material.epimorphism.light_enriched_bedrock_smoke": "Light Enriched Bedrock Smoke",
   "material.epimorphism.light_enriched_taranium_fuel": "Light Enriched Taranium Fuel",
   "material.epimorphism.light_enriched_taranium_gas": "Light Enriched Taranium Gas",
+  "material.epimorphism.light_gray_concrete": "Light Gray Concrete",
   "material.epimorphism.light_hyper_fuel": "Light Hyper Fuel",
   "material.epimorphism.light_naquadah_fuel": "Light Naquadah Fuel",
   "material.epimorphism.light_quarks": "Light Quarks",
   "material.epimorphism.light_taranium_fuel": "Light Taranium Fuel",
   "material.epimorphism.light_taranium_gas": "Light Taranium Gas",
+  "material.epimorphism.lime_concrete": "Lime Concrete",
   "material.epimorphism.lithium_amalgam": "Lithium Amalgam",
   "material.epimorphism.lithium_carbonate": "Lithium Carbonate",
   "material.epimorphism.lithium_fluoride": "Lithium Fluoride",
@@ -1237,6 +1246,7 @@
   "material.epimorphism.low_purity_rare_earth_chlorides_solution": "Low Purity Rare Earth Chlorides Solution",
   "material.epimorphism.lutetium_oxide": "Lutetium Oxide",
   "material.epimorphism.lutetium_thulium_yttrium_chlorides_solution": "Lutetium Thulium Yttrium Chlorides Solution",
+  "material.epimorphism.magenta_concrete": "Magenta Concrete",
   "material.epimorphism.magnesium_bromide": "Magnesium Bromide",
   "material.epimorphism.magnesium_chloride_bromide": "Magnesium Chloride Bromide",
   "material.epimorphism.magnetic_chromium_germanium_telluride": "Magnetic Chromium Germanium Telluride",
@@ -1306,6 +1316,7 @@
   "material.epimorphism.nitryl_fluoride": "Nitryl Fluoride",
   "material.epimorphism.octafluoro_pentanol": "Octafluoro Pentanol",
   "material.epimorphism.oganesson_breeding_base": "Oganesson Breeding Base",
+  "material.epimorphism.orange_concrete": "Orange Concrete",
   "material.epimorphism.orichalcum": "Orichalcum",
   "material.epimorphism.orichalcum_energized": "Orichalcum Energized",
   "material.epimorphism.osmium_tetrachloride": "Osmium Tetrachloride",
@@ -1332,6 +1343,7 @@
   "material.epimorphism.phosphoryl_chloride": "Phosphoryl Chloride",
   "material.epimorphism.phthalic_anhydride": "Phthalic Anhydride",
   "material.epimorphism.pikyonium_64_b": "Pikyonium 64 B",
+  "material.epimorphism.pink_concrete": "Pink Concrete",
   "material.epimorphism.platinum_group_alloy": "Platinum Group Alloy",
   "material.epimorphism.platinum_group_sludge_solution": "Platinum Group Sludge Solution",
   "material.epimorphism.platinum_metal": "Platinum Metal",
@@ -1371,6 +1383,7 @@
   "material.epimorphism.primal_mana": "Primal Mana",
   "material.epimorphism.propadiene": "Propadiene",
   "material.epimorphism.pure_naquadria_mixture_solution": "Pure Naquadria Mixture Solution",
+  "material.epimorphism.purple_concrete": "Purple Concrete",
   "material.epimorphism.pyridine": "Pyridine",
   "material.epimorphism.pyrocatechol": "Pyrocatechol",
   "material.epimorphism.pyromellitic_dianhydride": "Pyromellitic Dianhydride",
@@ -1388,6 +1401,7 @@
   "material.epimorphism.rarest_metal_residue": "Rarest Metal Residue",
   "material.epimorphism.raw_star_matter": "Raw Star Matter",
   "material.epimorphism.red_algae": "Red Algae",
+  "material.epimorphism.red_concrete": "Red Concrete",
   "material.epimorphism.red_phosphorus": "Red Phosphorus",
   "material.epimorphism.residual_draconium_solution": "Residual Draconium Solution",
   "material.epimorphism.resorcinol": "Resorcinol",
@@ -1526,6 +1540,7 @@
   "material.epimorphism.waelz_oxide": "Waelz Oxide",
   "material.epimorphism.waelz_slag": "Waelz Slag",
   "material.epimorphism.wet_bromine": "Wet Bromine",
+  "material.epimorphism.white_concrete": "White Concrete",
   "material.epimorphism.white_dwarf_matter": "White Dwarf Matter",
   "material.epimorphism.white_phosphorus": "White Phosphorus",
   "material.epimorphism.wollastonite": "Wollastonite",
@@ -1533,6 +1548,7 @@
   "material.epimorphism.xenon_hexafluoro_enriched_naquadate": "Xenon Hexafluoro Enriched Naquadate",
   "material.epimorphism.xenon_trioxide": "Xenon Trioxide",
   "material.epimorphism.y_tb_dy_ho_oxides_solution": "Y Tb Dy Ho Oxides Solution",
+  "material.epimorphism.yellow_concrete": "Yellow Concrete",
   "material.epimorphism.ytterbium_178": "Ytterbium 178",
   "material.epimorphism.ytterbium_oxide": "Ytterbium Oxide",
   "material.epimorphism.yttrium_oxide": "Yttrium Oxide",
diff --git a/src/generated/resources/assets/epimorphism/lang/zh_cn.json b/src/generated/resources/assets/epimorphism/lang/zh_cn.json
index 2499d0b..2839c9f 100644
--- a/src/generated/resources/assets/epimorphism/lang/zh_cn.json
+++ b/src/generated/resources/assets/epimorphism/lang/zh_cn.json
@@ -775,11 +775,13 @@
   "material.epimorphism.bismuth_vanadate": "钒酸铋",
   "material.epimorphism.bismuth_vanadate_solution": "钒酸铋溶液",
   "material.epimorphism.bistrichloromethylbenzene": "1,4-双(三氯甲基)苯",
+  "material.epimorphism.black_concrete": "黑色混凝土",
   "material.epimorphism.black_dwarf_matter": "黑矮星物质",
   "material.epimorphism.black_phosphorus": "黑磷",
   "material.epimorphism.black_plutonium": "黑钚",
   "material.epimorphism.black_titanium": "黑钛合金",
   "material.epimorphism.blazing_pyrotheum": "烈焰之炽焱",
+  "material.epimorphism.blue_concrete": "蓝色混凝土",
   "material.epimorphism.blue_phosphorus": "蓝磷",
   "material.epimorphism.borane_dimethylsulfide": "硼烷二甲硫醚",
   "material.epimorphism.borazine": "环氮硼烷",
@@ -797,6 +799,7 @@
   "material.epimorphism.bromobutane": "溴丁烷",
   "material.epimorphism.bromodihydrothiine": "溴二氢硫醚",
   "material.epimorphism.brown_algae": "褐藻",
+  "material.epimorphism.brown_concrete": "棕色混凝土",
   "material.epimorphism.butanediol": "1,4-丁二醇",
   "material.epimorphism.butanol": "丁醇",
   "material.epimorphism.butyl_lithium": "丁基锂",
@@ -863,6 +866,7 @@
   "material.epimorphism.cubic_boron_nitride": "立方氮化硼",
   "material.epimorphism.cubic_heterodiamond": "立方杂金刚石",
   "material.epimorphism.cubic_zirconia": "立方氧化锆",
+  "material.epimorphism.cyan_concrete": "青色混凝土",
   "material.epimorphism.cyanonaphthalene": "氰萘",
   "material.epimorphism.cyclooctadiene": "环辛二烯",
   "material.epimorphism.cycloparaphenylene": "环对苯撑(CPP)",
@@ -967,7 +971,9 @@
   "material.epimorphism.gold_trifluoride": "三氟化金",
   "material.epimorphism.golden_algae": "金藻",
   "material.epimorphism.graphene_oxide": "氧化石墨烯",
+  "material.epimorphism.gray_concrete": "灰色混凝土",
   "material.epimorphism.green_algae": "绿藻",
+  "material.epimorphism.green_concrete": "绿色混凝土",
   "material.epimorphism.grignard_reagent": "格氏试剂",
   "material.epimorphism.grisium": "灰钛合金",
   "material.epimorphism.gst_glass": "GST玻璃",
@@ -1062,14 +1068,17 @@
   "material.epimorphism.lead_chloride": "氯化铅",
   "material.epimorphism.legendarium": "传奇金属",
   "material.epimorphism.light_bedrock_smoke": "轻基岩烟",
+  "material.epimorphism.light_blue_concrete": "淡蓝色混凝土",
   "material.epimorphism.light_enriched_bedrock_smoke": "轻富集基岩烟",
   "material.epimorphism.light_enriched_taranium_fuel": "轻塔兰金属燃料",
   "material.epimorphism.light_enriched_taranium_gas": "轻富集塔兰金属气",
+  "material.epimorphism.light_gray_concrete": "淡灰色混凝土",
   "material.epimorphism.light_hyper_fuel": "轻超能燃料",
   "material.epimorphism.light_naquadah_fuel": "轻硅岩燃料",
   "material.epimorphism.light_quarks": "轻夸克",
   "material.epimorphism.light_taranium_fuel": "轻塔兰金属燃料",
   "material.epimorphism.light_taranium_gas": "轻塔兰金属气",
+  "material.epimorphism.lime_concrete": "黄绿色混凝土",
   "material.epimorphism.lithium_amalgam": "锂汞齐",
   "material.epimorphism.lithium_carbonate": "碳酸锂",
   "material.epimorphism.lithium_fluoride": "氟化锂",
@@ -1084,6 +1093,7 @@
   "material.epimorphism.low_purity_rare_earth_chlorides_solution": "低纯度稀土氯化物溶液",
   "material.epimorphism.lutetium_oxide": "氧化镥",
   "material.epimorphism.lutetium_thulium_yttrium_chlorides_solution": "镥铥钇氯化物溶液",
+  "material.epimorphism.magenta_concrete": "品红色混凝土",
   "material.epimorphism.magnesium_bromide": "溴化镁",
   "material.epimorphism.magnesium_chloride_bromide": "溴氯化镁",
   "material.epimorphism.magnetic_chromium_germanium_telluride": "磁化碲化锗铬",
@@ -1149,6 +1159,7 @@
   "material.epimorphism.nitryl_fluoride": "硝酰氟",
   "material.epimorphism.octafluoro_pentanol": "八氟戊醇",
   "material.epimorphism.oganesson_breeding_base": "气奥增殖基",
+  "material.epimorphism.orange_concrete": "橙色混凝土",
   "material.epimorphism.orichalcum": "山铜",
   "material.epimorphism.orichalcum_energized": "充能山铜",
   "material.epimorphism.osmium_tetrachloride": "四氯化锇",
@@ -1175,6 +1186,7 @@
   "material.epimorphism.phosphoryl_chloride": "磷酰氯",
   "material.epimorphism.phthalic_anhydride": "邻苯二甲酸酐",
   "material.epimorphism.pikyonium_64_b": "皮卡优合金-64B",
+  "material.epimorphism.pink_concrete": "粉色混凝土",
   "material.epimorphism.platinum_group_alloy": "稀有金属合金",
   "material.epimorphism.platinum_group_sludge_solution": "铂族金属泥浆液",
   "material.epimorphism.platinum_metal": "铂金属",
@@ -1211,6 +1223,7 @@
   "material.epimorphism.primal_mana": "原始魔力",
   "material.epimorphism.propadiene": "丙二烯",
   "material.epimorphism.pure_naquadria_mixture_solution": "洁净超能硅岩混合物乳液",
+  "material.epimorphism.purple_concrete": "紫色混凝土",
   "material.epimorphism.pyridine": "吡啶",
   "material.epimorphism.pyrocatechol": "邻苯二酚",
   "material.epimorphism.pyromellitic_dianhydride": "均苯四酸二酐(PDMA)",
@@ -1227,6 +1240,7 @@
   "material.epimorphism.rarest_metal_residue": "稀有金属残余物",
   "material.epimorphism.raw_star_matter": "原始恒星等离子体物质",
   "material.epimorphism.red_algae": "红藻",
+  "material.epimorphism.red_concrete": "红色混凝土",
   "material.epimorphism.red_phosphorus": "红磷",
   "material.epimorphism.residual_draconium_solution": "龙素残余物溶液",
   "material.epimorphism.resorcinol": "间苯二酚",
@@ -1358,6 +1372,7 @@
   "material.epimorphism.waelz_oxide": "威氏氧化物",
   "material.epimorphism.waelz_slag": "威氏浸出渣",
   "material.epimorphism.wet_bromine": "含水溴烟气",
+  "material.epimorphism.white_concrete": "白色混凝土",
   "material.epimorphism.white_dwarf_matter": "白矮星物质",
   "material.epimorphism.white_phosphorus": "白磷",
   "material.epimorphism.wollastonite": "硅灰石",
@@ -1365,6 +1380,7 @@
   "material.epimorphism.xenon_hexafluoro_enriched_naquadate": "六氟氙酸富集硅岩",
   "material.epimorphism.xenon_trioxide": "三氧化氙",
   "material.epimorphism.y_tb_dy_ho_oxides_solution": "钇-铽-镝-钬氧化物溶液",
+  "material.epimorphism.yellow_concrete": "黄色混凝土",
   "material.epimorphism.ytterbium_178": "镱-178",
   "material.epimorphism.ytterbium_oxide": "氧化镱",
   "material.epimorphism.yttrium_oxide": "氧化钇",
diff --git a/src/main/java/com/epimorphismmc/epimorphism/api/data/chemical/material/info/EPMaterialFlags.java b/src/main/java/com/epimorphismmc/epimorphism/api/data/chemical/material/info/EPMaterialFlags.java
index 874656e..6dbe578 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/api/data/chemical/material/info/EPMaterialFlags.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/api/data/chemical/material/info/EPMaterialFlags.java
@@ -21,4 +21,8 @@ public class EPMaterialFlags {
                     "generate_laser_emitter")
             .requireProps(PropertyKey.FLUID)
             .build();
+    public static final MaterialFlag DISABLE_SMALL_DUST = new MaterialFlag.Builder(
+                    "disable_small_dust")
+            .requireProps(PropertyKey.DUST)
+            .build();
 }
diff --git a/src/main/java/com/epimorphismmc/epimorphism/api/data/tag/EPTagPrefix.java b/src/main/java/com/epimorphismmc/epimorphism/api/data/tag/EPTagPrefix.java
index fa07b8d..3ae5edc 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/api/data/tag/EPTagPrefix.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/api/data/tag/EPTagPrefix.java
@@ -131,6 +131,6 @@ public static class Conditions {
     }
 
     public static void init() {
-        /**/
+        TagPrefixAddition.init();
     }
 }
diff --git a/src/main/java/com/epimorphismmc/epimorphism/api/data/tag/TagPrefixAddition.java b/src/main/java/com/epimorphismmc/epimorphism/api/data/tag/TagPrefixAddition.java
new file mode 100644
index 0000000..da8c901
--- /dev/null
+++ b/src/main/java/com/epimorphismmc/epimorphism/api/data/tag/TagPrefixAddition.java
@@ -0,0 +1,13 @@
+package com.epimorphismmc.epimorphism.api.data.tag;
+
+import static com.epimorphismmc.epimorphism.api.data.chemical.material.info.EPMaterialFlags.*;
+import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.*;
+import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.Conditions.*;
+
+public class TagPrefixAddition {
+
+    public static void init() {
+        dustSmall.generationCondition(hasDustProperty.and(mat -> !mat.hasFlag(DISABLE_SMALL_DUST)));
+        dustTiny.generationCondition(hasDustProperty.and(mat -> !mat.hasFlag(DISABLE_SMALL_DUST)));
+    }
+}
diff --git a/src/main/java/com/epimorphismmc/epimorphism/api/machine/feature/multiblock/stats/ICasingMachine.java b/src/main/java/com/epimorphismmc/epimorphism/api/machine/feature/multiblock/stats/ICasingMachine.java
index aff182d..3c1f05f 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/api/machine/feature/multiblock/stats/ICasingMachine.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/api/machine/feature/multiblock/stats/ICasingMachine.java
@@ -2,8 +2,8 @@
 
 import com.epimorphismmc.monomorphism.block.tier.ITierType;
 import com.epimorphismmc.monomorphism.machine.multiblock.MultiStatsElectricMultiblockMachine;
-
 import com.epimorphismmc.monomorphism.machine.trait.MultiblockTrait;
+
 import com.gregtechceu.gtceu.api.machine.feature.IMachineFeature;
 import com.gregtechceu.gtceu.api.pattern.MultiblockState;
 
diff --git a/src/main/java/com/epimorphismmc/epimorphism/api/machine/feature/multiblock/stats/ICoilMachine.java b/src/main/java/com/epimorphismmc/epimorphism/api/machine/feature/multiblock/stats/ICoilMachine.java
index 4f1004c..4a532ac 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/api/machine/feature/multiblock/stats/ICoilMachine.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/api/machine/feature/multiblock/stats/ICoilMachine.java
@@ -1,6 +1,7 @@
 package com.epimorphismmc.epimorphism.api.machine.feature.multiblock.stats;
 
 import com.epimorphismmc.monomorphism.machine.trait.MultiblockTrait;
+
 import com.gregtechceu.gtceu.api.block.ICoilType;
 import com.gregtechceu.gtceu.api.machine.feature.IMachineFeature;
 import com.gregtechceu.gtceu.api.pattern.MultiblockState;
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMaterials.java b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMaterials.java
index 64ad506..918a02b 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMaterials.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMaterials.java
@@ -14,8 +14,18 @@
 
 import com.gregtechceu.gtceu.api.data.chemical.material.Material;
 
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.item.DyeColor;
+import net.minecraft.world.level.ItemLike;
+
+import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.*;
+
 public class EPMaterials {
-    public EPMaterials() {}
+
+    public static Material[] CONCRETES;
+
+    private EPMaterials() {}
 
     //  Element Materials
     public static Material Draconium;
@@ -415,6 +425,22 @@ public EPMaterials() {}
     public static Material ConcentrateDragonBreath;
     public static Material DragonBlood;
     public static Material DragonTear;
+    public static Material ConcreteBlack;
+    public static Material ConcreteRed;
+    public static Material ConcreteGreen;
+    public static Material ConcreteBrown;
+    public static Material ConcreteBlue;
+    public static Material ConcretePurple;
+    public static Material ConcreteCyan;
+    public static Material ConcreteLightGray;
+    public static Material ConcreteGray;
+    public static Material ConcretePink;
+    public static Material ConcreteLime;
+    public static Material ConcreteYellow;
+    public static Material ConcreteLightBlue;
+    public static Material ConcreteMagenta;
+    public static Material ConcreteOrange;
+    public static Material ConcreteWhite;
 
     //  Organic Chemistry Materials
     public static Material KaptonK;
@@ -745,6 +771,40 @@ public static void init() {
 
         EPMaterialPropertyAddition.init();
         EPMaterialFlagAddition.init();
+
+        CONCRETES = new Material[] {
+            ConcreteWhite,
+            ConcreteOrange,
+            ConcreteMagenta,
+            ConcreteLightBlue,
+            ConcreteYellow,
+            ConcreteLime,
+            ConcretePink,
+            ConcreteGray,
+            ConcreteLightGray,
+            ConcreteCyan,
+            ConcretePurple,
+            ConcreteBlue,
+            ConcreteBrown,
+            ConcreteGreen,
+            ConcreteRed,
+            ConcreteBlack
+        };
+
+        for (int i = 0; i < DyeColor.values().length; i++) {
+            var color = DyeColor.values()[i];
+            String dyeName = color.getName();
+            concrete(
+                    CONCRETES[i],
+                    BuiltInRegistries.BLOCK.get(new ResourceLocation(dyeName + "_concrete")),
+                    BuiltInRegistries.ITEM.get(new ResourceLocation(dyeName + "_concrete_powder")));
+        }
+    }
+
+    private static void concrete(Material material, ItemLike concreteBlock, ItemLike concreteDust) {
+        dust.setIgnored(material, concreteDust);
+        block.setIgnored(material, concreteBlock);
+        block.modifyMaterialAmount(material, 1);
     }
 
     public static Material.Builder Builder(String name) {
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipes.java b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipes.java
index 97f22fa..67c2251 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipes.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipes.java
@@ -6,12 +6,14 @@
 import com.epimorphismmc.epimorphism.data.recipe.handler.BouleRecipeHandler;
 import com.epimorphismmc.epimorphism.data.recipe.handler.ComponentAsslineRecipeHandler;
 import com.epimorphismmc.epimorphism.data.recipe.handler.PartsRecipeHandler;
-import com.epimorphismmc.epimorphism.data.recipe.handler.WrapItemRecipeHandler;
 import com.epimorphismmc.epimorphism.data.recipe.machine.multi.ConcreteBackfillerMachineHandler;
 import com.epimorphismmc.epimorphism.data.recipe.machine.multi.SteamMachineHandler;
+import com.epimorphismmc.epimorphism.data.recipe.misc.ConcreteBackfillerRecipes;
+import com.epimorphismmc.epimorphism.data.recipe.misc.ConcreteRecipes;
 import com.epimorphismmc.epimorphism.data.recipe.misc.FuelRecipeHandler;
 import com.epimorphismmc.epimorphism.data.recipe.misc.LargeNaquadahReactorRecipeHandler;
 import com.epimorphismmc.epimorphism.data.recipe.misc.RadiationHatchRecipeHandler;
+import com.epimorphismmc.epimorphism.data.recipe.misc.WrapItemRecipes;
 
 import net.minecraft.data.recipes.FinishedRecipe;
 
@@ -37,7 +39,6 @@ public static void init(Consumer<FinishedRecipe> provider) {
         BouleRecipeHandler.init(provider);
         ComponentAsslineRecipeHandler.finish(provider);
         PartsRecipeHandler.init(provider);
-        WrapItemRecipeHandler.init(provider);
 
         /////////////////////////////////////////
         // *****       Misc Recipes      ***** //
@@ -45,6 +46,9 @@ public static void init(Consumer<FinishedRecipe> provider) {
         FuelRecipeHandler.init(provider);
         LargeNaquadahReactorRecipeHandler.init(provider);
         RadiationHatchRecipeHandler.init(provider);
+        ConcreteBackfillerRecipes.init(provider);
+        ConcreteRecipes.init(provider);
+        WrapItemRecipes.init(provider);
     }
 
     public static void remove(GTRecipeEvent.RemoveRecipe event) {}
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java b/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java
index 4fe4c3a..bffb149 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java
@@ -5,11 +5,11 @@
 import com.gregtechceu.gtceu.api.fluids.attribute.FluidAttributes;
 import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKeys;
 
-import static com.epimorphismmc.epimorphism.common.data.EPMaterials.Builder;
-import static com.epimorphismmc.epimorphism.common.data.EPMaterials.ConcentrateDragonBreath;
-import static com.epimorphismmc.epimorphism.common.data.EPMaterials.DragonBlood;
-import static com.epimorphismmc.epimorphism.common.data.EPMaterials.DragonBreath;
-import static com.epimorphismmc.epimorphism.common.data.EPMaterials.DragonTear;
+import static com.epimorphismmc.epimorphism.api.data.chemical.material.info.EPMaterialFlags.*;
+import static com.epimorphismmc.epimorphism.common.data.EPMaterials.*;
+import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialFlags.*;
+import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialIconSet.*;
+import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
 
 public class EPSecondDegreeMaterials {
     public static void register() {
@@ -39,5 +39,165 @@ public static void register() {
                 .iconSet(MaterialIconSet.DULL)
                 .buildAndRegister()
                 .setFormula("⚙", false);
+
+        ConcreteBlack = Builder("black_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0x202020)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteRed = Builder("red_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0xAA0000)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteGreen = Builder("green_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0x00AA00)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteBrown = Builder("brown_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0x604000)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteBlue = Builder("blue_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0x0000AA)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcretePurple = Builder("purple_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0xAA00AA)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteCyan = Builder("cyan_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0x00AAAA)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteLightGray = Builder("light_gray_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0xAAAAAA)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteGray = Builder("gray_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0x555555)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcretePink = Builder("pink_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0xFFC0C0)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteLime = Builder("lime_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0x80FF80)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteYellow = Builder("yellow_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0xFFFF00)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteLightBlue = Builder("light_blue_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0x6080FF)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteMagenta = Builder("magenta_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0xFF00FF)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteOrange = Builder("orange_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0xFF8000)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
+
+        ConcreteWhite = Builder("white_concrete")
+                .dust()
+                .liquid(new FluidBuilder().temperature(286))
+                .color(0xFFFFFF)
+                .secondaryColor(0xbbbaba)
+                .iconSet(ROUGH)
+                .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
+                .components(Stone, 1)
+                .buildAndRegister();
     }
 }
diff --git a/src/main/java/com/epimorphismmc/epimorphism/data/lang/MaterialLang.java b/src/main/java/com/epimorphismmc/epimorphism/data/lang/MaterialLang.java
index dd24b6d..bdc0f53 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/data/lang/MaterialLang.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/data/lang/MaterialLang.java
@@ -399,6 +399,22 @@ public static void init(MOLangProvider provider) {
         //        addCNMaterial(provider, HydrogenCyanide, "氰化氢");
         //        addCNMaterial(provider, SodiumCyanide, "氰化钠");
         //        addCNMaterial(provider, SodiumPerchlorate, "高氯酸钠");
+        addCNMaterial(provider, ConcreteWhite, "白色混凝土");
+        addCNMaterial(provider, ConcreteOrange, "橙色混凝土");
+        addCNMaterial(provider, ConcreteMagenta, "品红色混凝土");
+        addCNMaterial(provider, ConcreteLightBlue, "淡蓝色混凝土");
+        addCNMaterial(provider, ConcreteYellow, "黄色混凝土");
+        addCNMaterial(provider, ConcreteLime, "黄绿色混凝土");
+        addCNMaterial(provider, ConcretePink, "粉色混凝土");
+        addCNMaterial(provider, ConcreteGray, "灰色混凝土");
+        addCNMaterial(provider, ConcreteLightGray, "淡灰色混凝土");
+        addCNMaterial(provider, ConcreteCyan, "青色混凝土");
+        addCNMaterial(provider, ConcretePurple, "紫色混凝土");
+        addCNMaterial(provider, ConcreteBlue, "蓝色混凝土");
+        addCNMaterial(provider, ConcreteBrown, "棕色混凝土");
+        addCNMaterial(provider, ConcreteGreen, "绿色混凝土");
+        addCNMaterial(provider, ConcreteRed, "红色混凝土");
+        addCNMaterial(provider, ConcreteBlack, "黑色混凝土");
 
         // Second Degree Materials
         addCNMaterial(provider, DragonBreath, "龙息");
diff --git a/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java b/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java
index b627f2b..c99d6c4 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java
@@ -1,21 +1,34 @@
 package com.epimorphismmc.epimorphism.data.recipe.misc;
 
+import com.epimorphismmc.epimorphism.Epimorphism;
+import com.epimorphismmc.epimorphism.common.data.EPMaterials;
+
+import com.gregtechceu.gtceu.api.data.chemical.material.Material;
+
 import net.minecraft.data.recipes.FinishedRecipe;
 
 import java.util.function.Consumer;
 
 import static com.epimorphismmc.epimorphism.common.data.EPRecipeTypes.*;
 import static com.gregtechceu.gtceu.api.GTValues.*;
-import static com.gregtechceu.gtceu.common.data.GTBlocks.*;
+import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.*;
 import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
 
 public class ConcreteBackfillerRecipes {
 
     public static void init(Consumer<FinishedRecipe> provider) {
+        concrete(provider, Concrete);
+
+        for (Material concrete : EPMaterials.CONCRETES) {
+            concrete(provider, concrete);
+        }
+    }
+
+    private static void concrete(Consumer<FinishedRecipe> provider, Material material) {
         CONCRETE_BACKFILLER_RECIPES
-                .recipeBuilder("concrete")
-                .inputFluids(Concrete.getFluid(144))
-                .outputItems(LIGHT_CONCRETE)
+                .recipeBuilder(Epimorphism.id(material.getName()))
+                .inputFluids(material.getFluid(144))
+                .outputItems(block, material)
                 .EUt(EV)
                 .duration(20)
                 .save(provider);
diff --git a/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteRecipes.java b/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteRecipes.java
new file mode 100644
index 0000000..24ca905
--- /dev/null
+++ b/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteRecipes.java
@@ -0,0 +1,33 @@
+package com.epimorphismmc.epimorphism.data.recipe.misc;
+
+import com.epimorphismmc.epimorphism.Epimorphism;
+
+import net.minecraft.data.recipes.FinishedRecipe;
+import net.minecraft.world.item.DyeColor;
+import net.minecraftforge.common.Tags;
+
+import java.util.function.Consumer;
+
+import static com.epimorphismmc.epimorphism.common.data.EPMaterials.*;
+import static com.gregtechceu.gtceu.api.GTValues.*;
+import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
+import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.*;
+
+public class ConcreteRecipes {
+    public static void init(Consumer<FinishedRecipe> provider) {
+        for (int i = 0; i < DyeColor.values().length; i++) {
+            var color = DyeColor.values()[i];
+            String dyeName = color.getName();
+            MIXER_RECIPES
+                    .recipeBuilder(Epimorphism.id(dyeName + "_concrete"))
+                    .inputItems(Tags.Items.SAND, 4)
+                    .inputItems(Tags.Items.GRAVEL, 4)
+                    .inputFluids(CHEMICAL_DYES[color.ordinal()].getFluid(L))
+                    .inputFluids(Water.getFluid(1000))
+                    .outputFluids(CONCRETES[i].getFluid(144 * 8))
+                    .duration(200)
+                    .EUt(VA[ULV])
+                    .save(provider);
+        }
+    }
+}
diff --git a/src/main/java/com/epimorphismmc/epimorphism/data/recipe/handler/WrapItemRecipeHandler.java b/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/WrapItemRecipes.java
similarity index 51%
rename from src/main/java/com/epimorphismmc/epimorphism/data/recipe/handler/WrapItemRecipeHandler.java
rename to src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/WrapItemRecipes.java
index e6e5b83..386d123 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/data/recipe/handler/WrapItemRecipeHandler.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/WrapItemRecipes.java
@@ -1,26 +1,31 @@
-package com.epimorphismmc.epimorphism.data.recipe.handler;
+package com.epimorphismmc.epimorphism.data.recipe.misc;
 
-import com.epimorphismmc.epimorphism.common.data.items.EPWrapItem;
+import com.epimorphismmc.epimorphism.Epimorphism;
+
+import com.epimorphismmc.monomorphism.utility.RegisteredObjects;
 
-import com.gregtechceu.gtceu.common.data.GTMaterials;
 import com.gregtechceu.gtceu.common.data.GTRecipeTypes;
 
 import net.minecraft.data.recipes.FinishedRecipe;
 
 import java.util.function.Consumer;
 
+import static com.epimorphismmc.epimorphism.common.data.items.EPWrapItem.WRAP_CIRCUIT_MAP;
+import static com.epimorphismmc.epimorphism.common.data.items.EPWrapItem.WRAP_ITEM_MAP;
+import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
+
 /**
  * 封装物品相关配方
  */
-public class WrapItemRecipeHandler {
+public class WrapItemRecipes {
     public static void init(Consumer<FinishedRecipe> provider) {
-        EPWrapItem.WRAP_CIRCUIT_MAP.object2ObjectEntrySet().fastForEach(entry -> {
+        WRAP_CIRCUIT_MAP.object2ObjectEntrySet().fastForEach(entry -> {
             var item = entry.getValue().asItem();
             var tag = entry.getKey();
             GTRecipeTypes.ASSEMBLER_RECIPES
-                    .recipeBuilder("wrap_" + tag.location().getPath().replace('/', '_'))
+                    .recipeBuilder(Epimorphism.id("wrap_" + tag.location().getPath().replace('/', '_')))
                     .inputItems(tag, 16)
-                    .inputFluids(GTMaterials.Polyethylene.getFluid(72))
+                    .inputFluids(Polyethylene.getFluid(72))
                     .circuitMeta(16)
                     .outputItems(item, 1)
                     .duration(600)
@@ -28,13 +33,14 @@ public static void init(Consumer<FinishedRecipe> provider) {
                     .save(provider);
         });
 
-        EPWrapItem.WRAP_ITEM_MAP.object2ObjectEntrySet().fastForEach(entry -> {
+        WRAP_ITEM_MAP.object2ObjectEntrySet().fastForEach(entry -> {
             var item = entry.getValue().asItem();
             var wrappedItem = entry.getKey().asItem();
             GTRecipeTypes.ASSEMBLER_RECIPES
-                    .recipeBuilder("wrap_" + wrappedItem.asItem().getDescriptionId())
+                    .recipeBuilder(Epimorphism.id(
+                            "wrap_" + RegisteredObjects.getKeyOrThrow(wrappedItem).getPath()))
                     .inputItems(wrappedItem, 16)
-                    .inputFluids(GTMaterials.Polyethylene.getFluid(72))
+                    .inputFluids(Polyethylene.getFluid(72))
                     .circuitMeta(16)
                     .outputItems(item, 1)
                     .duration(600)

From 4aa84641b8334bb404bfba79e7f4dff97256a08c Mon Sep 17 00:00:00 2001
From: Gate Guardian <xtzcy76040108@163.com>
Date: Fri, 9 Aug 2024 19:45:25 +0800
Subject: [PATCH 3/4] resolve conflicts

---
 .../epimorphism/common/data/EPMachines.java      |  8 ++++++--
 .../epimorphism/common/data/EPRecipes.java       | 16 +++++-----------
 .../data/materials/EPSecondDegreeMaterials.java  |  4 ++++
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java
index 65ec66e..2ed8b6c 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java
@@ -124,11 +124,15 @@
 
 import static com.epimorphismmc.epimorphism.EpimorphismCommon.registrate;
 import static com.epimorphismmc.epimorphism.api.pattern.EPPredicates.direction;
-import static com.epimorphismmc.epimorphism.common.block.BlockMaps.*;
+import static com.epimorphismmc.epimorphism.common.block.BlockMaps.ALL_CP_CASINGS;
+import static com.epimorphismmc.epimorphism.common.block.BlockMaps.ALL_CP_TUBES;
+import static com.epimorphismmc.epimorphism.common.block.BlockMaps.ALL_FIELD_BLOCKS;
+import static com.epimorphismmc.epimorphism.common.block.BlockMaps.ALL_FIREBOXS;
 import static com.epimorphismmc.epimorphism.common.data.EPRecipeTypes.*;
 import static com.epimorphismmc.monomorphism.block.MOBlockMaps.ALL_COIL_BLOCKS;
 import static com.epimorphismmc.monomorphism.block.MOBlockMaps.ALL_MACHINE_CASINGS;
-import static com.epimorphismmc.monomorphism.pattern.MOPredicates.*;
+import static com.epimorphismmc.monomorphism.pattern.MOPredicates.coilBlock;
+import static com.epimorphismmc.monomorphism.pattern.MOPredicates.machineCasingBlock;
 import static com.gregtechceu.gtceu.api.GTValues.*;
 import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.*;
 import static com.gregtechceu.gtceu.api.machine.multiblock.PartAbility.*;
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipes.java b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipes.java
index 6b2cb4b..6e350ba 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipes.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPRecipes.java
@@ -6,21 +6,15 @@
 import com.epimorphismmc.epimorphism.data.recipe.handler.BouleRecipeHandler;
 import com.epimorphismmc.epimorphism.data.recipe.handler.ComponentAssemblyLineRecipeHandler;
 import com.epimorphismmc.epimorphism.data.recipe.handler.PartsRecipeHandler;
-import com.epimorphismmc.epimorphism.data.recipe.handler.WrapItemRecipeHandler;
 import com.epimorphismmc.epimorphism.data.recipe.machine.multi.ComponentAssemblyLineMachineRecipe;
 import com.epimorphismmc.epimorphism.data.recipe.machine.multi.ConcreteBackfillerMachineRecipe;
 import com.epimorphismmc.epimorphism.data.recipe.machine.multi.SteamMachineRecipe;
 import com.epimorphismmc.epimorphism.data.recipe.misc.BorosilicateGlassRecipes;
+import com.epimorphismmc.epimorphism.data.recipe.misc.ConcreteBackfillerRecipes;
+import com.epimorphismmc.epimorphism.data.recipe.misc.ConcreteRecipes;
 import com.epimorphismmc.epimorphism.data.recipe.misc.FuelRecipes;
 import com.epimorphismmc.epimorphism.data.recipe.misc.LargeNaquadahReactorRecipes;
 import com.epimorphismmc.epimorphism.data.recipe.misc.RadiationHatchRecipes;
-import com.epimorphismmc.epimorphism.data.recipe.machine.multi.ConcreteBackfillerMachineHandler;
-import com.epimorphismmc.epimorphism.data.recipe.machine.multi.SteamMachineHandler;
-import com.epimorphismmc.epimorphism.data.recipe.misc.ConcreteBackfillerRecipes;
-import com.epimorphismmc.epimorphism.data.recipe.misc.ConcreteRecipes;
-import com.epimorphismmc.epimorphism.data.recipe.misc.FuelRecipeHandler;
-import com.epimorphismmc.epimorphism.data.recipe.misc.LargeNaquadahReactorRecipeHandler;
-import com.epimorphismmc.epimorphism.data.recipe.misc.RadiationHatchRecipeHandler;
 import com.epimorphismmc.epimorphism.data.recipe.misc.WrapItemRecipes;
 
 import net.minecraft.data.recipes.FinishedRecipe;
@@ -52,9 +46,9 @@ public static void init(Consumer<FinishedRecipe> provider) {
         /////////////////////////////////////////
         // *****       Misc Recipes      ***** //
         /////////////////////////////////////////
-        FuelRecipeHandler.init(provider);
-        LargeNaquadahReactorRecipeHandler.init(provider);
-        RadiationHatchRecipeHandler.init(provider);
+        FuelRecipes.init(provider);
+        LargeNaquadahReactorRecipes.init(provider);
+        RadiationHatchRecipes.init(provider);
         ConcreteBackfillerRecipes.init(provider);
         ConcreteRecipes.init(provider);
         WrapItemRecipes.init(provider);
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java b/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java
index 3f4bf3b..bffb149 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java
@@ -5,7 +5,11 @@
 import com.gregtechceu.gtceu.api.fluids.attribute.FluidAttributes;
 import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKeys;
 
+import static com.epimorphismmc.epimorphism.api.data.chemical.material.info.EPMaterialFlags.*;
 import static com.epimorphismmc.epimorphism.common.data.EPMaterials.*;
+import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialFlags.*;
+import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialIconSet.*;
+import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
 
 public class EPSecondDegreeMaterials {
     public static void register() {

From fb797272bf7e9d3e4a8af1a940f49328317eeb2b Mon Sep 17 00:00:00 2001
From: Gate Guardian <xtzcy76040108@163.com>
Date: Sat, 10 Aug 2024 07:37:58 +0800
Subject: [PATCH 4/4] refactor

---
 ...ler.java => ForgeClientEventListener.java} |   2 +-
 ...ler.java => ForgeCommonEventListener.java} |   2 +-
 .../epimorphism/common/data/EPMachines.java   |   2 +-
 .../materials/EPSecondDegreeMaterials.java    |  16 --
 .../electric/ConcreteBackfillerMachine.java   |  54 ++---
 .../trait/ConcreteBackfillerLogic.java        | 206 +++++++++---------
 .../misc/ConcreteBackfillerRecipes.java       |   6 +-
 7 files changed, 123 insertions(+), 165 deletions(-)
 rename src/main/java/com/epimorphismmc/epimorphism/client/{ForgeClientEventHandler.java => ForgeClientEventListener.java} (95%)
 rename src/main/java/com/epimorphismmc/epimorphism/common/{ForgeCommonEventHandler.java => ForgeCommonEventListener.java} (99%)

diff --git a/src/main/java/com/epimorphismmc/epimorphism/client/ForgeClientEventHandler.java b/src/main/java/com/epimorphismmc/epimorphism/client/ForgeClientEventListener.java
similarity index 95%
rename from src/main/java/com/epimorphismmc/epimorphism/client/ForgeClientEventHandler.java
rename to src/main/java/com/epimorphismmc/epimorphism/client/ForgeClientEventListener.java
index 4ccd76b..8286ea3 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/client/ForgeClientEventHandler.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/client/ForgeClientEventListener.java
@@ -14,7 +14,7 @@
         bus = Mod.EventBusSubscriber.Bus.FORGE,
         value = Dist.CLIENT)
 @OnlyIn(Dist.CLIENT)
-public class ForgeClientEventHandler {
+public class ForgeClientEventListener {
 
     @SubscribeEvent
     public static void onRenderWorldLast(RenderLevelStageEvent event) {
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/ForgeCommonEventHandler.java b/src/main/java/com/epimorphismmc/epimorphism/common/ForgeCommonEventListener.java
similarity index 99%
rename from src/main/java/com/epimorphismmc/epimorphism/common/ForgeCommonEventHandler.java
rename to src/main/java/com/epimorphismmc/epimorphism/common/ForgeCommonEventListener.java
index a481848..c25ef89 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/ForgeCommonEventHandler.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/ForgeCommonEventListener.java
@@ -27,7 +27,7 @@
 import static com.epimorphismmc.epimorphism.common.data.EPItems.*;
 
 @Mod.EventBusSubscriber(modid = Epimorphism.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
-public class ForgeCommonEventHandler {
+public class ForgeCommonEventListener {
 
     @SubscribeEvent
     public static void onPlayerLeftClickBlock(PlayerInteractEvent.LeftClickBlock event) {
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java
index 2ed8b6c..40aadac 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/data/EPMachines.java
@@ -2221,7 +2221,7 @@ public class EPMachines {
     public static final MultiblockMachineDefinition[] CONCRETE_BACKFILLER = registerTieredEPMultis(
             "concrete_backfiller",
             (holder, tier) ->
-                    new ConcreteBackfillerMachine(holder, tier, 64 / tier, (int) Math.pow(2, tier - 1)),
+                    new ConcreteBackfillerMachine(holder, tier, (int) Math.pow(2, tier - 1)),
             (tier, builder) -> builder
                     .langValue("Concrete Backfiller")
                     .tooltips(
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java b/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java
index bffb149..2c4163c 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/data/materials/EPSecondDegreeMaterials.java
@@ -44,7 +44,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0x202020)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -54,7 +53,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0xAA0000)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -64,7 +62,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0x00AA00)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -74,7 +71,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0x604000)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -84,7 +80,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0x0000AA)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -94,7 +89,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0xAA00AA)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -104,7 +98,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0x00AAAA)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -114,7 +107,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0xAAAAAA)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -124,7 +116,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0x555555)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -134,7 +125,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0xFFC0C0)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -144,7 +134,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0x80FF80)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -154,7 +143,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0xFFFF00)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -164,7 +152,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0x6080FF)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -174,7 +161,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0xFF00FF)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -184,7 +170,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0xFF8000)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
@@ -194,7 +179,6 @@ public static void register() {
                 .dust()
                 .liquid(new FluidBuilder().temperature(286))
                 .color(0xFFFFFF)
-                .secondaryColor(0xbbbaba)
                 .iconSet(ROUGH)
                 .flags(DISABLE_SMALL_DUST, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES)
                 .components(Stone, 1)
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/machine/multiblock/electric/ConcreteBackfillerMachine.java b/src/main/java/com/epimorphismmc/epimorphism/common/machine/multiblock/electric/ConcreteBackfillerMachine.java
index e731653..4568260 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/machine/multiblock/electric/ConcreteBackfillerMachine.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/machine/multiblock/electric/ConcreteBackfillerMachine.java
@@ -9,10 +9,10 @@
 import com.gregtechceu.gtceu.api.machine.multiblock.MultiblockDisplayText;
 import com.gregtechceu.gtceu.api.machine.multiblock.WorkableElectricMultiblockMachine;
 import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic;
+import com.gregtechceu.gtceu.api.recipe.GTRecipe;
 import com.gregtechceu.gtceu.common.data.GTBlocks;
 import com.gregtechceu.gtceu.common.data.GTMaterials;
 import com.gregtechceu.gtceu.common.item.PortableScannerBehavior;
-import com.gregtechceu.gtceu.utils.GTUtil;
 
 import net.minecraft.ChatFormatting;
 import net.minecraft.MethodsReturnNonnullByDefault;
@@ -25,6 +25,7 @@
 import net.minecraft.world.phys.BlockHitResult;
 
 import lombok.Getter;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -43,8 +44,8 @@ public class ConcreteBackfillerMachine extends WorkableElectricMultiblockMachine
     private final int tier;
 
     public ConcreteBackfillerMachine(
-            IMachineBlockEntity holder, int tier, int speed, int maximumChunkDiameter) {
-        super(holder, speed, maximumChunkDiameter);
+            IMachineBlockEntity holder, int tier, int maximumChunkDiameter) {
+        super(holder, maximumChunkDiameter);
         this.tier = tier;
     }
 
@@ -55,10 +56,6 @@ public ConcreteBackfillerMachine(
     @Override
     public void onStructureFormed() {
         super.onStructureFormed();
-        getRecipeLogic().setVoltageTier(GTUtil.getTierByVoltage(energyContainer.getInputVoltage()));
-        getRecipeLogic()
-                .setOverclockAmount(Math.max(
-                        1, GTUtil.getTierByVoltage(this.energyContainer.getInputVoltage()) - this.tier));
         getRecipeLogic().initPos();
     }
 
@@ -92,11 +89,10 @@ public List<Component> getDataInfo(PortableScannerBehavior.DisplayMode mode) {
 
     @Override
     protected RecipeLogic createRecipeLogic(Object... args) {
-        if (args[args.length - 2] instanceof Integer speed
-                && args[args.length - 1] instanceof Integer maxRadius) {
-            return new ConcreteBackfillerLogic(this, speed, maxRadius * CHUNK_LENGTH / 2);
+        if (args[args.length - 1] instanceof Integer maxRadius) {
+            return new ConcreteBackfillerLogic(this, maxRadius * CHUNK_LENGTH / 2);
         } else {
-            throw new IllegalArgumentException("ConcreteBackfiller need args [speed, maxRadius]");
+            throw new IllegalArgumentException("ConcreteBackfiller need args [maxRadius]");
         }
     }
 
@@ -107,31 +103,17 @@ public ConcreteBackfillerLogic getRecipeLogic() {
 
     @Override
     public long getMaxVoltage() {
-        return GTValues.V[getEnergyTier()];
+        return Math.max(GTValues.V[tier], super.getMaxVoltage());
     }
 
-    public int getEnergyTier() {
-        if (energyContainer == null) return this.tier;
-        return Math.min(
-                this.tier + 1,
-                Math.max(this.tier, GTUtil.getFloorTierByVoltage(energyContainer.getInputVoltage())));
+    @Override
+    public long getOverclockVoltage() {
+        return Math.max(GTValues.V[tier], super.getOverclockVoltage());
     }
 
-    public boolean drainEnergy(boolean simulate) {
-        if (energyContainer != null && energyContainer.getEnergyStored() > 0) {
-            long energyToDrain = GTValues.VA[getEnergyTier()];
-            long resultEnergy = energyContainer.getEnergyStored() - energyToDrain;
-            if (resultEnergy >= 0L && resultEnergy <= energyContainer.getEnergyCapacity()) {
-                if (!simulate) {
-                    energyContainer.changeEnergy(-energyToDrain);
-                }
-                return true;
-            } else {
-                return false;
-            }
-        } else {
-            return false;
-        }
+    @Override
+    public @Nullable GTRecipe fullModifyRecipe(GTRecipe recipe) {
+        return doModifyRecipe(getRecipeLogic().modifyRecipe(recipe));
     }
 
     @Override
@@ -150,7 +132,6 @@ public void addDisplayText(List<Component> textList) {
         MultiblockDisplayText.builder(textList, isFormed())
                 .setWorkingStatus(getRecipeLogic().isWorkingEnabled(), getRecipeLogic().isActive())
                 .addEnergyUsageLine(energyContainer)
-                .addParallelsLine(getRecipeLogic().getOverclockAmount())
                 .addWorkingStatusLine()
                 .addProgressLine(getRecipeLogic().getProgressPercent());
         getDefinition().getAdditionalDisplay().accept(this, textList);
@@ -196,7 +177,9 @@ public void addDisplayText(List<Component> textList) {
     @Override
     protected InteractionResult onScrewdriverClick(
             Player playerIn, InteractionHand hand, Direction gridSide, BlockHitResult hitResult) {
-        if (isRemote() || !this.isFormed()) return InteractionResult.SUCCESS;
+        if (!isFormed()) return InteractionResult.PASS;
+
+        if (isRemote()) return InteractionResult.sidedSuccess(true);
 
         if (!isActive()) {
             int currentRadius = getRecipeLogic().getCurrentRadius();
@@ -215,7 +198,6 @@ protected InteractionResult onScrewdriverClick(
             playerIn.sendSystemMessage(Component.translatable("gtceu.multiblock.large_miner.errorradius")
                     .withStyle(ChatFormatting.RED));
         }
-
-        return InteractionResult.SUCCESS;
+        return InteractionResult.sidedSuccess(false);
     }
 }
diff --git a/src/main/java/com/epimorphismmc/epimorphism/common/machine/trait/ConcreteBackfillerLogic.java b/src/main/java/com/epimorphismmc/epimorphism/common/machine/trait/ConcreteBackfillerLogic.java
index 29e9a5a..e97d479 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/common/machine/trait/ConcreteBackfillerLogic.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/common/machine/trait/ConcreteBackfillerLogic.java
@@ -7,8 +7,8 @@
 import com.gregtechceu.gtceu.api.capability.recipe.IO;
 import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic;
 import com.gregtechceu.gtceu.api.recipe.GTRecipe;
+import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
 import com.gregtechceu.gtceu.api.recipe.RecipeHelper;
-import com.gregtechceu.gtceu.api.recipe.modifier.ParallelLogic;
 import com.gregtechceu.gtceu.common.block.SurfaceRockBlock;
 
 import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted;
@@ -22,12 +22,12 @@
 
 import lombok.Getter;
 import lombok.Setter;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedList;
 
-import javax.annotation.Nullable;
 import javax.annotation.ParametersAreNonnullByDefault;
 
 @ParametersAreNonnullByDefault
@@ -44,20 +44,9 @@ public class ConcreteBackfillerLogic extends RecipeLogic {
 
     private final ConcreteBackfillerMachine filler;
 
-    @Getter
-    private final int speed;
-
     @Getter
     private final int maximumRadius;
 
-    @Setter
-    @Getter
-    private int voltageTier;
-
-    @Getter
-    @Setter
-    private int overclockAmount = 0;
-
     private final LinkedList<BlockPos> posesToFill = new LinkedList<>();
 
     @Getter
@@ -111,11 +100,13 @@ public class ConcreteBackfillerLogic extends RecipeLogic {
     @Persisted
     private boolean isDone;
 
-    public ConcreteBackfillerLogic(ConcreteBackfillerMachine machine, int speed, int maximumRadius) {
+    @Persisted
+    @Nullable
+    private BlockState lastBlock;
+
+    public ConcreteBackfillerLogic(ConcreteBackfillerMachine machine, int maximumRadius) {
         super(machine);
         this.filler = machine;
-        this.speed = speed;
-        this.duration = speed;
         this.maximumRadius = maximumRadius;
         this.currentRadius = maximumRadius;
     }
@@ -128,102 +119,30 @@ public ManagedFieldHolder getFieldHolder() {
     @Override
     public void resetRecipeLogic() {
         super.resetRecipeLogic();
-        duration = speed;
+        this.lastBlock = null;
         resetArea();
     }
 
     @Override
     public void serverTick() {
-        // main logic
-        if (!isSuspend() && filler.getLevel() instanceof ServerLevel level && checkCanFill()) {
-
-            var matches = searchRecipe();
-            while (matches != null && matches.hasNext()) {
-                GTRecipe match = matches.next();
-                if (match == null) continue;
-
-                int parallel = ParallelLogic.getMaxRecipeMultiplier(match, filler, getOverclockAmount());
-            }
-
-            // checkCanFill already check energy, needn't simulate
-            filler.drainEnergy(false);
-            setStatus(Status.WORKING);
-
-            checkPosToFill();
-
-            if (progress >= duration && !posesToFill.isEmpty()) {
-                for (int i = 0; i < getOverclockAmount(); i++) {
-                    if (posesToFill.isEmpty()) {
-                        break;
-                    }
-                    BlockPos pos = posesToFill.getFirst();
-                    BlockState blockState = level.getBlockState(pos);
-                    // check make sure here still can fill
-                    while (!checkStateCanFill(blockState)) {
-                        posesToFill.removeFirst();
-                        if (posesToFill.isEmpty()) {
-                            break;
-                        }
-                        pos = posesToFill.getFirst();
-                        blockState = level.getBlockState(pos);
-                    }
-
-                    // has place to fill
-                    if (checkStateCanFill(blockState)) {
-                        fillAndDrainFluid(pos, level);
-                        posesToFill.removeFirst();
-                    }
-                }
-                progress = 0;
-            }
-            progress++;
-            totalContinuousRunningTime++;
-
-            if (posesToFill.isEmpty()) {
-                x = fillX;
-                y = fillY;
-                z = fillZ;
-
-                // blocks may change during machine working, so let's check again
-                posesToFill.addAll(getPosesToFill());
-                if (posesToFill.isEmpty()) {
-                    isDone = true;
-                    setStatus(Status.IDLE);
-                }
-            }
-        } else {
-            // machine isn't working enabled
-            this.setStatus(Status.IDLE);
-            if (subscription != null) {
-                subscription.unsubscribe();
-                subscription = null;
-            }
+        if (!isSuspend() && checkCoordinatesInvalid()) {
+            initPos();
         }
+       super.serverTick();
     }
 
-    private void fillAndDrainFluid(BlockPos pos, ServerLevel level) {
-        var matches = searchRecipe();
-        while (matches != null && matches.hasNext()) {
-            GTRecipe match = matches.next();
-            if (match == null) continue;
-
-            if (match.matchRecipeContents(IO.IN, machine, match.inputs).isSuccess()) {
-                if (handleRecipeIO(match, IO.IN)) {
-                    var item = RecipeHelper.getOutputItems(match).get(0).getItem();
-                    if (item instanceof BlockItem blockItem) {
-                        level.setBlockAndUpdate(pos, blockItem.getBlock().defaultBlockState());
-                        fillX = pos.getX();
-                        fillY = pos.getY();
-                        fillZ = pos.getZ();
-                        return;
-                    }
-                }
-            }
-        }
+    @Override
+    public boolean isSuspend() {
+        return super.isSuspend() || isDone;
     }
 
+    //////////////////////////////////////
+    // ********* Recipe Handle ******** //
+    //////////////////////////////////////
+
     @Override
     protected @Nullable Iterator<GTRecipe> searchRecipe() {
+        // the same as the super method, but only matches the recipe inputs
         if (!machine.hasProxies()) return null;
         var iterator = machine
                 .getRecipeType()
@@ -241,13 +160,93 @@ private void fillAndDrainFluid(BlockPos pos, ServerLevel level) {
             any = true;
             break;
         }
+
         if (any) {
             iterator.reset();
             return iterator;
         }
+
+        for (GTRecipeType.ICustomRecipeLogic logic : machine.getRecipeType().getCustomRecipeLogicRunners()) {
+            GTRecipe recipe = logic.createCustomRecipe(machine);
+            if (recipe != null) return Collections.singleton(recipe).iterator();
+        }
         return Collections.emptyIterator();
     }
 
+    public GTRecipe modifyRecipe(GTRecipe recipe) {
+        if (!recipe.outputs.isEmpty()) {
+            // must copy because this is the origin recipe
+            recipe = recipe.copy();
+            var item = RecipeHelper.getOutputItems(recipe).get(0).getItem();
+            if (item instanceof BlockItem blockItem) {
+                this.lastBlock = blockItem.getBlock().defaultBlockState();
+            }
+            recipe.outputs.clear();
+        }
+        return recipe;
+    }
+
+    @Override
+    public void setupRecipe(GTRecipe recipe) {
+        checkPosToFill();
+        if (!posesToFill.isEmpty()) {
+            super.setupRecipe(recipe);
+        }
+    }
+
+    @Override
+    protected boolean handleRecipeIO(GTRecipe recipe, IO io) {
+        if (io == IO.OUT) {
+            if (!posesToFill.isEmpty()) {
+                this.fillState();
+            }
+
+            if (posesToFill.isEmpty()) {
+                x = fillX;
+                y = fillY;
+                z = fillZ;
+
+                // blocks may change during machine working, so let's check again
+                posesToFill.addAll(getPosesToFill());
+                if (posesToFill.isEmpty()) {
+                    this.isDone = true;
+                    // do not try the last recipe again
+                    this.recipeDirty = true;
+                }
+            }
+            return true;
+        }
+        return super.handleRecipeIO(recipe, io);
+    }
+
+    //////////////////////////////////////
+    // *********** Backfill *********** //
+    //////////////////////////////////////
+
+    private void fillState() {
+        if (filler.getLevel() instanceof ServerLevel level) {
+            BlockPos pos = posesToFill.getFirst();
+            BlockState blockState = level.getBlockState(pos);
+            // check make sure here still can fill
+            while (!checkStateCanFill(blockState)) {
+                posesToFill.removeFirst();
+                if (posesToFill.isEmpty()) {
+                    return;
+                }
+                pos = posesToFill.getFirst();
+                blockState = level.getBlockState(pos);
+            }
+
+            if (lastBlock != null) {
+                level.setBlockAndUpdate(pos, lastBlock);
+                fillX = pos.getX();
+                fillY = pos.getY();
+                fillZ = pos.getZ();
+            }
+            posesToFill.removeFirst();
+        }
+    }
+
     public void initPos() {
         this.initPos(getCenterPos(), currentRadius);
     }
@@ -327,13 +326,6 @@ private boolean checkCoordinatesInvalid() {
         return x == Integer.MAX_VALUE && y == Integer.MAX_VALUE && z == Integer.MAX_VALUE;
     }
 
-    private boolean checkCanFill() {
-        if (!isDone() && checkCoordinatesInvalid()) {
-            initPos();
-        }
-        return !isDone;
-    }
-
     public void resetArea() {
         initPos();
         if (this.isDone) this.setWorkingEnabled(false);
diff --git a/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java b/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java
index c99d6c4..ecb0bbc 100644
--- a/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java
+++ b/src/main/java/com/epimorphismmc/epimorphism/data/recipe/misc/ConcreteBackfillerRecipes.java
@@ -10,7 +10,7 @@
 import java.util.function.Consumer;
 
 import static com.epimorphismmc.epimorphism.common.data.EPRecipeTypes.*;
-import static com.gregtechceu.gtceu.api.GTValues.*;
+import static com.epimorphismmc.epimorphism.data.recipe.EPRecipeUtil.second;
 import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.*;
 import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
 
@@ -29,8 +29,8 @@ private static void concrete(Consumer<FinishedRecipe> provider, Material materia
                 .recipeBuilder(Epimorphism.id(material.getName()))
                 .inputFluids(material.getFluid(144))
                 .outputItems(block, material)
-                .EUt(EV)
-                .duration(20)
+                .EUt(96)
+                .duration(second(3))
                 .save(provider);
     }
 }