diff --git a/README.md b/README.md index 06d66c9..30fba67 100644 --- a/README.md +++ b/README.md @@ -54,3 +54,7 @@ Check out [here](https://github.com/GTNewHorizons/RetroFuturaGradle/issues/51#is - `UNDERLINE` - `ITALIC` - `RESET` + +### Credits + +- Texture of Programmed Upgrade is from [Neeve's AE2: Extended Life Additions (NAE2)](https://github.com/AE2-UEL/NAE2) diff --git a/dependencies.gradle b/dependencies.gradle index 283409e..e6944f9 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -42,6 +42,7 @@ dependencies { implementation("com.github.GTNewHorizons:GT5-Unofficial:5.09.48.66:dev") implementation("com.github.GTNewHorizons:NewHorizonsCoreMod:2.5.16:dev") + implementation("com.github.GTNewHorizons:AE2FluidCraft-Rework:1.3.26-gtnh") // FIXME: publish TST to somewhere else implementation("com.github.GTNewHorizons:Twist-Space-Technology-Mod:0.5.8-publish.11+344150b931-dirty") diff --git a/src/main/java/cn/taskeren/op/mixin/late/AdditionalAE_UpgradeInventory_Mixin.java b/src/main/java/cn/taskeren/op/mixin/late/AdditionalAE_UpgradeInventory_Mixin.java new file mode 100644 index 0000000..e172f22 --- /dev/null +++ b/src/main/java/cn/taskeren/op/mixin/late/AdditionalAE_UpgradeInventory_Mixin.java @@ -0,0 +1,50 @@ +package cn.taskeren.op.mixin.late; + +import appeng.api.config.Upgrades; +import appeng.parts.automation.UpgradeInventory; +import cn.taskeren.op.ae.OP_AEUpgrades; +import com.llamalad7.mixinextras.sugar.Local; +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.CallbackInfoReturnable; + +@Mixin(value = UpgradeInventory.class, remap = false) +public abstract class AdditionalAE_UpgradeInventory_Mixin { + + /* + + The additional upgrade items are registered as `OP_GeneratedAEUpgradeItem` and it implements IUpgradeModule, so we don't need to + do extra things in `isItemValidForSlot`. + + In this class, we should manually count our custom upgrades and return the right value in the method. + + */ + + @Unique + private int op$programmedUpgrades = 0; + + @Inject(method = "updateUpgradeInfo", at = @At("HEAD")) + private void op$updateUpgradeInfo_cleanse(CallbackInfo ci) { + op$programmedUpgrades = 0; + } + + @Inject(method = "updateUpgradeInfo", at = @At(value = "INVOKE_ASSIGN", target = "Lappeng/api/implementations/items/IUpgradeModule;getType(Lnet/minecraft/item/ItemStack;)Lappeng/api/config/Upgrades;")) + private void op$updateUpgradeInfo_count(CallbackInfo ci, @Local(name = "myUpgrade") Upgrades myUpgrade) { + if(myUpgrade == OP_AEUpgrades.getProgrammedUpgrade()) { + op$programmedUpgrades++; + } + } + + @Inject(method = "getInstalledUpgrades", at = @At("RETURN"), cancellable = true) + private void op$getInstalledUpgrades(Upgrades u, CallbackInfoReturnable cir) { + // overwrite + if (u == OP_AEUpgrades.getProgrammedUpgrade()) { + cir.setReturnValue(op$programmedUpgrades); + } + } + + +} diff --git a/src/main/java/cn/taskeren/op/mixin/late/AdditionalAE_Upgrades_Mixin.java b/src/main/java/cn/taskeren/op/mixin/late/AdditionalAE_Upgrades_Mixin.java new file mode 100644 index 0000000..cb668da --- /dev/null +++ b/src/main/java/cn/taskeren/op/mixin/late/AdditionalAE_Upgrades_Mixin.java @@ -0,0 +1,52 @@ +package cn.taskeren.op.mixin.late; + +import appeng.api.config.Upgrades; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.ArrayList; +import java.util.Arrays; + +@Mixin(value = Upgrades.class, remap = false) +@Unique +public abstract class AdditionalAE_Upgrades_Mixin { + + /* + + Added an extra instance to `Upgrades` enum. + + This tricky method is from https://github.com/SpongePowered/Mixin/issues/387#issuecomment-888408556 + + But there is a potential bug that in the runtime the new created instance is added to the $VALUES twice, and + I cannot find the reason it is added twice. But it works for now, so I assume it affect nothing. + + You should get the instance from `OP_AEUpgrades`. + + */ + + @Shadow + @Final + @Mutable + private static Upgrades[] $VALUES; + + private static final Upgrades PROGRAMMED = op$createInstance("PROGRAMMED", 1); + + @Invoker("") + public static Upgrades op$constructor(String name, int ordinal, int tier) { + throw new AssertionError(); + } + + private static Upgrades op$createInstance(String name, int tier) { + // get existing instances + ArrayList values = new ArrayList<>(Arrays.asList($VALUES)); + // create the new instance + Upgrades value = op$constructor(name, values.get(values.size() - 1).ordinal() + 1, tier); + // add the new instance to the instance cache list + values.add(value); + // overwrite the $VALUES to the value list with the new instance + $VALUES = values.toArray(new Upgrades[0]); + // return the new instance + return value; + } + +} diff --git a/src/main/java/cn/taskeren/op/mixin/late/GTApi_GregTech_API_Mixin.java b/src/main/java/cn/taskeren/op/mixin/late/GTApi_GregTech_API_Mixin.java new file mode 100644 index 0000000..2cd182e --- /dev/null +++ b/src/main/java/cn/taskeren/op/mixin/late/GTApi_GregTech_API_Mixin.java @@ -0,0 +1,17 @@ +package cn.taskeren.op.mixin.late; + +import com.google.common.collect.Multimap; +import gregtech.api.GregTech_API; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(value = GregTech_API.class, remap = false) +public interface GTApi_GregTech_API_Mixin { + + @Accessor("sRealConfigurationList") + static Multimap getRealConfigurationList() { + throw new AssertionError(); + } + +} diff --git a/src/main/java/cn/taskeren/op/mixin/late/ProInterface_DualityInterface_Mixin.java b/src/main/java/cn/taskeren/op/mixin/late/ProInterface_DualityInterface_Mixin.java new file mode 100644 index 0000000..cd4fb07 --- /dev/null +++ b/src/main/java/cn/taskeren/op/mixin/late/ProInterface_DualityInterface_Mixin.java @@ -0,0 +1,69 @@ +package cn.taskeren.op.mixin.late; + +import appeng.api.config.Upgrades; +import appeng.api.networking.crafting.ICraftingPatternDetails; +import appeng.helpers.DualityInterface; +import cn.taskeren.op.ae.OP_AEUpgrades; +import cn.taskeren.op.gt.utils.GTApi; +import codechicken.lib.inventory.InventoryUtils; +import com.llamalad7.mixinextras.sugar.Local; +import gregtech.api.interfaces.IConfigurationCircuitSupport; +import gregtech.api.metatileentity.BaseMetaTileEntity; +import gregtech.api.util.GT_Utility; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +@Mixin(value = DualityInterface.class, remap = false) +public abstract class ProInterface_DualityInterface_Mixin { + + @Shadow + private List waitingToSend; + + @Shadow + public abstract IInventory getStorage(); + + @Shadow + public abstract int getInstalledUpgrades(Upgrades u); + + @Inject(method = "pushPattern", at = @At(value = "INVOKE", target = "Lappeng/helpers/DualityInterface;pushItemsOut(Ljava/util/EnumSet;)Z", ordinal = 0)) + private void op$pushItemsOut(ICraftingPatternDetails patternDetails, InventoryCrafting table, CallbackInfoReturnable cir, @Local(name = "te") TileEntity tile) { + if(getInstalledUpgrades(OP_AEUpgrades.getProgrammedUpgrade()) < 1) { // requires the upgrade installed + return; + } + + if(tile instanceof BaseMetaTileEntity) { + BaseMetaTileEntity bmte = (BaseMetaTileEntity) tile; + IConfigurationCircuitSupport circuitSupport = bmte.getConfigurationCircuitSupport(); + if(circuitSupport != null) { + // get the first circuit stack in the items that will be inserted to the machine + Optional circuitStackOptional = waitingToSend.stream() + .filter(Objects::nonNull) + .filter(GTApi.INSTANCE::isConfigurationCircuit).findFirst(); + + circuitStackOptional.ifPresent(circuitStack -> { + if (circuitSupport.getConfigurationCircuits().stream().anyMatch(allowedStack -> GT_Utility.areStacksEqual(allowedStack, circuitStack))) { + // set the circuit slot to the circuit stack + int circuitSlot = circuitSupport.getCircuitSlot(); + bmte.getMetaTileEntity().setInventorySlotContents(circuitSlot, circuitStack.copy()); + // remove the circuit stack from items that will be inserted to the machine + waitingToSend.remove(circuitStack); + // and return the circuit stack to the interface storage + InventoryUtils.insertItem(getStorage(), circuitStack, false); + } + }); + } + } + } + +} diff --git a/src/main/java/cn/taskeren/op/utils/MixinAccessorBridge.java b/src/main/java/cn/taskeren/op/utils/MixinAccessorBridge.java new file mode 100644 index 0000000..dc177af --- /dev/null +++ b/src/main/java/cn/taskeren/op/utils/MixinAccessorBridge.java @@ -0,0 +1,19 @@ +package cn.taskeren.op.utils; + +import cn.taskeren.op.mixin.late.GTApi_GregTech_API_Mixin; +import com.google.common.collect.Multimap; +import net.minecraft.item.ItemStack; + +/** + * This class is a bridge that used to access {@link org.spongepowered.asm.mixin.gen.Accessor}s in Kotlin while not throwing {@link IncompatibleClassChangeError}. + */ +public class MixinAccessorBridge { + + /** + * @return gregtech.api.GregTech_API#sRealConfigurationList + */ + public static Multimap getRealConfigurationList() { + return GTApi_GregTech_API_Mixin.getRealConfigurationList(); + } + +} diff --git a/src/main/kotlin/cn/taskeren/op/ae/OP_AEUpgrades.kt b/src/main/kotlin/cn/taskeren/op/ae/OP_AEUpgrades.kt new file mode 100644 index 0000000..69f744d --- /dev/null +++ b/src/main/kotlin/cn/taskeren/op/ae/OP_AEUpgrades.kt @@ -0,0 +1,40 @@ +package cn.taskeren.op.ae + +import appeng.api.AEApi +import appeng.api.config.Upgrades +import cn.taskeren.op.OP_Logger +import com.glodblock.github.loader.ItemAndBlockHolder as AE2FCItemAndBlockHolder + +/** + * @see cn.taskeren.op.mixin.late.AdditionalAE_Upgrades_Mixin + */ +object OP_AEUpgrades : OP_Logger { + + /** + * @return the instance of Programmed Upgrade, or `null` if the mixin is failed or AE2 is not available. + */ + @JvmStatic + val programmedUpgrade: Upgrades? by lazy { runCatching { Upgrades.valueOf("PROGRAMMED") }.getOrNull() } + + /** + * @return the available OP additional upgrades. + */ + @JvmStatic + val upgrades: List by lazy { listOf(programmedUpgrade).filterNotNull() } + + fun init() { + val aeApi = AEApi.instance() + + // add upgrades to the allowlist of the ae2 parts and blocks + if(programmedUpgrade != null) { + logger.info("Programmed Upgrade is found!") + // ae2 + programmedUpgrade?.registerItem(aeApi.definitions().parts().iface(), 1) + programmedUpgrade?.registerItem(aeApi.definitions().blocks().iface(), 1) + // ae2fc + programmedUpgrade?.registerItem(AE2FCItemAndBlockHolder.FLUID_INTERFACE.stack(), 1) + programmedUpgrade?.registerItem(AE2FCItemAndBlockHolder.INTERFACE.stack(), 1) + } + } + +} diff --git a/src/main/kotlin/cn/taskeren/op/forge/CommonInit.kt b/src/main/kotlin/cn/taskeren/op/forge/CommonInit.kt index a5a1d16..5a7abe8 100644 --- a/src/main/kotlin/cn/taskeren/op/forge/CommonInit.kt +++ b/src/main/kotlin/cn/taskeren/op/forge/CommonInit.kt @@ -1,6 +1,7 @@ package cn.taskeren.op.forge import cn.taskeren.op.OP_Logger +import cn.taskeren.op.ae.OP_AEUpgrades import cn.taskeren.op.forge.config.OP_Config import cn.taskeren.op.gt.init.LazyScheduler import cn.taskeren.op.gt.init.OP_GTRegistrar @@ -38,6 +39,7 @@ open class CommonInit : OP_Logger { } open fun postInit(e: FMLPostInitializationEvent) { + OP_AEUpgrades.init() LazyScheduler.runPostInit() } diff --git a/src/main/kotlin/cn/taskeren/op/forge/OP_Mod.kt b/src/main/kotlin/cn/taskeren/op/forge/OP_Mod.kt index a8a60a6..c8bb847 100644 --- a/src/main/kotlin/cn/taskeren/op/forge/OP_Mod.kt +++ b/src/main/kotlin/cn/taskeren/op/forge/OP_Mod.kt @@ -28,7 +28,8 @@ import cpw.mods.fml.common.event.FMLServerStartingEvent dependencies = "required-after:gregtech;" + "required-after:miscutils;" + // gt++ "required-after:tectech;" + // TecTech - "required-after:dreamcraft;" + "required-after:dreamcraft;" + + "required-after:appliedenergistics2;" // AE2 ) object OP_Mod : OP_Logger { diff --git a/src/main/kotlin/cn/taskeren/op/gt/IdItemContainer.kt b/src/main/kotlin/cn/taskeren/op/gt/IdItemContainer.kt index c04a2d0..e7d0c2f 100644 --- a/src/main/kotlin/cn/taskeren/op/gt/IdItemContainer.kt +++ b/src/main/kotlin/cn/taskeren/op/gt/IdItemContainer.kt @@ -40,8 +40,10 @@ fun IdItemContainer.addRecipe(recipeMap: IRecipeMap, block: GT_RecipeBuilder.(de } } -fun IdItemContainer.addRecipeSimple(block: (defaultItem: ItemStack) -> Unit) = apply { +fun IdItemContainer.useItemStackPostInit(block: (defaultItem: ItemStack) -> Unit) = apply { LazyScheduler.schedulePostInit { block(get(1)) } } + +fun IdItemContainer.addRecipeSimple(block: (defaultItem: ItemStack) -> Unit) = useItemStackPostInit(block) diff --git a/src/main/kotlin/cn/taskeren/op/gt/init/OP_GTRegistrar.kt b/src/main/kotlin/cn/taskeren/op/gt/init/OP_GTRegistrar.kt index 18f0db2..b107ae7 100644 --- a/src/main/kotlin/cn/taskeren/op/gt/init/OP_GTRegistrar.kt +++ b/src/main/kotlin/cn/taskeren/op/gt/init/OP_GTRegistrar.kt @@ -1,7 +1,10 @@ package cn.taskeren.op.gt.init +import appeng.api.AEApi +import cn.taskeren.op.ae.OP_AEUpgrades import cn.taskeren.op.gt.addRecipe import cn.taskeren.op.gt.addRecipeSimple +import cn.taskeren.op.gt.item.OP_GeneratedAEUpgradeItem import cn.taskeren.op.gt.item.OP_GeneratedItem import cn.taskeren.op.gt.item.impl.ActiveTransformerExplosionCoreItemBehaviour import cn.taskeren.op.gt.item.impl.InsuranceReceiptItemBehaviour @@ -13,6 +16,7 @@ import cn.taskeren.op.gt.single.OP_DebugEnergyHatch import cn.taskeren.op.gt.single.OP_InsuranceCounter import cn.taskeren.op.gt.single.OP_OverpowerMachine import cn.taskeren.op.gt.single.OP_UniHatch +import cn.taskeren.op.gt.useItemStackPostInit import cn.taskeren.op.gt.utils.PatternRecipeBuilder import cn.taskeren.op.gt.utils.PatternRecipeBuilder.X import com.github.technus.tectech.thing.CustomItemList @@ -23,6 +27,7 @@ import gregtech.api.enums.TierEU import gregtech.api.recipe.RecipeMaps import gregtech.api.util.GT_ModHandler import gregtech.api.util.GT_RecipeBuilder +import gregtech.api.util.GT_Utility import gtPlusPlus.xmod.gregtech.api.enums.GregtechItemList import net.minecraft.item.ItemStack import com.dreammaster.gthandler.CustomItemList as DreamItemList @@ -31,6 +36,7 @@ object OP_GTRegistrar { fun registerAllMachines() { registerSimpleItems() + registerAdditionalAEUpgrades() registerSingleMachines() } @@ -57,13 +63,13 @@ object OP_GTRegistrar { // #tr gt.metaitem.op.32003.name // #en Insurance Receipt // #zh 保险单 - addItem(it, "Insurance Receipt", "", InsuranceReceiptItemBehaviour) + addItem(it, "Insurance Receipt", null, InsuranceReceiptItemBehaviour) } OP_ItemList.ActiveTransformerExplosionCore.registerItem { // #tr gt.metaitem.op.32004.name // #en Active Transformer Explosion Core // #zh 有源变压器爆炸核心 - addItem(it, "Active Transformer Explosion Core", "", ActiveTransformerExplosionCoreItemBehaviour) + addItem(it, "Active Transformer Explosion Core", null, ActiveTransformerExplosionCoreItemBehaviour) }.addRecipe(RecipeMaps.hammerRecipes) { itemInputs(CustomItemList.Machine_Multi_Transformer.get(1)) // active transformer itemOutputs(it.copy().also { it.stackSize = 8 }) @@ -72,6 +78,30 @@ object OP_GTRegistrar { } } + private fun registerAdditionalAEUpgrades() = with(OP_GeneratedAEUpgradeItem) { + OP_ItemList.ProgrammedUpgrade.registerItem { + // #tr gt.metaitem.op.ae.32000.name + // #en Programmed Upgrade + // #zh 编程卡 + // #tr gt.metaitem.op.ae.32000.tooltip + // #en Adjust Configuration Circuit by Pattern + // #zh 根据样板调整虚拟电路板 + addItem(it, "Programmed Upgrade", "Adjust Configuration Circuit by Pattern") + }.useItemStackPostInit { + registerUpgrade(it, OP_AEUpgrades.programmedUpgrade) + }.addRecipeSimple { + val definitions = AEApi.instance().definitions() + GT_ModHandler.addCraftingRecipe( + it, + arrayOf( + "BC", + 'B', definitions.materials().basicCard().maybeStack(1).get(), + 'C', GT_Utility.getIntegratedCircuit(0) + ) + ) + } + } + private fun registerSingleMachines() { // #tr gt.blockmachines.overpower_machine.name // #en Incredible Malicious Machine Overpowering System diff --git a/src/main/kotlin/cn/taskeren/op/gt/init/OP_ItemList.kt b/src/main/kotlin/cn/taskeren/op/gt/init/OP_ItemList.kt index b46c186..9826eeb 100644 --- a/src/main/kotlin/cn/taskeren/op/gt/init/OP_ItemList.kt +++ b/src/main/kotlin/cn/taskeren/op/gt/init/OP_ItemList.kt @@ -14,11 +14,15 @@ import net.minecraft.item.ItemStack enum class OP_ItemList(override val id: Short) : IdItemContainer, OP_Logger { + // OP_GeneratedItem DyingBioChip(1), CertifiedElectrician(2), InsuranceReceipt(3), ActiveTransformerExplosionCore(4), + // OP_GeneratedAEUpgradeItem + ProgrammedUpgrade(0), + ; private lateinit var theItem: ItemStack diff --git a/src/main/kotlin/cn/taskeren/op/gt/item/OP_GeneratedAEUpgradeItem.kt b/src/main/kotlin/cn/taskeren/op/gt/item/OP_GeneratedAEUpgradeItem.kt new file mode 100644 index 0000000..6e2bdde --- /dev/null +++ b/src/main/kotlin/cn/taskeren/op/gt/item/OP_GeneratedAEUpgradeItem.kt @@ -0,0 +1,36 @@ +package cn.taskeren.op.gt.item + +import appeng.api.config.Upgrades +import appeng.api.implementations.items.IUpgradeModule +import gregtech.api.items.GT_MetaGenerated_Item_X32 +import gregtech.api.util.GT_Utility +import net.minecraft.item.ItemStack + +/** + * Textures should be placed at `assets/gregtech/textures/items/gt.metaitem.op.ae/$id.png` + * + * @see gregtech.common.items.GT_MetaGenerated_Item_01 + */ +object OP_GeneratedAEUpgradeItem : GT_MetaGenerated_Item_X32("metaitem.op.ae"), IUpgradeModule { + + private val upgradeTypeRegistry = mutableMapOf() + + fun registerUpgrade(item: ItemStack, upgrades: Upgrades?) { + if(upgrades != null) { + upgradeTypeRegistry[item] = upgrades + } else { + upgradeTypeRegistry -= item + } + } + + override fun getType(stack: ItemStack): Upgrades? { + for((item, upgrade) in upgradeTypeRegistry) { + if(GT_Utility.areStacksEqual(item, stack, true)) { + return upgrade + } + } + + return null + } + +} diff --git a/src/main/kotlin/cn/taskeren/op/gt/utils/GTApi.kt b/src/main/kotlin/cn/taskeren/op/gt/utils/GTApi.kt index 9372be4..3efbc58 100644 --- a/src/main/kotlin/cn/taskeren/op/gt/utils/GTApi.kt +++ b/src/main/kotlin/cn/taskeren/op/gt/utils/GTApi.kt @@ -1,6 +1,8 @@ package cn.taskeren.op.gt.utils +import cn.taskeren.op.utils.MixinAccessorBridge import gregtech.api.GregTech_API +import gregtech.api.util.GT_Utility import net.minecraft.item.ItemStack object GTApi { @@ -26,4 +28,10 @@ object GTApi { fun getMetaTileEntityById(metaId: Int) = GregTech_API.METATILEENTITIES.getOrNull(metaId) + val configurationCircuits: Collection + get() = MixinAccessorBridge.getRealConfigurationList().values() + + fun isConfigurationCircuit(stack: ItemStack): Boolean = + configurationCircuits.any { GT_Utility.areStacksEqual(stack, it) } + } diff --git a/src/main/kotlin/cn/taskeren/op/mixin_plugin/OP_LateMixin.kt b/src/main/kotlin/cn/taskeren/op/mixin_plugin/OP_LateMixin.kt index f5125fe..597c858 100644 --- a/src/main/kotlin/cn/taskeren/op/mixin_plugin/OP_LateMixin.kt +++ b/src/main/kotlin/cn/taskeren/op/mixin_plugin/OP_LateMixin.kt @@ -26,10 +26,16 @@ class OP_LateMixin : ILateMixinLoader { val mixinClasses = mutableListOf() if("gregtech" in loadedMods) { mixinClasses += "Insurance_BaseMetaTileEntity_Mixin" + mixinClasses += "GTApi_GregTech_API_Mixin" } if("modularui" in loadedMods) { mixinClasses += "CrashProof_ModularGui_Mixin" } + if("appliedenergistics2" in loadedMods) { + mixinClasses += "ProInterface_DualityInterface_Mixin" + mixinClasses += "AdditionalAE_Upgrades_Mixin" + mixinClasses += "AdditionalAE_UpgradeInventory_Mixin" + } mixinClasses.forEach { logger.info("Applied Mixin: {}", it) } return mixinClasses diff --git a/src/main/resources/assets/Overpowered/lang/en_US.lang b/src/main/resources/assets/Overpowered/lang/en_US.lang index da81146..4582117 100644 --- a/src/main/resources/assets/Overpowered/lang/en_US.lang +++ b/src/main/resources/assets/Overpowered/lang/en_US.lang @@ -7,6 +7,8 @@ gt.metaitem.op.32002.name=Certified Electrician gt.metaitem.op.32002.tooltip=Proof of your qualifications on Electrical Engineering gt.metaitem.op.32003.name=Insurance Receipt gt.metaitem.op.32004.name=Active Transformer Explosion Core +gt.metaitem.op.ae.32000.name=Programmed Upgrade +gt.metaitem.op.ae.32000.tooltip=Adjust Configuration Circuit by Pattern gt.blockmachines.overpower_machine.name=Incredible Malicious Machine Overpowering System gt.blockmachines.active_transformer_rack.name=Active Transformer Rack gt.blockmachines.insurance_counter.name=Galactic Inc. Insurance Counter diff --git a/src/main/resources/assets/Overpowered/lang/zh_CN.lang b/src/main/resources/assets/Overpowered/lang/zh_CN.lang index b4fe219..409bc43 100644 --- a/src/main/resources/assets/Overpowered/lang/zh_CN.lang +++ b/src/main/resources/assets/Overpowered/lang/zh_CN.lang @@ -5,6 +5,8 @@ gt.metaitem.op.32002.name=电工资格证 gt.metaitem.op.32002.tooltip=证明你在电气工程的资历 gt.metaitem.op.32003.name=保险单 gt.metaitem.op.32004.name=有源变压器爆炸核心 +gt.metaitem.op.ae.32000.name=编程卡 +gt.metaitem.op.ae.32000.tooltip=根据样板调整虚拟电路板 gt.blockmachines.overpower_machine.name=超级绝绝子机器强化系统 gt.blockmachines.active_transformer_rack.name=有源变压器机械架 gt.blockmachines.insurance_counter.name=星际保险公司柜台 diff --git a/src/main/resources/assets/gregtech/textures/items/gt.metaitem.op.ae/0.png b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.op.ae/0.png new file mode 100644 index 0000000..e7f1d81 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.op.ae/0.png differ