diff --git a/.github/workflows/head.yml b/.github/workflows/head.yml
index e8c9af5..1ff9faa 100644
--- a/.github/workflows/head.yml
+++ b/.github/workflows/head.yml
@@ -22,6 +22,8 @@ jobs:
with:
java-version: 17
- uses: gradle/gradle-build-action@v2
+ with:
+ cache-read-only: ${{ github.repository != 'badasintended/megane' }}
- run: |
chmod +x setup.sh
./setup.sh
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e48ec3a..dd1f0cf 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -15,6 +15,8 @@ jobs:
with:
java-version: 17
- uses: gradle/gradle-build-action@v2
+ with:
+ cache-read-only: true
- run: |
chmod +x setup.sh
./setup.sh
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 0178eab..2e9fab5 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -11,7 +11,7 @@ repositories {
}
dependencies {
- implementation("fabric-loom:fabric-loom.gradle.plugin:0.12.+")
+ implementation("fabric-loom:fabric-loom.gradle.plugin:1.0.+")
implementation("com.modrinth.minotaur:Minotaur:2.2.1")
implementation("com.github.deirn:CurseForgeGradle:c693018f92")
implementation("com.google.code.gson:gson:2.9.1")
diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt
index f3ac807..16dd6c9 100644
--- a/buildSrc/src/main/kotlin/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/Dependencies.kt
@@ -9,19 +9,19 @@ object versions {
object deps {
val minecraft = "com.mojang:minecraft:${versions.minecraft}"
val yarn = "net.fabricmc:yarn:1.18.2+build.3:v2"
- val fabricLoader = "net.fabricmc:fabric-loader:0.14.7"
+ val fabricLoader = "net.fabricmc:fabric-loader:0.14.9"
- val wthit = "mcp.mobius.waila:wthit:fabric-4.12.0"
+ val wthit = "mcp.mobius.waila:wthit:fabric-4.13.3"
- val ae2 = "appeng:appliedenergistics2-fabric:11.1.5"
+ val ae2 = "appeng:appliedenergistics2-fabric:11.1.6"
val alloyForge = "maven.modrinth:jhl28YkY:2.0.13+1.18"
val create = "com.simibubi:Create:0.5.0c-708"
val clothConfig = "me.shedaniel.cloth:cloth-config-fabric:6.2.62"
val extraGen = "maven.modrinth:VXtwLg17:1.2.1-BETA+1.18"
val fabricApi = "net.fabricmc.fabric-api:fabric-api:0.58.0+1.18.2"
- val flk = "net.fabricmc:fabric-language-kotlin:1.8.2+kotlin.1.7.10"
+ val flk = "net.fabricmc:fabric-language-kotlin:1.8.3+kotlin.1.7.10"
val kibe = "maven.modrinth:OvlwmUdC:1.9.9-BETA+1.18"
- val modernDynamics = "maven.modrinth:fMpvLrnF:0.2.4-beta"
+ val modernDynamics = "maven.modrinth:fMpvLrnF:0.2.5-beta"
val modmenu = "com.terraformersmc:modmenu:3.2.3"
val noIndium = "me.luligabi:NoIndium:1.0.2+1.18.2"
val owo = "io.wispforest:owo-lib:0.7.2-no-cme+1.18"
diff --git a/module-base/api/src/main/java/lol/bai/megane/api/MeganeModule.java b/module-base/api/src/main/java/lol/bai/megane/api/MeganeModule.java
index cfd04ee..a936499 100644
--- a/module-base/api/src/main/java/lol/bai/megane/api/MeganeModule.java
+++ b/module-base/api/src/main/java/lol/bai/megane/api/MeganeModule.java
@@ -5,9 +5,15 @@
public interface MeganeModule {
+ /**
+ * Register common-sided providers here.
+ */
default void registerCommon(CommonRegistrar registrar) {
}
+ /**
+ * Register client-sided providers here.
+ */
default void registerClient(ClientRegistrar registrar) {
}
diff --git a/module-base/api/src/main/java/lol/bai/megane/api/provider/EnergyInfoProvider.java b/module-base/api/src/main/java/lol/bai/megane/api/provider/EnergyInfoProvider.java
index 474a78c..31d2995 100644
--- a/module-base/api/src/main/java/lol/bai/megane/api/provider/EnergyInfoProvider.java
+++ b/module-base/api/src/main/java/lol/bai/megane/api/provider/EnergyInfoProvider.java
@@ -1,8 +1,7 @@
package lol.bai.megane.api.provider;
-import javax.annotation.Nullable;
-
import lol.bai.megane.api.registry.ClientRegistrar;
+import lol.bai.megane.api.util.BarFormat;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
@@ -35,15 +34,23 @@ public Text getName() {
return DEFAULT_NAME;
}
+ /**
+ * Returns the format of the number on the bar.
+ */
+ public BarFormat getFormat() {
+ return BarFormat.FRACTION;
+ }
+
/**
* Returns the color of the energy bar.
*/
public abstract int getColor();
/**
- * Returns the unit of the energy, or {@code null} if it doesn't have one.
+ * Returns the unit of the energy.
*/
- @Nullable
- public abstract String getUnit();
+ public String getUnit() {
+ return "E";
+ }
}
diff --git a/module-base/api/src/main/java/lol/bai/megane/api/provider/EnergyProvider.java b/module-base/api/src/main/java/lol/bai/megane/api/provider/EnergyProvider.java
index c1c6fc9..f0382b8 100644
--- a/module-base/api/src/main/java/lol/bai/megane/api/provider/EnergyProvider.java
+++ b/module-base/api/src/main/java/lol/bai/megane/api/provider/EnergyProvider.java
@@ -29,7 +29,7 @@ public boolean hasEnergy() {
/**
* Returns how much the capacity of the storage.
*
- * Return {@code -1} to mark this as unlimited capacity.
+ * Return {@code -1} to mark this doesn't have a capacity.
*/
public abstract long getMax();
diff --git a/module-base/api/src/main/java/lol/bai/megane/api/provider/base/IoLessProgressProvider.java b/module-base/api/src/main/java/lol/bai/megane/api/provider/base/IoLessProgressProvider.java
new file mode 100644
index 0000000..8177d77
--- /dev/null
+++ b/module-base/api/src/main/java/lol/bai/megane/api/provider/base/IoLessProgressProvider.java
@@ -0,0 +1,29 @@
+package lol.bai.megane.api.provider.base;
+
+import lol.bai.megane.api.provider.ProgressProvider;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+public abstract class IoLessProgressProvider extends ProgressProvider {
+
+ @Override
+ public int getInputSlotCount() {
+ return 0;
+ }
+
+ @Override
+ public int getOutputSlotCount() {
+ return 0;
+ }
+
+ @Override
+ public @NotNull ItemStack getInputStack(int slot) {
+ return ItemStack.EMPTY;
+ }
+
+ @Override
+ public @NotNull ItemStack getOutputStack(int slot) {
+ return ItemStack.EMPTY;
+ }
+
+}
diff --git a/module-base/api/src/main/java/lol/bai/megane/api/util/BarFormat.java b/module-base/api/src/main/java/lol/bai/megane/api/util/BarFormat.java
new file mode 100644
index 0000000..e048653
--- /dev/null
+++ b/module-base/api/src/main/java/lol/bai/megane/api/util/BarFormat.java
@@ -0,0 +1,6 @@
+package lol.bai.megane.api.util;
+
+public enum BarFormat {
+ FRACTION,
+ PERCENT
+}
diff --git a/module-base/runtime/src/main/java/lol/bai/megane/runtime/Megane.java b/module-base/runtime/src/main/java/lol/bai/megane/runtime/Megane.java
index d9caba2..1f499fa 100644
--- a/module-base/runtime/src/main/java/lol/bai/megane/runtime/Megane.java
+++ b/module-base/runtime/src/main/java/lol/bai/megane/runtime/Megane.java
@@ -122,8 +122,9 @@ public void register(IRegistrar r) {
LOGGER.info("[megane] Loading {} from {}", className, modId);
MeganeModule entry = (MeganeModule) Class.forName(className).getDeclaredConstructor().newInstance();
entry.registerCommon(Registrar.INSTANCE);
- if (loader.getEnvironmentType() == EnvType.CLIENT)
+ if (loader.getEnvironmentType() == EnvType.CLIENT) {
entry.registerClient(Registrar.INSTANCE);
+ }
} catch (Throwable t) {
LOGGER.error("[megane] error when loading {} from {}", className, modId);
t.printStackTrace();
diff --git a/module-base/runtime/src/main/java/lol/bai/megane/runtime/component/BarComponent.java b/module-base/runtime/src/main/java/lol/bai/megane/runtime/component/StorageAmountComponent.java
similarity index 54%
rename from module-base/runtime/src/main/java/lol/bai/megane/runtime/component/BarComponent.java
rename to module-base/runtime/src/main/java/lol/bai/megane/runtime/component/StorageAmountComponent.java
index 1263201..5e40d5f 100644
--- a/module-base/runtime/src/main/java/lol/bai/megane/runtime/component/BarComponent.java
+++ b/module-base/runtime/src/main/java/lol/bai/megane/runtime/component/StorageAmountComponent.java
@@ -3,6 +3,7 @@
import java.math.RoundingMode;
import java.text.DecimalFormat;
+import lol.bai.megane.api.util.BarFormat;
import lol.bai.megane.runtime.util.MeganeUtils;
import mcp.mobius.waila.api.ITooltipComponent;
import net.minecraft.client.util.math.MatrixStack;
@@ -10,10 +11,11 @@
import static net.minecraft.client.gui.DrawableHelper.fill;
-public class BarComponent implements ITooltipComponent {
+public class StorageAmountComponent implements ITooltipComponent {
private static final DecimalFormat FORMAT = new DecimalFormat("#.##");
private static final Identifier TEXTURE = MeganeUtils.id("textures/bar.png");
+ private static final String INFINITE = "\u221E";
static {
FORMAT.setRoundingMode(RoundingMode.DOWN);
@@ -22,42 +24,69 @@ public class BarComponent implements ITooltipComponent {
private final int color;
private final double stored, max;
+ private final boolean drawBar;
private final String valString;
- public BarComponent(int color, double stored, double max, String unit, boolean verbose) {
+ public StorageAmountComponent(BarFormat format, int color, double stored, double max, String unit, boolean verbose) {
this.color = color;
this.stored = stored;
this.max = max;
- String storedString;
- if (stored < 0 || stored == Double.MAX_VALUE) {
- storedString = "∞";
- } else {
- storedString = verbose ? String.valueOf(stored) : MeganeUtils.suffix((long) stored);
+ if (isInfinite(max)) {
+ drawBar = false;
+ valString = createValStr(createNumberStr(stored, verbose), unit);
+ return;
}
- String maxString;
- if (max <= 0 || max == Double.MAX_VALUE) {
- maxString = "∞";
- } else {
- maxString = verbose ? String.valueOf(max) : MeganeUtils.suffix((long) max);
- }
+ String number = switch (format) {
+ case FRACTION -> {
+ String storedString = createNumberStr(stored, verbose);
+ String maxString = max == 0 ? INFINITE : createNumberStr(max, verbose);
+ yield storedString + '/' + maxString;
+ }
+ case PERCENT -> {
+ if (isInfinite(stored) || max == 0 || isInfinite(max)) {
+ yield INFINITE + '%';
+ }
+
+ yield String.valueOf(stored / max * 100) + '%';
+ }
+ };
+
+ drawBar = true;
+ valString = number + (unit.isEmpty() ? "" : " " + unit);
+ }
+
+ private static String createNumberStr(double number, boolean verbose) {
+ return isInfinite(number) ? INFINITE
+ : verbose ? String.valueOf(number) : MeganeUtils.suffix((long) number);
+ }
- valString = storedString + "/" + maxString + (unit.isEmpty() ? "" : " " + unit);
+ private static String createValStr(String number, String unit) {
+ return number + (unit.isEmpty() ? "" : " " + unit);
+ }
+
+ private static boolean isInfinite(double number) {
+ return number < 0 || number == Double.MAX_VALUE || number == Double.POSITIVE_INFINITY;
}
@Override
public int getWidth() {
- return Math.max(MeganeUtils.textRenderer().getWidth(valString), 100);
+ return Math.max(MeganeUtils.textRenderer().getWidth(valString), drawBar ? 100 : -1);
}
@Override
public int getHeight() {
- return 13;
+ return drawBar ? 13 : MeganeUtils.textRenderer().fontHeight;
}
@Override
public void render(MatrixStack matrices, int x, int y, float delta) {
+ if (!drawBar) {
+ MeganeUtils.textRenderer().draw(matrices, valString, x, y, 0xFF000000 | color);
+ return;
+ }
+
float ratio = max == 0 ? 1F : ((float) Math.floor((Math.min((float) (stored / max), 1F)) * 100)) / 100F;
MeganeUtils.drawTexture(matrices, TEXTURE, x, y, 100, 11, 0, 0, 1F, 0.5F, color);
diff --git a/module-base/runtime/src/main/java/lol/bai/megane/runtime/provider/block/EnergyComponentProvider.java b/module-base/runtime/src/main/java/lol/bai/megane/runtime/provider/block/EnergyComponentProvider.java
index f66395e..67386cf 100644
--- a/module-base/runtime/src/main/java/lol/bai/megane/runtime/provider/block/EnergyComponentProvider.java
+++ b/module-base/runtime/src/main/java/lol/bai/megane/runtime/provider/block/EnergyComponentProvider.java
@@ -5,7 +5,8 @@
import java.util.Objects;
import lol.bai.megane.api.provider.EnergyInfoProvider;
-import lol.bai.megane.runtime.component.BarComponent;
+import lol.bai.megane.api.util.BarFormat;
+import lol.bai.megane.runtime.component.StorageAmountComponent;
import lol.bai.megane.runtime.config.MeganeConfig;
import lol.bai.megane.runtime.registry.Registrar;
import mcp.mobius.waila.api.IBlockAccessor;
@@ -69,7 +70,7 @@ protected void append(ITooltip tooltip, IBlockAccessor accessor) {
} else {
color = provider == null
? colors.computeIfAbsent(MODID, c -> 0x710C00)
- : provider.getColor();
+ : provider.getColor() & 0xFFFFFF;
colors.put(key, color);
CONFIG.save();
}
@@ -87,7 +88,7 @@ protected void append(ITooltip tooltip, IBlockAccessor accessor) {
tooltip.addLine(new PairComponent(
new WrappedComponent(provider != null ? provider.getName() : ENERGY_NAME),
- new BarComponent(color, stored, max, unit, expand)));
+ new StorageAmountComponent(provider != null ? provider.getFormat() : BarFormat.FRACTION, color, stored, max, unit, expand)));
}
}
diff --git a/module-base/runtime/src/main/java/lol/bai/megane/runtime/provider/block/FluidComponentProvider.java b/module-base/runtime/src/main/java/lol/bai/megane/runtime/provider/block/FluidComponentProvider.java
index 17acd8a..cbfa4ba 100644
--- a/module-base/runtime/src/main/java/lol/bai/megane/runtime/provider/block/FluidComponentProvider.java
+++ b/module-base/runtime/src/main/java/lol/bai/megane/runtime/provider/block/FluidComponentProvider.java
@@ -4,7 +4,8 @@
import java.util.Map;
import lol.bai.megane.api.provider.FluidInfoProvider;
-import lol.bai.megane.runtime.component.BarComponent;
+import lol.bai.megane.api.util.BarFormat;
+import lol.bai.megane.runtime.component.StorageAmountComponent;
import lol.bai.megane.runtime.registry.Registrar;
import mcp.mobius.waila.api.IBlockAccessor;
import mcp.mobius.waila.api.ITooltip;
@@ -60,7 +61,7 @@ protected void addFluid(ITooltip tooltip, IBlockAccessor accessor, Fluid fluid,
int color;
if (nbt != null && provider != null) {
- color = provider.getColor();
+ color = provider.getColor() & 0xFFFFFF;
} else if (colors.containsKey(id)) {
color = colors.get(id);
} else {
@@ -73,7 +74,7 @@ protected void addFluid(ITooltip tooltip, IBlockAccessor accessor, Fluid fluid,
tooltip.addLine(new PairComponent(
new WrappedComponent(provider == null ? fluidName(fluid) : provider.getName()),
- new BarComponent(color, stored, max, "mB", expand)));
+ new StorageAmountComponent(BarFormat.FRACTION, color, stored, max, "mB", expand)));
}
@Override
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/MeganeCreate.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/MeganeCreate.java
index 70ccced..f88df67 100644
--- a/module-compat/create/src/main/java/lol/bai/megane/module/create/MeganeCreate.java
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/MeganeCreate.java
@@ -1,13 +1,35 @@
package lol.bai.megane.module.create;
+import com.simibubi.create.content.contraptions.components.actors.BlockBreakingKineticTileEntity;
+import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerTileEntity;
+import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity;
+import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity;
+import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity;
import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
+import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
+import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity;
+import com.simibubi.create.content.schematics.block.SchematicTableTileEntity;
+import com.simibubi.create.content.schematics.block.SchematicannonTileEntity;
import com.tterrag.registrate.fabric.SimpleFlowableFluid;
import lol.bai.megane.api.MeganeModule;
import lol.bai.megane.api.registry.ClientRegistrar;
import lol.bai.megane.api.registry.CommonRegistrar;
+import lol.bai.megane.module.create.provider.BasinFluidProvider;
+import lol.bai.megane.module.create.provider.BasinItemProvider;
+import lol.bai.megane.module.create.provider.BasinProgressProvider;
+import lol.bai.megane.module.create.provider.BlockBreakingProgressProvider;
import lol.bai.megane.module.create.provider.CreativeFluidTankFluidProvider;
+import lol.bai.megane.module.create.provider.CrushingWheelControllerProgressProvider;
+import lol.bai.megane.module.create.provider.DeployerItemProvider;
import lol.bai.megane.module.create.provider.FluidTankFluidProvider;
+import lol.bai.megane.module.create.provider.ItemStackHandlerItemProvider;
+import lol.bai.megane.module.create.provider.MechanicalMixerProgressProvider;
+import lol.bai.megane.module.create.provider.MillstoneItemProvider;
+import lol.bai.megane.module.create.provider.MillstoneProgressProvider;
+import lol.bai.megane.module.create.provider.SchematicannonEnergyInfoProvider;
+import lol.bai.megane.module.create.provider.SchematicannonEnergyProvider;
+import lol.bai.megane.module.create.provider.SchematicannonProgressProvider;
import lol.bai.megane.module.create.provider.SimpleFlowableFluidInfoProvider;
@SuppressWarnings("unused")
@@ -15,13 +37,32 @@ public class MeganeCreate implements MeganeModule {
@Override
public void registerCommon(CommonRegistrar registrar) {
- registrar.addFluid(CreativeFluidTankTileEntity.class, new CreativeFluidTankFluidProvider());
+ registrar.addFluid(999, CreativeFluidTankTileEntity.class, new CreativeFluidTankFluidProvider());
+ registrar.addFluid(BasinTileEntity.class, new BasinFluidProvider());
registrar.addFluid(FluidTankTileEntity.class, new FluidTankFluidProvider<>());
+
+ registrar.addEnergy(SchematicannonTileEntity.class, new SchematicannonEnergyProvider());
+
+ registrar.addProgress(BasinTileEntity.class, new BasinProgressProvider());
+ registrar.addProgress(BlockBreakingKineticTileEntity.class, new BlockBreakingProgressProvider());
+ registrar.addProgress(CrushingWheelControllerTileEntity.class, new CrushingWheelControllerProgressProvider());
+ registrar.addProgress(MechanicalMixerTileEntity.class, new MechanicalMixerProgressProvider());
+ registrar.addProgress(MillstoneTileEntity.class, new MillstoneProgressProvider());
+ registrar.addProgress(SchematicannonTileEntity.class, new SchematicannonProgressProvider());
+
+ registrar.addItem(BasinTileEntity.class, new BasinItemProvider());
+ registrar.addItem(DeployerTileEntity.class, new DeployerItemProvider());
+ registrar.addItem(ItemVaultTileEntity.class, new ItemStackHandlerItemProvider.Single<>(ItemVaultTileEntity::getInventoryOfBlock));
+ registrar.addItem(MillstoneTileEntity.class, new MillstoneItemProvider());
+ registrar.addItem(SchematicannonTileEntity.class, new ItemStackHandlerItemProvider.Single<>(t -> t.inventory));
+ registrar.addItem(SchematicTableTileEntity.class, new ItemStackHandlerItemProvider.Single<>(t -> t.inventory));
}
@Override
public void registerClient(ClientRegistrar registrar) {
registrar.addFluidInfo(SimpleFlowableFluid.class, new SimpleFlowableFluidInfoProvider());
+
+ registrar.addEnergyInfo(SchematicannonTileEntity.class, new SchematicannonEnergyInfoProvider());
}
}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessBasinOperatingTileEntity.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessBasinOperatingTileEntity.java
new file mode 100644
index 0000000..cb824bd
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessBasinOperatingTileEntity.java
@@ -0,0 +1,16 @@
+package lol.bai.megane.module.create.mixin;
+
+import java.util.Optional;
+
+import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
+import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(BasinOperatingTileEntity.class)
+public interface AccessBasinOperatingTileEntity {
+
+ @Invoker("getBasin")
+ Optional megane_getBasin();
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessBasinTileEntity.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessBasinTileEntity.java
new file mode 100644
index 0000000..c01cf85
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessBasinTileEntity.java
@@ -0,0 +1,16 @@
+package lol.bai.megane.module.create.mixin;
+
+import java.util.Optional;
+
+import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
+import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(BasinTileEntity.class)
+public interface AccessBasinTileEntity {
+
+ @Invoker("getOperator")
+ Optional megane_getOperator();
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessBlockBreakingKineticTileEntity.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessBlockBreakingKineticTileEntity.java
new file mode 100644
index 0000000..c8c285f
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessBlockBreakingKineticTileEntity.java
@@ -0,0 +1,13 @@
+package lol.bai.megane.module.create.mixin;
+
+import com.simibubi.create.content.contraptions.components.actors.BlockBreakingKineticTileEntity;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(BlockBreakingKineticTileEntity.class)
+public interface AccessBlockBreakingKineticTileEntity {
+
+ @Accessor("destroyProgress")
+ int megane_destroyProgress();
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessMillstoneProgressProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessMillstoneProgressProvider.java
new file mode 100644
index 0000000..ce0cabb
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/AccessMillstoneProgressProvider.java
@@ -0,0 +1,14 @@
+package lol.bai.megane.module.create.mixin;
+
+import com.simibubi.create.content.contraptions.components.millstone.MillingRecipe;
+import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(MillstoneTileEntity.class)
+public interface AccessMillstoneProgressProvider {
+
+ @Accessor("lastRecipe")
+ MillingRecipe megane_lastRecipe();
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/MixinCrushingWheelControllerTileEntity.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/MixinCrushingWheelControllerTileEntity.java
new file mode 100644
index 0000000..fabdbf6
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/MixinCrushingWheelControllerTileEntity.java
@@ -0,0 +1,34 @@
+package lol.bai.megane.module.create.mixin;
+
+import java.util.Optional;
+
+import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerTileEntity;
+import com.simibubi.create.content.contraptions.processing.ProcessingRecipe;
+import io.github.fabricators_of_create.porting_lib.transfer.item.RecipeWrapper;
+import lol.bai.megane.module.create.provider.CrushingWheelControllerProgressProvider;
+import net.minecraft.item.ItemStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Unique;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
+
+@Mixin(CrushingWheelControllerTileEntity.class)
+public abstract class MixinCrushingWheelControllerTileEntity implements CrushingWheelControllerProgressProvider.Access {
+
+ @Unique
+ private int recipeDuration;
+
+ @SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "OptionalIsPresent"})
+ @Inject(method = "itemInserted", at = @At("TAIL"), locals = LocalCapture.CAPTURE_FAILHARD)
+ private void megane_storeRecipeDuration(ItemStack stack, CallbackInfo ci, Optional> recipe) {
+ recipeDuration = recipe.isPresent() ? recipe.get().getProcessingDuration() : 0;
+ }
+
+ @Override
+ public int megane_recipeDuration() {
+ return recipeDuration;
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/MixinMechanicalMixerTileEntity.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/MixinMechanicalMixerTileEntity.java
new file mode 100644
index 0000000..d7f1e1b
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/mixin/MixinMechanicalMixerTileEntity.java
@@ -0,0 +1,31 @@
+package lol.bai.megane.module.create.mixin;
+
+import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity;
+import lol.bai.megane.module.create.provider.MechanicalMixerProgressProvider;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(MechanicalMixerTileEntity.class)
+public abstract class MixinMechanicalMixerTileEntity implements MechanicalMixerProgressProvider.Access {
+
+ @Shadow
+ public int processingTicks;
+
+ @Unique
+ private int recipeTicks;
+
+ @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity;getBasin()Ljava/util/Optional;"))
+ private void megane_storeRecipeTicks(CallbackInfo ci) {
+ recipeTicks = processingTicks;
+ }
+
+ @Override
+ public int megane_getRecipeTicks() {
+ return recipeTicks;
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BaseBasinProgressProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BaseBasinProgressProvider.java
new file mode 100644
index 0000000..1a4d64d
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BaseBasinProgressProvider.java
@@ -0,0 +1,41 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
+import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
+import io.github.fabricators_of_create.porting_lib.transfer.item.ItemStackHandler;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class BaseBasinProgressProvider extends ItemStackHandlerProgressProvider {
+
+ private BasinTileEntity basin;
+ private BasinOperatingTileEntity operator;
+
+ @Nullable
+ abstract BasinTileEntity getBasin();
+
+ @Nullable
+ abstract BasinOperatingTileEntity getOperator();
+
+ @Override
+ protected void init() {
+ basin = getBasin();
+ operator = getOperator();
+ super.init();
+ }
+
+ @Override
+ public boolean hasProgress() {
+ return operator != null;
+ }
+
+ @Override
+ @Nullable ItemStackHandler getInputStackHandler() {
+ return basin.getInputInventory();
+ }
+
+ @Override
+ @Nullable ItemStackHandler getOutputStackHandler() {
+ return basin.getOutputInventory();
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinFluidProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinFluidProvider.java
new file mode 100644
index 0000000..8461ba6
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinFluidProvider.java
@@ -0,0 +1,27 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
+import io.github.fabricators_of_create.porting_lib.transfer.fluid.FluidTank;
+import io.github.fabricators_of_create.porting_lib.util.FluidStack;
+import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
+
+@SuppressWarnings("UnstableApiUsage")
+public class BasinFluidProvider extends FluidStackProvider {
+
+ @Override
+ public int getSlotCount() {
+ return 2;
+ }
+
+ @Override
+ FluidStack getFluidStack(int slot) {
+ FluidTank tank = slot == 0 ? getObject().getTanks().getFirst().getPrimaryHandler() : getObject().getTanks().getSecond().getPrimaryHandler();
+ return tank.getFluid();
+ }
+
+ @Override
+ public double getMax(int slot) {
+ return droplets(FluidConstants.BUCKET);
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinItemProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinItemProvider.java
new file mode 100644
index 0000000..dee6d06
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinItemProvider.java
@@ -0,0 +1,18 @@
+package lol.bai.megane.module.create.provider;
+
+import java.util.List;
+
+import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
+import com.simibubi.create.foundation.item.SmartInventory;
+import io.github.fabricators_of_create.porting_lib.transfer.item.ItemStackHandler;
+
+public class BasinItemProvider extends ItemStackHandlerItemProvider {
+
+ @Override
+ void appendHandlers(List handlers) {
+ for (SmartInventory inv : getObject().getInvs()) {
+ handlers.add(inv);
+ }
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinOperatingProgressProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinOperatingProgressProvider.java
new file mode 100644
index 0000000..32a9827
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinOperatingProgressProvider.java
@@ -0,0 +1,26 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
+import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
+import lol.bai.megane.module.create.mixin.AccessBasinOperatingTileEntity;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class BasinOperatingProgressProvider extends BaseBasinProgressProvider {
+
+ private AccessBasinOperatingTileEntity access;
+ private BasinTileEntity basin;
+
+ @Override
+ protected void init() {
+ access = getObjectCasted();
+ basin = access.megane_getBasin().orElse(null);
+
+ super.init();
+ }
+
+ @Override
+ @Nullable BasinTileEntity getBasin() {
+ return basin;
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinProgressProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinProgressProvider.java
new file mode 100644
index 0000000..b823557
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BasinProgressProvider.java
@@ -0,0 +1,48 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity;
+import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
+import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
+import lol.bai.megane.module.create.mixin.AccessBasinTileEntity;
+import org.jetbrains.annotations.Nullable;
+
+public class BasinProgressProvider extends BaseBasinProgressProvider {
+
+ private AccessBasinTileEntity access;
+ private BasinOperatingTileEntity operator;
+ private int percentage;
+
+ @Override
+ protected void init() {
+ access = getObjectCasted();
+ operator = access.megane_getOperator().orElse(null);
+
+ percentage = -1;
+ if (operator instanceof MechanicalMixerTileEntity mixer) {
+ percentage = MechanicalMixerProgressProvider.getPercentage(mixer);
+ }
+
+ super.init();
+ }
+
+ @Override
+ public boolean hasProgress() {
+ return percentage > -1;
+ }
+
+ @Override
+ public int getPercentage() {
+ return percentage;
+ }
+
+ @Override
+ @Nullable BasinTileEntity getBasin() {
+ return getObject();
+ }
+
+ @Override
+ @Nullable BasinOperatingTileEntity getOperator() {
+ return operator;
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BlockBreakingProgressProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BlockBreakingProgressProvider.java
new file mode 100644
index 0000000..bf14747
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/BlockBreakingProgressProvider.java
@@ -0,0 +1,21 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.contraptions.components.actors.BlockBreakingKineticTileEntity;
+import lol.bai.megane.api.provider.base.IoLessProgressProvider;
+import lol.bai.megane.module.create.mixin.AccessBlockBreakingKineticTileEntity;
+
+public class BlockBreakingProgressProvider extends IoLessProgressProvider {
+
+ AccessBlockBreakingKineticTileEntity access;
+
+ @Override
+ protected void init() {
+ access = getObjectCasted();
+ }
+
+ @Override
+ public int getPercentage() {
+ return access.megane_destroyProgress() * 10;
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/CrushingWheelControllerProgressProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/CrushingWheelControllerProgressProvider.java
new file mode 100644
index 0000000..5d3cb1f
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/CrushingWheelControllerProgressProvider.java
@@ -0,0 +1,45 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerTileEntity;
+import io.github.fabricators_of_create.porting_lib.transfer.item.ItemStackHandler;
+import org.jetbrains.annotations.Nullable;
+
+public class CrushingWheelControllerProgressProvider extends ItemStackHandlerProgressProvider {
+
+ Access access;
+ int recipeDuration;
+
+ @Override
+ protected void init() {
+ super.init();
+ access = getObjectCasted();
+ recipeDuration = access.megane_recipeDuration();
+ }
+
+ @Override
+ public boolean hasProgress() {
+ return recipeDuration > 0 && getObject().inventory.remainingTime > 0;
+ }
+
+ @Override
+ @Nullable ItemStackHandler getInputStackHandler() {
+ return getObject().inventory;
+ }
+
+ @Override
+ @Nullable ItemStackHandler getOutputStackHandler() {
+ return null;
+ }
+
+ @Override
+ public int getPercentage() {
+ return remainingPercentage(getObject().inventory.remainingTime, recipeDuration);
+ }
+
+ public interface Access {
+
+ int megane_recipeDuration();
+
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/DeployerItemProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/DeployerItemProvider.java
new file mode 100644
index 0000000..971477a
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/DeployerItemProvider.java
@@ -0,0 +1,20 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity;
+import lol.bai.megane.api.provider.ItemProvider;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+public class DeployerItemProvider extends ItemProvider {
+
+ @Override
+ public int getSlotCount() {
+ return 1;
+ }
+
+ @Override
+ public @NotNull ItemStack getStack(int slot) {
+ return getObject().getPlayer().getMainHandStack();
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/FluidStackProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/FluidStackProvider.java
new file mode 100644
index 0000000..af91a64
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/FluidStackProvider.java
@@ -0,0 +1,31 @@
+package lol.bai.megane.module.create.provider;
+
+import io.github.fabricators_of_create.porting_lib.util.FluidStack;
+import lol.bai.megane.api.provider.FluidProvider;
+import net.minecraft.fluid.Fluid;
+import net.minecraft.nbt.NbtCompound;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class FluidStackProvider extends FluidProvider {
+
+ private FluidStack stack;
+
+ abstract FluidStack getFluidStack(int slot);
+
+ @Override
+ public @Nullable Fluid getFluid(int slot) {
+ stack = getFluidStack(slot);
+ return stack.getFluid();
+ }
+
+ @Override
+ public double getStored(int slot) {
+ return droplets(stack.getAmount());
+ }
+
+ @Override
+ public @Nullable NbtCompound getNbt(int slot) {
+ return stack.getTag();
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/FluidTankFluidProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/FluidTankFluidProvider.java
index 4624451..210989e 100644
--- a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/FluidTankFluidProvider.java
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/FluidTankFluidProvider.java
@@ -2,12 +2,9 @@
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
import io.github.fabricators_of_create.porting_lib.transfer.fluid.FluidTank;
-import lol.bai.megane.api.provider.FluidProvider;
-import net.minecraft.fluid.Fluid;
-import net.minecraft.nbt.NbtCompound;
-import org.jetbrains.annotations.Nullable;
+import io.github.fabricators_of_create.porting_lib.util.FluidStack;
-public class FluidTankFluidProvider extends FluidProvider {
+public class FluidTankFluidProvider extends FluidStackProvider {
FluidTank tank;
@@ -22,18 +19,8 @@ public int getSlotCount() {
}
@Override
- public @Nullable Fluid getFluid(int slot) {
- return tank.getFluid().getFluid();
- }
-
- @Override
- public @Nullable NbtCompound getNbt(int slot) {
- return tank.getFluid().getTag();
- }
-
- @Override
- public double getStored(int slot) {
- return droplets(tank.getFluid().getAmount());
+ FluidStack getFluidStack(int slot) {
+ return tank.getFluid();
}
@Override
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/ItemStackHandlerItemProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/ItemStackHandlerItemProvider.java
new file mode 100644
index 0000000..8d7854f
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/ItemStackHandlerItemProvider.java
@@ -0,0 +1,58 @@
+package lol.bai.megane.module.create.provider;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+import io.github.fabricators_of_create.porting_lib.transfer.item.ItemStackHandler;
+import lol.bai.megane.api.provider.ItemProvider;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+public abstract class ItemStackHandlerItemProvider extends ItemProvider {
+
+ private final List handlers = new ArrayList<>();
+ private int slotCount;
+
+ abstract void appendHandlers(List handlers);
+
+ @Override
+ protected void init() {
+ handlers.clear();
+ appendHandlers(handlers);
+ slotCount = handlers.stream().mapToInt(ItemStackHandler::getSlots).sum();
+ }
+
+ @Override
+ public int getSlotCount() {
+ return slotCount;
+ }
+
+ @Override
+ public @NotNull ItemStack getStack(int slot) {
+ int pad = 0;
+ for (ItemStackHandler handler : handlers) {
+ if ((slot - pad) < handler.getSlots()) {
+ return handler.getStackInSlot(slot - pad);
+ }
+ pad += handler.getSlots();
+ }
+ return ItemStack.EMPTY;
+ }
+
+ public static class Single extends ItemStackHandlerItemProvider {
+
+ private final Function getter;
+
+ public Single(Function getter) {
+ this.getter = getter;
+ }
+
+ @Override
+ void appendHandlers(List handlers) {
+ handlers.add(getter.apply(getObject()));
+ }
+
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/ItemStackHandlerProgressProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/ItemStackHandlerProgressProvider.java
new file mode 100644
index 0000000..ffed360
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/ItemStackHandlerProgressProvider.java
@@ -0,0 +1,50 @@
+package lol.bai.megane.module.create.provider;
+
+import io.github.fabricators_of_create.porting_lib.transfer.item.ItemStackHandler;
+import lol.bai.megane.api.provider.ProgressProvider;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class ItemStackHandlerProgressProvider extends ProgressProvider {
+
+ @Nullable
+ private ItemStackHandler input;
+
+ @Nullable
+ private ItemStackHandler output;
+
+ @Override
+ protected void init() {
+ super.init();
+ input = getInputStackHandler();
+ output = getOutputStackHandler();
+ }
+
+ @Nullable
+ abstract ItemStackHandler getInputStackHandler();
+
+ @Nullable
+ abstract ItemStackHandler getOutputStackHandler();
+
+ @Override
+ public int getInputSlotCount() {
+ return input == null ? 0 : input.getSlots();
+ }
+
+ @Override
+ public int getOutputSlotCount() {
+ return output == null ? 0 : output.getSlots();
+ }
+
+ @Override
+ public @NotNull ItemStack getInputStack(int slot) {
+ return input == null ? ItemStack.EMPTY : input.getStackInSlot(slot);
+ }
+
+ @Override
+ public @NotNull ItemStack getOutputStack(int slot) {
+ return output == null ? ItemStack.EMPTY : output.getStackInSlot(slot);
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/MechanicalMixerProgressProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/MechanicalMixerProgressProvider.java
new file mode 100644
index 0000000..2482061
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/MechanicalMixerProgressProvider.java
@@ -0,0 +1,47 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity;
+import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
+import org.jetbrains.annotations.Nullable;
+
+public class MechanicalMixerProgressProvider extends BasinOperatingProgressProvider {
+
+ static int getPercentage(MechanicalMixerTileEntity mixer) {
+ if (mixer.processingTicks < 0) {
+ return -1;
+ }
+
+ int recipeTicks = ((Access) mixer).megane_getRecipeTicks();
+ return recipeTicks > 0 ? remainingPercentage(mixer.processingTicks, recipeTicks) : -1;
+ }
+
+ private int percentage;
+
+ @Override
+ protected void init() {
+ percentage = getPercentage(getObject());
+ super.init();
+ }
+
+ @Override
+ public boolean hasProgress() {
+ return percentage >= 0;
+ }
+
+ @Override
+ public int getPercentage() {
+ return percentage;
+ }
+
+ @Override
+ @Nullable BasinOperatingTileEntity getOperator() {
+ return getObject();
+ }
+
+ public interface Access {
+
+ int megane_getRecipeTicks();
+
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/MillstoneItemProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/MillstoneItemProvider.java
new file mode 100644
index 0000000..e03d2fd
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/MillstoneItemProvider.java
@@ -0,0 +1,16 @@
+package lol.bai.megane.module.create.provider;
+
+import java.util.List;
+
+import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity;
+import io.github.fabricators_of_create.porting_lib.transfer.item.ItemStackHandler;
+
+public class MillstoneItemProvider extends ItemStackHandlerItemProvider {
+
+ @Override
+ void appendHandlers(List handlers) {
+ handlers.add(getObject().inputInv);
+ handlers.add(getObject().outputInv);
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/MillstoneProgressProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/MillstoneProgressProvider.java
new file mode 100644
index 0000000..397ff97
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/MillstoneProgressProvider.java
@@ -0,0 +1,40 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.contraptions.components.millstone.MillingRecipe;
+import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity;
+import io.github.fabricators_of_create.porting_lib.transfer.item.ItemStackHandler;
+import lol.bai.megane.module.create.mixin.AccessMillstoneProgressProvider;
+
+public class MillstoneProgressProvider extends ItemStackHandlerProgressProvider {
+
+ AccessMillstoneProgressProvider access;
+ MillingRecipe recipe;
+
+ @Override
+ protected void init() {
+ super.init();
+ access = getObjectCasted();
+ recipe = access.megane_lastRecipe();
+ }
+
+ @Override
+ public boolean hasProgress() {
+ return recipe != null && getObject().timer > 0;
+ }
+
+ @Override
+ ItemStackHandler getInputStackHandler() {
+ return getObject().inputInv;
+ }
+
+ @Override
+ ItemStackHandler getOutputStackHandler() {
+ return getObject().outputInv;
+ }
+
+ @Override
+ public int getPercentage() {
+ return remainingPercentage(getObject().timer, recipe.getProcessingDuration());
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/SchematicannonEnergyInfoProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/SchematicannonEnergyInfoProvider.java
new file mode 100644
index 0000000..6662783
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/SchematicannonEnergyInfoProvider.java
@@ -0,0 +1,33 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.schematics.block.SchematicannonTileEntity;
+import lol.bai.megane.api.provider.EnergyInfoProvider;
+import lol.bai.megane.api.util.BarFormat;
+import net.minecraft.item.Items;
+import net.minecraft.text.Text;
+import org.jetbrains.annotations.Nullable;
+
+public class SchematicannonEnergyInfoProvider extends EnergyInfoProvider {
+
+ @Override
+ public Text getName() {
+ return Items.GUNPOWDER.getName();
+ }
+
+ @Override
+ public BarFormat getFormat() {
+ return BarFormat.PERCENT;
+ }
+
+ @Override
+ public int getColor() {
+ return 0x2D2D2D;
+ }
+
+ @Nullable
+ @Override
+ public String getUnit() {
+ return "";
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/SchematicannonEnergyProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/SchematicannonEnergyProvider.java
new file mode 100644
index 0000000..c14dbe1
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/SchematicannonEnergyProvider.java
@@ -0,0 +1,18 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.schematics.block.SchematicannonTileEntity;
+import lol.bai.megane.api.provider.EnergyProvider;
+
+public class SchematicannonEnergyProvider extends EnergyProvider {
+
+ @Override
+ public long getStored() {
+ return (long) (getObject().fuelLevel * 100);
+ }
+
+ @Override
+ public long getMax() {
+ return 100;
+ }
+
+}
diff --git a/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/SchematicannonProgressProvider.java b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/SchematicannonProgressProvider.java
new file mode 100644
index 0000000..33e9093
--- /dev/null
+++ b/module-compat/create/src/main/java/lol/bai/megane/module/create/provider/SchematicannonProgressProvider.java
@@ -0,0 +1,24 @@
+package lol.bai.megane.module.create.provider;
+
+import com.simibubi.create.content.schematics.block.SchematicannonTileEntity;
+import io.github.fabricators_of_create.porting_lib.transfer.item.ItemStackHandler;
+import org.jetbrains.annotations.Nullable;
+
+public class SchematicannonProgressProvider extends ItemStackHandlerProgressProvider {
+
+ @Override
+ @Nullable ItemStackHandler getInputStackHandler() {
+ return getObject().inventory;
+ }
+
+ @Override
+ @Nullable ItemStackHandler getOutputStackHandler() {
+ return null;
+ }
+
+ @Override
+ public int getPercentage() {
+ return currentPercentage(getObject().blocksPlaced, getObject().blocksToPlace);
+ }
+
+}
diff --git a/module-compat/create/src/main/resources/fabric.mod.json b/module-compat/create/src/main/resources/fabric.mod.json
index 43ee26b..cb8dd81 100644
--- a/module-compat/create/src/main/resources/fabric.mod.json
+++ b/module-compat/create/src/main/resources/fabric.mod.json
@@ -5,6 +5,7 @@
"authors" : ["deirn"],
"license" : "MIT",
"icon" : "assets/megane/icon.png",
+ "mixins" : ["megane-create.mixins.json"],
"depends" : {
"megane-api" : "*",
"create": "*"
diff --git a/module-compat/create/src/main/resources/megane-create.mixins.json b/module-compat/create/src/main/resources/megane-create.mixins.json
new file mode 100644
index 0000000..ca57d3f
--- /dev/null
+++ b/module-compat/create/src/main/resources/megane-create.mixins.json
@@ -0,0 +1,17 @@
+{
+ "required" : true,
+ "minVersion" : "0.8",
+ "package" : "lol.bai.megane.module.create.mixin",
+ "compatibilityLevel": "JAVA_8",
+ "injectors" : {
+ "defaultRequire": 1
+ },
+ "mixins" : [
+ "AccessBasinOperatingTileEntity",
+ "AccessBasinTileEntity",
+ "AccessBlockBreakingKineticTileEntity",
+ "AccessMillstoneProgressProvider",
+ "MixinCrushingWheelControllerTileEntity",
+ "MixinMechanicalMixerTileEntity"
+ ]
+}