From 448ef817580f0503435633336f3aba524d635e9b Mon Sep 17 00:00:00 2001
From: Florian Kostenzer <fkostenzer@0815.tirol>
Date: Thu, 30 Mar 2023 21:25:21 +0200
Subject: [PATCH] feat: basic computercraft integration

---
 build.gradle                                  |  1 +
 .../java/gregification/base/BaseConfig.java   |  5 ++
 src/main/java/gregification/base/ModIDs.java  |  3 +-
 .../computercraft/ComputerCraftConfig.java    | 11 ++++
 .../computercraft/ComputerCraftModule.java    | 47 ++++++++++++++++
 .../peripheral/MetaTileEntityPeripheral.java  | 45 ++++++++++++++++
 ...tityPeripheralEnergyContainerFunction.java | 44 +++++++++++++++
 .../MetaTileEntityPeripheralFunction.java     | 13 +++++
 ...ileEntityPeripheralSetEnabledFunction.java | 33 ++++++++++++
 ...etaTileEntityPeripheralStatusFunction.java | 53 +++++++++++++++++++
 10 files changed, 254 insertions(+), 1 deletion(-)
 create mode 100644 src/main/java/gregification/modules/computercraft/ComputerCraftConfig.java
 create mode 100644 src/main/java/gregification/modules/computercraft/ComputerCraftModule.java
 create mode 100644 src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheral.java
 create mode 100644 src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralEnergyContainerFunction.java
 create mode 100644 src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralFunction.java
 create mode 100644 src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralSetEnabledFunction.java
 create mode 100644 src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralStatusFunction.java

diff --git a/build.gradle b/build.gradle
index ee7cefb..d2f1a64 100644
--- a/build.gradle
+++ b/build.gradle
@@ -137,6 +137,7 @@ dependencies {
     implementation fg.deobf("curse.maven:tfcraft-302973:3268988")
     implementation fg.deobf("curse.maven:ae2-extended-life-570458:4323863")
     implementation fg.deobf("curse.maven:gregtech-food-option-${project.gtfo_id}:${project.gtfo_version}")
+    implementation fg.deobf("curse.maven:cc-tweaked-282001:2718128")
 
     // May get some form of compatibility in the future
     //implementation fg.deobf("curse.maven:mcjtylib-233105:2745846")
diff --git a/src/main/java/gregification/base/BaseConfig.java b/src/main/java/gregification/base/BaseConfig.java
index fe6dea5..e668994 100644
--- a/src/main/java/gregification/base/BaseConfig.java
+++ b/src/main/java/gregification/base/BaseConfig.java
@@ -28,4 +28,9 @@ public class BaseConfig {
     @Comment({"Enable Tinkers' Construct integration.", "Default: true"})
     @RequiresMcRestart
     public static boolean enableTinkersConstructModule = true;
+
+    @Comment({"Enable ComputerCraft integration.", "Default: true"})
+    @RequiresMcRestart
+    public static boolean enableComputerCraftModule = true;
+
 }
diff --git a/src/main/java/gregification/base/ModIDs.java b/src/main/java/gregification/base/ModIDs.java
index eb3adf8..85baa19 100644
--- a/src/main/java/gregification/base/ModIDs.java
+++ b/src/main/java/gregification/base/ModIDs.java
@@ -23,5 +23,6 @@ public class ModIDs {
             MODID_THAUM = "thaumcraft",
             GENDUSTRY = "gendustry",
             MODID_GTFO = "gregtechfoodoption",
-            MODID_TFC = "tfc";
+            MODID_TFC = "tfc",
+            MODID_CC = "computercraft";
 }
diff --git a/src/main/java/gregification/modules/computercraft/ComputerCraftConfig.java b/src/main/java/gregification/modules/computercraft/ComputerCraftConfig.java
new file mode 100644
index 0000000..3e660b5
--- /dev/null
+++ b/src/main/java/gregification/modules/computercraft/ComputerCraftConfig.java
@@ -0,0 +1,11 @@
+package gregification.modules.computercraft;
+
+import gregification.Gregification;
+import net.minecraftforge.common.config.Config;
+import net.minecraftforge.common.config.Config.LangKey;
+
+
+@LangKey("gregification.config.open_computers")
+@Config(modid = Gregification.MODID, name = Gregification.MODID + "/computercraft", category = "ComputerCraft")
+public class ComputerCraftConfig {
+}
diff --git a/src/main/java/gregification/modules/computercraft/ComputerCraftModule.java b/src/main/java/gregification/modules/computercraft/ComputerCraftModule.java
new file mode 100644
index 0000000..cd48bcd
--- /dev/null
+++ b/src/main/java/gregification/modules/computercraft/ComputerCraftModule.java
@@ -0,0 +1,47 @@
+package gregification.modules.computercraft;
+
+import dan200.computercraft.api.ComputerCraftAPI;
+import dan200.computercraft.api.peripheral.IPeripheral;
+import dan200.computercraft.api.peripheral.IPeripheralProvider;
+import gregification.base.BaseConfig;
+import gregification.base.ModIDs;
+import gregification.base.Module;
+import gregification.modules.computercraft.peripheral.MetaTileEntityPeripheral;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.util.GTUtility;
+import net.minecraft.util.EnumFacing;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+import net.minecraftforge.fml.common.Loader;
+import net.minecraftforge.fml.common.event.FMLInitializationEvent;
+import org.apache.logging.log4j.Logger;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+@Module.Root(name = "Gregification: Computercraft")
+public class ComputerCraftModule implements Module {
+
+    @Log
+    public static Logger logger;
+
+    @Override
+    public boolean isModuleActive() {
+        return BaseConfig.enableComputerCraftModule && Loader.isModLoaded(ModIDs.MODID_CC);
+    }
+
+    @Override
+    public void init(FMLInitializationEvent event) {
+        ComputerCraftAPI.registerPeripheralProvider(new IPeripheralProvider() {
+            @Nullable
+            @Override
+            public IPeripheral getPeripheral(@Nonnull World world, @Nonnull BlockPos blockPos, @Nonnull EnumFacing enumFacing) {
+                MetaTileEntity metaTileEntity = GTUtility.getMetaTileEntity(world, blockPos);
+                if (metaTileEntity != null) {
+                    return new MetaTileEntityPeripheral(metaTileEntity, enumFacing);
+                }
+                return null;
+            }
+        });
+    }
+}
diff --git a/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheral.java b/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheral.java
new file mode 100644
index 0000000..884fb5f
--- /dev/null
+++ b/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheral.java
@@ -0,0 +1,45 @@
+package gregification.modules.computercraft.peripheral;
+
+import dan200.computercraft.api.lua.ILuaContext;
+import dan200.computercraft.api.lua.LuaException;
+import dan200.computercraft.api.peripheral.IComputerAccess;
+import dan200.computercraft.api.peripheral.IPeripheral;
+import gregtech.api.metatileentity.MetaTileEntity;
+import net.minecraft.util.EnumFacing;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.Arrays;
+
+public class MetaTileEntityPeripheral implements IPeripheral {
+    private final MetaTileEntityPeripheralFunction[] functions;
+
+    public MetaTileEntityPeripheral(MetaTileEntity metaTileEntity, EnumFacing enumFacing) {
+        this.functions = Arrays.stream(new MetaTileEntityPeripheralFunction[]{
+                new MetaTileEntityPeripheralEnergyContainerFunction(metaTileEntity, enumFacing),
+                new MetaTileEntityPeripheralStatusFunction(metaTileEntity),
+                new MetaTileEntityPeripheralSetEnabledFunction(metaTileEntity),
+        }).filter(MetaTileEntityPeripheralFunction::isEnabled).toArray(MetaTileEntityPeripheralFunction[]::new);
+    }
+
+    @Nonnull
+    public String getType() {
+        return "gregtech_meta_timer_entity";
+    }
+
+    @Nonnull
+    public String[] getMethodNames() {
+        return Arrays.stream(functions).map(MetaTileEntityPeripheralFunction::getName).toArray(String[]::new);
+    }
+
+    @Nullable
+    public Object[] callMethod(@Nonnull IComputerAccess iComputerAccess, @Nonnull ILuaContext iLuaContext, int i, @Nonnull Object[] objects) throws LuaException, InterruptedException {
+        return functions[i].call(iComputerAccess, iLuaContext, i, objects);
+    }
+
+    public boolean equals(@Nullable IPeripheral iPeripheral) {
+        return iPeripheral == this;
+    }
+
+}
+
diff --git a/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralEnergyContainerFunction.java b/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralEnergyContainerFunction.java
new file mode 100644
index 0000000..85951f9
--- /dev/null
+++ b/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralEnergyContainerFunction.java
@@ -0,0 +1,44 @@
+package gregification.modules.computercraft.peripheral;
+
+import dan200.computercraft.api.lua.ILuaContext;
+import dan200.computercraft.api.peripheral.IComputerAccess;
+import gregtech.api.capability.GregtechCapabilities;
+import gregtech.api.capability.IEnergyContainer;
+import gregtech.api.metatileentity.MetaTileEntity;
+import net.minecraft.util.EnumFacing;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class MetaTileEntityPeripheralEnergyContainerFunction implements MetaTileEntityPeripheralFunction {
+
+    private final IEnergyContainer energyContainer;
+
+    public MetaTileEntityPeripheralEnergyContainerFunction(MetaTileEntity metaTileEntity, EnumFacing enumFacing) {
+        this.energyContainer = metaTileEntity.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, enumFacing);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return this.energyContainer != null;
+    }
+
+    @Override
+    public String getName() {
+        return "getEnergy";
+    }
+
+    @Override
+    public Object[] call(IComputerAccess iComputerAccess, ILuaContext iLuaContext, int i, Object[] objects) {
+        Map<String, Object> data = new HashMap<>();
+        data.put("stored", energyContainer.getEnergyStored());
+        data.put("capacity", energyContainer.getEnergyCapacity());
+        data.put("average_input", energyContainer.getInputPerSec());
+        data.put("average_output", energyContainer.getOutputPerSec());
+        data.put("input_voltage", energyContainer.getInputVoltage());
+        data.put("output_voltage", energyContainer.getOutputVoltage());
+        data.put("input_amperage", energyContainer.getInputAmperage());
+        data.put("output_amperage", energyContainer.getOutputAmperage());
+        return new Object[]{data};
+    }
+}
diff --git a/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralFunction.java b/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralFunction.java
new file mode 100644
index 0000000..5f378e2
--- /dev/null
+++ b/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralFunction.java
@@ -0,0 +1,13 @@
+package gregification.modules.computercraft.peripheral;
+
+import dan200.computercraft.api.lua.ILuaContext;
+import dan200.computercraft.api.lua.LuaException;
+import dan200.computercraft.api.peripheral.IComputerAccess;
+
+interface MetaTileEntityPeripheralFunction {
+    boolean isEnabled();
+
+    String getName();
+
+    Object[] call(IComputerAccess iComputerAccess, ILuaContext iLuaContext, int i, Object[] objects) throws LuaException, InterruptedException;
+}
diff --git a/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralSetEnabledFunction.java b/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralSetEnabledFunction.java
new file mode 100644
index 0000000..c4a95ad
--- /dev/null
+++ b/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralSetEnabledFunction.java
@@ -0,0 +1,33 @@
+package gregification.modules.computercraft.peripheral;
+
+import dan200.computercraft.api.lua.ILuaContext;
+import dan200.computercraft.api.peripheral.IComputerAccess;
+import gregtech.api.capability.GregtechTileCapabilities;
+import gregtech.api.capability.IControllable;
+import gregtech.api.metatileentity.MetaTileEntity;
+
+class MetaTileEntityPeripheralSetEnabledFunction implements MetaTileEntityPeripheralFunction {
+
+    private final IControllable controllable;
+
+    public MetaTileEntityPeripheralSetEnabledFunction(MetaTileEntity metaTileEntity) {
+        this.controllable = metaTileEntity.getCapability(GregtechTileCapabilities.CAPABILITY_CONTROLLABLE, null);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return this.controllable != null;
+    }
+
+    @Override
+    public String getName() {
+        return "setEnabled";
+    }
+
+    @Override
+    public Object[] call(IComputerAccess iComputerAccess, ILuaContext iLuaContext, int i, Object[] objects) {
+        boolean enabled = objects.length > 0 && objects[0] instanceof Boolean ? (Boolean) objects[0] : true;
+        controllable.setWorkingEnabled(enabled);
+        return new Object[]{};
+    }
+}
diff --git a/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralStatusFunction.java b/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralStatusFunction.java
new file mode 100644
index 0000000..28bf508
--- /dev/null
+++ b/src/main/java/gregification/modules/computercraft/peripheral/MetaTileEntityPeripheralStatusFunction.java
@@ -0,0 +1,53 @@
+package gregification.modules.computercraft.peripheral;
+
+import dan200.computercraft.api.lua.ILuaContext;
+import dan200.computercraft.api.peripheral.IComputerAccess;
+import gregtech.api.capability.GregtechTileCapabilities;
+import gregtech.api.capability.IControllable;
+import gregtech.api.capability.impl.AbstractRecipeLogic;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.TieredMetaTileEntity;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class MetaTileEntityPeripheralStatusFunction implements MetaTileEntityPeripheralFunction {
+
+    private final TieredMetaTileEntity tieredMetaTileEntity;
+
+    private final IControllable controllable;
+    private final AbstractRecipeLogic recipeLogic;
+
+    public MetaTileEntityPeripheralStatusFunction(MetaTileEntity metaTileEntity) {
+        this.tieredMetaTileEntity = metaTileEntity instanceof TieredMetaTileEntity ? (TieredMetaTileEntity) metaTileEntity : null;
+        this.controllable = metaTileEntity.getCapability(GregtechTileCapabilities.CAPABILITY_CONTROLLABLE, null);
+        this.recipeLogic = metaTileEntity.getCapability(GregtechTileCapabilities.CAPABILITY_RECIPE_LOGIC, null);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return this.tieredMetaTileEntity != null || this.controllable != null || this.recipeLogic != null;
+    }
+
+    @Override
+    public String getName() {
+        return "getStatus";
+    }
+
+    @Override
+    public Object[] call(IComputerAccess iComputerAccess, ILuaContext iLuaContext, int i, Object[] objects) {
+        Map<String, Object> data = new HashMap<>();
+        if (controllable != null) {
+            data.put("enabled", controllable.isWorkingEnabled());
+        }
+        if (tieredMetaTileEntity != null) {
+            data.put("tier", tieredMetaTileEntity.getTier());
+        }
+        if (recipeLogic != null) {
+            data.put("active", recipeLogic.isActive());
+            data.put("progress", recipeLogic.getProgress());
+            data.put("maxProgress", recipeLogic.getMaxProgress());
+        }
+        return new Object[]{data};
+    }
+}