diff --git a/src/main/java/co/neeve/nae2/common/parts/implementations/PartPCCNotifier.java b/src/main/java/co/neeve/nae2/common/parts/implementations/PartPCCNotifier.java new file mode 100644 index 0000000..2b57aee --- /dev/null +++ b/src/main/java/co/neeve/nae2/common/parts/implementations/PartPCCNotifier.java @@ -0,0 +1,90 @@ +package co.neeve.nae2.common.parts.implementations; + +import appeng.api.parts.IPartCollisionHelper; +import appeng.api.parts.IPartModel; +import appeng.api.util.AECableType; +import appeng.api.util.AEPartLocation; +import appeng.items.parts.PartModels; +import appeng.parts.PartBasicState; +import appeng.parts.PartModel; +import appeng.util.Platform; +import co.neeve.nae2.Tags; +import gregtech.api.capability.IGhostSlotConfigurable; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.jetbrains.annotations.NotNull; + +import static appeng.parts.automation.PartLevelEmitter.*; + +public class PartPCCNotifier extends PartBasicState { + @PartModels + public static final ResourceLocation MODEL_BASE_OFF = new ResourceLocation(Tags.MODID, + "part/pcc_notifier_base_off"); + @PartModels + public static final ResourceLocation MODEL_BASE_ON = new ResourceLocation(Tags.MODID, + "part/pcc_notifier_base_on"); + @PartModels + + public static final PartModel MODEL_OFF_OFF = new PartModel(MODEL_BASE_OFF, MODEL_STATUS_OFF); + public static final PartModel MODEL_OFF_ON = new PartModel(MODEL_BASE_OFF, MODEL_STATUS_ON); + public static final PartModel MODEL_OFF_HAS_CHANNEL = new PartModel(MODEL_BASE_OFF, MODEL_STATUS_HAS_CHANNEL); + public static final PartModel MODEL_ON_OFF = new PartModel(MODEL_BASE_ON, MODEL_STATUS_OFF); + public static final PartModel MODEL_ON_ON = new PartModel(MODEL_BASE_ON, MODEL_STATUS_ON); + public static final PartModel MODEL_ON_HAS_CHANNEL = new PartModel(MODEL_BASE_ON, MODEL_STATUS_HAS_CHANNEL); + + public PartPCCNotifier(ItemStack is) { + super(is); + this.getProxy().setIdlePowerUsage(1); + } + + @Override + @NotNull + public AECableType getCableConnectionType(final AEPartLocation dir) { + return AECableType.SMART; + } + + @Override + public void getBoxes(final IPartCollisionHelper bch) { + bch.addBox(7, 7, 11, 9, 9, 16); + } + + public void notifyMachine(int configNo) { + var side = this.getSide(); + var blockPos = this.getTile().getPos(); + var tile = this.getTile() + .getWorld().getTileEntity(blockPos.offset(side.getFacing())); + + if (tile instanceof MetaTileEntityHolder mteHolder) { + var mte = mteHolder.getMetaTileEntity(); + if (mte instanceof IGhostSlotConfigurable slotConfigurable) { + slotConfigurable.setGhostCircuitConfig(configNo); + } + } + } + + protected boolean isOn() { + if (Platform.isClient()) { + return (this.getClientFlags() & POWERED_FLAG) == POWERED_FLAG; + } + + return this.getProxy().isActive(); + } + + @NotNull + @Override + public IPartModel getStaticModels() { + if (this.isActive() && this.isPowered()) { + return this.isOn() ? MODEL_ON_HAS_CHANNEL : MODEL_OFF_HAS_CHANNEL; + } else if (this.isPowered()) { + return this.isOn() ? MODEL_ON_ON : MODEL_OFF_ON; + } else { + return this.isOn() ? MODEL_ON_OFF : MODEL_OFF_OFF; + } + } + + @Override + public float getCableConnectionLength(AECableType cable) { + return 16; + } +} diff --git a/src/main/java/co/neeve/nae2/common/registration/definitions/Parts.java b/src/main/java/co/neeve/nae2/common/registration/definitions/Parts.java index c7323d7..cc365a1 100644 --- a/src/main/java/co/neeve/nae2/common/registration/definitions/Parts.java +++ b/src/main/java/co/neeve/nae2/common/registration/definitions/Parts.java @@ -11,9 +11,11 @@ import co.neeve.nae2.Tags; import co.neeve.nae2.common.features.Features; import co.neeve.nae2.common.features.IFeature; +import co.neeve.nae2.common.features.subfeatures.UpgradeFeatures; import co.neeve.nae2.common.items.NAEBaseItemPart; import co.neeve.nae2.common.parts.implementations.PartBeamFormer; import co.neeve.nae2.common.parts.implementations.PartExposer; +import co.neeve.nae2.common.parts.implementations.PartPCCNotifier; import co.neeve.nae2.common.parts.p2p.PartP2PInterface; import co.neeve.nae2.common.parts.p2p.iface.InterfaceTunnelGridCache; import co.neeve.nae2.common.registration.registry.Registry; @@ -22,6 +24,10 @@ import co.neeve.nae2.common.registration.registry.interfaces.IDefinition; import co.neeve.nae2.common.registration.registry.rendering.ItemPartRendering; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import gregtech.api.GTValues; +import gregtech.api.recipes.ingredients.GTRecipeItemInput; +import gregtech.common.items.MetaItems; import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.client.renderer.block.model.ModelResourceLocation; @@ -37,14 +43,21 @@ import java.lang.reflect.Constructor; import java.util.*; +import static gregtech.api.recipes.RecipeMaps.ASSEMBLER_RECIPES; + public class Parts implements Definitions { private final Object2ObjectOpenHashMap byId = new Object2ObjectOpenHashMap<>(); private final NAEBaseItemPart itemPart; private final DamagedItemDefinition beamFormer; private final DamagedItemDefinition p2pTunnelInterface; private final DamagedItemDefinition exposer; + private final DamagedItemDefinition pccnotifier; public Parts(Registry registry) { + var definitions = Api.INSTANCE.definitions(); + var parts = definitions.parts(); + var blocks = definitions.blocks(); + this.itemPart = new NAEBaseItemPart(); registry.item("part", () -> this.itemPart) .rendering(new ItemPartRendering(this.itemPart)) @@ -58,6 +71,7 @@ public Parts(Registry registry) { this.beamFormer = this.createPart(this.itemPart, PartType.BEAM_FORMER); this.p2pTunnelInterface = this.createPart(this.itemPart, PartType.P2P_TUNNEL_INTERFACE); + this.p2pTunnelInterface.maybeStack(1) .ifPresent((tunnelStack) -> registry.addBootstrapComponent((IInitComponent) (r) -> { AEApi.instance().registries().gridCache() @@ -66,16 +80,36 @@ public Parts(Registry registry) { var tunnelType = AEApi.instance().registries().p2pTunnel() .registerTunnelType("NAE2_IFACE_P2P", tunnelStack); - var definitions = Api.INSTANCE.definitions(); - definitions.blocks().iface().maybeStack(1) + blocks.iface().maybeStack(1) .ifPresent((stack) -> registerTunnelConversion(tunnelType, stack)); - definitions.parts().iface().maybeStack(1) + parts.iface().maybeStack(1) .ifPresent((stack) -> registerTunnelConversion(tunnelType, stack)); })); this.exposer = this.createPart(this.itemPart, PartType.EXPOSER); + this.pccnotifier = this.createPart(this.itemPart, PartType.PCC_NOTIFIER); + this.pccnotifier.maybeStack(1).ifPresent((notifier) -> + registry.addBootstrapComponent((IInitComponent) (r) -> + ASSEMBLER_RECIPES.addRecipe( + ASSEMBLER_RECIPES.recipeBuilder() + .EUt(GTValues.VA[GTValues.LV]) + .duration(100) + .input(new GTRecipeItemInput( + Lists.newArrayList( + parts.levelEmitter(), + parts.fluidLevelEmitter() + ) + .stream() + .map(opt -> opt.maybeStack(1)) + .filter(Optional::isPresent) + .map(Optional::get) + .toArray(ItemStack[]::new) + )) + .input(MetaItems.SENSOR_LV) + .outputs(notifier) + .build()))); } private static void registerTunnelConversion(TunnelType tunnelType, ItemStack stack) { @@ -112,6 +146,10 @@ public Optional getById(String id) { return Optional.ofNullable(this.byId.getOrDefault(id, null)); } + public DamagedItemDefinition pccNotifier() { + return this.pccnotifier; + } + public enum PartType implements IDefinition { BEAM_FORMER("beam_former", PartBeamFormer.class, Features.BEAM_FORMERS), P2P_TUNNEL_INTERFACE("p2p_tunnel_interface", @@ -127,6 +165,13 @@ public void addCheckedInformation(ItemStack stack, World world, List lin ITooltipFlag advancedTooltips) { lines.add(I18n.format("nae2.exposer.tooltip")); } + }, + PCC_NOTIFIER("pcc_notifier", PartPCCNotifier.class, UpgradeFeatures.GREGTECH_CIRCUIT) { + @Override + public void addCheckedInformation(ItemStack stack, World world, List lines, + ITooltipFlag advancedTooltips) { + lines.add(I18n.format("item.nae2.part.pcc_notifier.desc")); + } }; private static Int2ObjectLinkedOpenHashMap cachedValues; diff --git a/src/main/java/co/neeve/nae2/mixin/upgrades/gregcircuit/MixinDualityInterface.java b/src/main/java/co/neeve/nae2/mixin/upgrades/gregcircuit/MixinDualityInterface.java index 00fb322..57d2ebb 100644 --- a/src/main/java/co/neeve/nae2/mixin/upgrades/gregcircuit/MixinDualityInterface.java +++ b/src/main/java/co/neeve/nae2/mixin/upgrades/gregcircuit/MixinDualityInterface.java @@ -1,12 +1,15 @@ package co.neeve.nae2.mixin.upgrades.gregcircuit; +import appeng.api.networking.IGridHost; import appeng.api.networking.crafting.ICraftingPatternDetails; +import appeng.api.util.AEPartLocation; import appeng.helpers.DualityInterface; import appeng.parts.automation.UpgradeInventory; import appeng.util.inv.InvOperation; import co.neeve.nae2.common.crafting.patterntransform.PatternTransform; import co.neeve.nae2.common.crafting.patterntransform.transformers.GregTechCircuitPatternTransformer; import co.neeve.nae2.common.interfaces.IExtendedUpgradeInventory; +import co.neeve.nae2.common.parts.implementations.PartPCCNotifier; import co.neeve.nae2.common.registration.definitions.Upgrades; import com.llamalad7.mixinextras.sugar.Local; import gregtech.api.capability.IGhostSlotConfigurable; @@ -14,6 +17,7 @@ import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; import net.minecraftforge.items.IItemHandler; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -31,7 +35,6 @@ public abstract class MixinDualityInterface { @Unique private WeakHashMap nae2$cachedCircuitValues = null; - @Shadow @Final private UpgradeInventory upgrades; @@ -51,22 +54,34 @@ public abstract class MixinDualityInterface { ) private void injectCircuitChange(ICraftingPatternDetails patternDetails, InventoryCrafting table, CallbackInfoReturnable cir, - @Local(name = "te") TileEntity tileEntity) { + @Local(name = "te") TileEntity tileEntity, + @Local(name = "s") EnumFacing s) { if (this.upgrades instanceof IExtendedUpgradeInventory upgradeInventory && upgradeInventory.getInstalledUpgrades(Upgrades.UpgradeType.GREGTECH_CIRCUIT) > 0) { + if (this.nae2$cachedCircuitValues == null) { + this.nae2$cachedCircuitValues = new WeakHashMap<>(); + } + int configNo = this.nae2$cachedCircuitValues.computeIfAbsent(patternDetails, d -> + GregTechCircuitPatternTransformer.getCircuitValueFromDetails(d).orElse(0)); + // I'm sorry, Seni. if (tileEntity instanceof MetaTileEntityHolder metaTileEntityHolder) { var mte = metaTileEntityHolder.getMetaTileEntity(); - if (mte instanceof IGhostSlotConfigurable slotConfigurable && slotConfigurable.hasGhostCircuitInventory()) { - if (this.nae2$cachedCircuitValues == null) { - this.nae2$cachedCircuitValues = new WeakHashMap<>(); - } + slotConfigurable.setGhostCircuitConfig(configNo); + } + } else if (tileEntity instanceof IGridHost host) { + var gridNode = host.getGridNode(AEPartLocation.fromFacing(s.getOpposite())); + if (gridNode == null) { + gridNode = host.getGridNode(AEPartLocation.INTERNAL); + } - slotConfigurable.setGhostCircuitConfig( - this.nae2$cachedCircuitValues.computeIfAbsent(patternDetails, d -> - GregTechCircuitPatternTransformer.getCircuitValueFromDetails(d).orElse(0))); + if (gridNode != null) { + var notifiers = gridNode.getGrid().getMachines(PartPCCNotifier.class); + for (var notifier : notifiers) { + ((PartPCCNotifier) notifier.getMachine()).notifyMachine(configNo); + } } } } diff --git a/src/main/resources/assets/nae2/lang/en_us.lang b/src/main/resources/assets/nae2/lang/en_us.lang index a1c83da..7d9a80d 100644 --- a/src/main/resources/assets/nae2/lang/en_us.lang +++ b/src/main/resources/assets/nae2/lang/en_us.lang @@ -42,6 +42,9 @@ item.nae2.material.cell_part_gas_16384k.name=§a16384k§r ME Gas Storage Compone # Parts item.nae2.part.beam_former.name=ME Beam Former item.nae2.part.exposer.name=ME Storage Exposer +item.nae2.part.pcc_notifier.name=ME Programmed Circuit Card Notifier +item.nae2.part.pcc_notifier.desc=Changes the ghost circuit in the machine/bus it's pointed at, but only whenever an §aME Interface§7 with a §aProgrammed Circuit Card§7 pushes a pattern into the network it's in.\n\nAutomate your multiblocks. + # Upgrades item.nae2.upgrade.hyper_acceleration.name=Hyper-Acceleration Card diff --git a/src/main/resources/assets/nae2/models/item/part/pcc_notifier.json b/src/main/resources/assets/nae2/models/item/part/pcc_notifier.json new file mode 100644 index 0000000..5a8e12b --- /dev/null +++ b/src/main/resources/assets/nae2/models/item/part/pcc_notifier.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "nae2:item/part/pcc_notifier" + } +} diff --git a/src/main/resources/assets/nae2/models/part/pcc_notifier.json b/src/main/resources/assets/nae2/models/part/pcc_notifier.json new file mode 100644 index 0000000..b0ee9ee --- /dev/null +++ b/src/main/resources/assets/nae2/models/part/pcc_notifier.json @@ -0,0 +1,76 @@ +{ + "parent": "appliedenergistics2:item/part/part", + "textures": { + "emitter": "nae2:items/part/level_emitter_on" + }, + "elements": [ + { + "from": [ + 7, + 6, + 7 + ], + "to": [ + 9, + 10, + 9 + ], + "faces": { + "north": { + "texture": "#emitter", + "uv": [ + 7, + 7, + 9, + 11 + ] + }, + "south": { + "texture": "#emitter", + "uv": [ + 7, + 7, + 9, + 11 + ] + }, + "east": { + "texture": "#emitter", + "uv": [ + 7, + 7, + 9, + 11 + ] + }, + "west": { + "texture": "#emitter", + "uv": [ + 7, + 7, + 9, + 11 + ] + }, + "up": { + "texture": "#emitter", + "uv": [ + 7, + 7, + 9, + 9 + ] + }, + "down": { + "texture": "#emitter", + "uv": [ + 7, + 9, + 9, + 11 + ] + } + } + } + ] +} diff --git a/src/main/resources/assets/nae2/models/part/pcc_notifier_base_off.json b/src/main/resources/assets/nae2/models/part/pcc_notifier_base_off.json new file mode 100644 index 0000000..6dd1ccf --- /dev/null +++ b/src/main/resources/assets/nae2/models/part/pcc_notifier_base_off.json @@ -0,0 +1,88 @@ +{ + "textures": { + "emitter": "nae2:part/pcc_notifier_off", + "sides": "appliedenergistics2:parts/monitor_sides", + "particle": "nae2:part/pcc_notifier_off" + }, + "elements": [ + { + "from": [ + 7, + 7, + 0 + ], + "to": [ + 9, + 9, + 4 + ], + "faces": { + "up": { + "texture": "#emitter", + "uv": [ + 6, + 7, + 10, + 9 + ], + "rotation": 90 + }, + "down": { + "texture": "#emitter", + "uv": [ + 6, + 7, + 10, + 9 + ], + "rotation": 270 + }, + "east": { + "texture": "#emitter", + "uv": [ + 6, + 7, + 10, + 9 + ], + "rotation": 180 + }, + "north": { + "texture": "#emitter", + "uv": [ + 6, + 7, + 8, + 9 + ] + }, + "west": { + "texture": "#emitter", + "uv": [ + 6, + 7, + 10, + 9 + ] + } + } + }, + { + "from": [ + 7, + 7, + 4 + ], + "to": [ + 9, + 9, + 5 + ], + "faces": { + "south": { + "texture": "#sides" + } + } + } + ] +} diff --git a/src/main/resources/assets/nae2/models/part/pcc_notifier_base_on.json b/src/main/resources/assets/nae2/models/part/pcc_notifier_base_on.json new file mode 100644 index 0000000..210342d --- /dev/null +++ b/src/main/resources/assets/nae2/models/part/pcc_notifier_base_on.json @@ -0,0 +1,177 @@ +{ + "ae2_uvl_marker": true, + "ambientocclusion": false, + "textures": { + "emitter": "nae2:part/pcc_notifier_on", + "particle": "nae2:part/pcc_notifier_on" + }, + "elements": [ + { + "from": [ + 7, + 7, + 3 + ], + "to": [ + 9, + 9, + 4 + ], + "faces": { + "up": { + "texture": "#emitter", + "uv": [ + 9, + 7, + 10, + 9 + ], + "rotation": 90 + }, + "down": { + "texture": "#emitter", + "uv": [ + 9, + 7, + 10, + 9 + ], + "rotation": 270 + }, + "east": { + "texture": "#emitter", + "uv": [ + 9, + 7, + 10, + 9 + ], + "rotation": 180 + }, + "west": { + "texture": "#emitter", + "uv": [ + 9, + 7, + 10, + 9 + ] + } + } + }, + { + "from": [ + 7, + 7, + 0 + ], + "to": [ + 9, + 9, + 3 + ], + "shade": false, + "faces": { + "north": { + "texture": "#emitter", + "uv": [ + 6, + 7, + 8, + 9 + ], + "rotation": 270, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + } + } + }, + { + "from": [ + 6, + 7, + -1 + ], + "to": [ + 10, + 9, + 3 + ], + "shade": false, + "faces": { + "up": { + "texture": "#emitter", + "uv": [ + 5, + 6, + 9, + 10 + ], + "rotation": 90, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "down": { + "texture": "#emitter", + "uv": [ + 5, + 6, + 9, + 10 + ], + "rotation": 270, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + } + } + }, + { + "from": [ + 7, + 6, + -1 + ], + "to": [ + 9, + 10, + 3 + ], + "shade": false, + "faces": { + "west": { + "texture": "#emitter", + "uv": [ + 5, + 6, + 9, + 10 + ], + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "east": { + "texture": "#emitter", + "uv": [ + 5, + 6, + 9, + 10 + ], + "rotation": 180, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + } + } + } + ] +} diff --git a/src/main/resources/assets/nae2/textures/item/part/pcc_notifier.png b/src/main/resources/assets/nae2/textures/item/part/pcc_notifier.png new file mode 100644 index 0000000..37b552a Binary files /dev/null and b/src/main/resources/assets/nae2/textures/item/part/pcc_notifier.png differ diff --git a/src/main/resources/assets/nae2/textures/part/pcc_notifier_off.png b/src/main/resources/assets/nae2/textures/part/pcc_notifier_off.png new file mode 100644 index 0000000..5ad6856 Binary files /dev/null and b/src/main/resources/assets/nae2/textures/part/pcc_notifier_off.png differ diff --git a/src/main/resources/assets/nae2/textures/part/pcc_notifier_on.png b/src/main/resources/assets/nae2/textures/part/pcc_notifier_on.png new file mode 100644 index 0000000..3d5043b Binary files /dev/null and b/src/main/resources/assets/nae2/textures/part/pcc_notifier_on.png differ