aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/common
diff options
context:
space:
mode:
authorquerns <33518699+querns@users.noreply.github.com>2023-09-13 10:03:17 -0500
committerGitHub <noreply@github.com>2023-09-13 17:03:17 +0200
commitb31052879e7601dbfea4c7fb53b94119c7bbf5c6 (patch)
tree69c6778c385c27ada8ec61478f5bc6da32bbc8fb /src/main/java/gregtech/common
parent62bb20ef6271b09dab45d66103a185774aba523e (diff)
downloadGT5-Unofficial-b31052879e7601dbfea4c7fb53b94119c7bbf5c6.tar.gz
GT5-Unofficial-b31052879e7601dbfea4c7fb53b94119c7bbf5c6.tar.bz2
GT5-Unofficial-b31052879e7601dbfea4c7fb53b94119c7bbf5c6.zip
Adds Metrics Transmitter Cover and Advanced GT Sensor Card for Information Panels (#2289)
* Adds several UI elements to multiblock drills * Adds metrics transmitter cover and associated sensor card * Fixes item icons and item name * Adds tooltips for adv. sensor card and metrics panel, fixes card/overlay icons, adds recipe for metrics cover * Refactor cover tab sync to send much smaller ISerializable payloads * Remove unused variable * Additional master merge cleanup * Adds interface for custom metrics export, adds oil drill support * Adds support for metrics covers retaining attached machine name for tooltip, metrics * * Adds discrete coordinates to Metrics Cover data * Adds machine to advanced sensor card tooltip * Adds cycle time and minimum energy hatch tier to multiblock ore drill tooltips * Moves many tooltip strings to i10n * Remove old GT_DisabledWhileActiveButton.java file that crept in during a messy merge * Spotless * Improve oil and ore drill metrics, more i18n * Addresses PR review concerns, adds more situations for self-destructing sensor cards * Remediates further PR concerns
Diffstat (limited to 'src/main/java/gregtech/common')
-rw-r--r--src/main/java/gregtech/common/GT_Proxy.java2
-rw-r--r--src/main/java/gregtech/common/covers/CoverInfo.java8
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Metrics_Transmitter.java212
-rw-r--r--src/main/java/gregtech/common/events/BaseMetricsCoverEvent.java21
-rw-r--r--src/main/java/gregtech/common/events/MetricsCoverDataEvent.java37
-rw-r--r--src/main/java/gregtech/common/events/MetricsCoverHostDeconstructedEvent.java16
-rw-r--r--src/main/java/gregtech/common/events/MetricsCoverSelfDestructEvent.java15
-rw-r--r--src/main/java/gregtech/common/items/GT_AdvancedSensorCard_Item.java323
-rw-r--r--src/main/java/gregtech/common/items/GT_MetaGenerated_Item_03.java20
-rw-r--r--src/main/java/gregtech/common/items/GT_SensorCard_Item.java2
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Cover_Tool.java24
-rw-r--r--src/main/java/gregtech/common/misc/GlobalMetricsCoverDatabase.java492
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java27
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java51
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java59
15 files changed, 1283 insertions, 26 deletions
diff --git a/src/main/java/gregtech/common/GT_Proxy.java b/src/main/java/gregtech/common/GT_Proxy.java
index d853ea5f0a..2da2b883ca 100644
--- a/src/main/java/gregtech/common/GT_Proxy.java
+++ b/src/main/java/gregtech/common/GT_Proxy.java
@@ -166,6 +166,7 @@ import gregtech.common.entities.GT_Entity_Arrow;
import gregtech.common.items.GT_MetaGenerated_Item_98;
import gregtech.common.items.GT_MetaGenerated_Tool_01;
import gregtech.common.misc.GlobalEnergyWorldSavedData;
+import gregtech.common.misc.GlobalMetricsCoverDatabase;
import gregtech.common.misc.spaceprojects.SpaceProjectWorldSavedData;
public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler, IGlobalWirelessEnergy {
@@ -1095,6 +1096,7 @@ public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler, IG
MinecraftForge.EVENT_BUS.register(new GlobalEnergyWorldSavedData(""));
MinecraftForge.EVENT_BUS.register(new SpaceProjectWorldSavedData());
MinecraftForge.EVENT_BUS.register(new GT_Worldgenerator.OregenPatternSavedData(""));
+ MinecraftForge.EVENT_BUS.register(new GlobalMetricsCoverDatabase());
FMLCommonHandler.instance()
.bus()
.register(new GT_Worldgenerator.OregenPatternSavedData(""));
diff --git a/src/main/java/gregtech/common/covers/CoverInfo.java b/src/main/java/gregtech/common/covers/CoverInfo.java
index e63fe6e176..0fac00218c 100644
--- a/src/main/java/gregtech/common/covers/CoverInfo.java
+++ b/src/main/java/gregtech/common/covers/CoverInfo.java
@@ -1,6 +1,7 @@
package gregtech.common.covers;
import java.lang.ref.WeakReference;
+import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
@@ -9,6 +10,8 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.Fluid;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizons.modularui.api.screen.ModularWindow;
import gregtech.api.GregTech_API;
@@ -238,4 +241,9 @@ public final class CoverInfo {
public int getFacadeMeta() {
return getCoverBehavior().getFacadeMeta(coverSide, coverID, coverData, coveredTile.get());
}
+
+ @NotNull
+ public List<String> getAdditionalTooltip(ISerializableObject data) {
+ return getCoverBehavior().getAdditionalTooltip(data);
+ }
}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Metrics_Transmitter.java b/src/main/java/gregtech/common/covers/GT_Cover_Metrics_Transmitter.java
new file mode 100644
index 0000000000..6d3cf529d3
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Metrics_Transmitter.java
@@ -0,0 +1,212 @@
+package gregtech.common.covers;
+
+import java.util.List;
+import java.util.UUID;
+
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.ByteArrayDataInput;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetricsExporter;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechDeviceInformation;
+import gregtech.api.metatileentity.BaseMetaTileEntity;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.events.MetricsCoverDataEvent;
+import gregtech.common.events.MetricsCoverSelfDestructEvent;
+import gregtech.common.misc.GlobalMetricsCoverDatabase;
+import gregtech.common.misc.GlobalMetricsCoverDatabase.State;
+import io.netty.buffer.ByteBuf;
+
+/**
+ * Used to transmit Nuclear Control information across dimensions. The only reason this is a cover is to artificially
+ * limit the number of total machines that transmit this data, for performance reasons.
+ * <p>
+ * This cover will retrieve information, preferentially, using {@link IMetricsExporter#reportMetrics()}. Absent this
+ * method, it will resort to {@link BaseMetaTileEntity#getInfoData()} instead.
+ */
+public class GT_Cover_Metrics_Transmitter
+ extends GT_CoverBehaviorBase<GT_Cover_Metrics_Transmitter.MetricsTransmitterData> {
+
+ @SuppressWarnings("SpellCheckingInspection")
+ public static final String FREQUENCY_MSB_KEY = "gt.metricscover.freq_msb";
+ @SuppressWarnings("SpellCheckingInspection")
+ public static final String FREQUENCY_LSB_KEY = "gt.metricscover.freq_lsb";
+ public static final String MACHINE_KEY = "machine_name";
+ public static final String CARD_STATE_KEY = "card_state";
+
+ @SuppressWarnings("unused")
+ public GT_Cover_Metrics_Transmitter() {
+ this(null);
+ }
+
+ public GT_Cover_Metrics_Transmitter(ITexture coverTexture) {
+ super(MetricsTransmitterData.class, coverTexture);
+ }
+
+ @Override
+ public MetricsTransmitterData createDataObject(int aLegacyData) {
+ // As a new cover, this shouldn't fire.
+ return new MetricsTransmitterData();
+ }
+
+ @Override
+ public MetricsTransmitterData createDataObject() {
+ return new MetricsTransmitterData();
+ }
+
+ @Override
+ protected int getTickRateImpl(ForgeDirection side, int aCoverID, MetricsTransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return 20;
+ }
+
+ @Override
+ public boolean isCoverPlaceable(ForgeDirection side, ItemStack aStack, ICoverable aTileEntity) {
+ return aTileEntity instanceof final IGregTechDeviceInformation device && device.isGivingInformation();
+ }
+
+ @Override
+ protected MetricsTransmitterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ MetricsTransmitterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ if (aTileEntity instanceof final BaseMetaTileEntity baseMTE && baseMTE.isGivingInformation()) {
+ final List<String> payload;
+
+ if (baseMTE.getMetaTileEntity() instanceof final IMetricsExporter metricsExporter) {
+ payload = metricsExporter.reportMetrics();
+ } else {
+ payload = ImmutableList.copyOf(baseMTE.getInfoData());
+ }
+
+ MinecraftForge.EVENT_BUS.post(new MetricsCoverDataEvent(
+ aCoverVariable.frequency,
+ payload,
+ new GlobalMetricsCoverDatabase.Coordinates(
+ baseMTE.getWorld().provider.getDimensionName(),
+ baseMTE.getXCoord(),
+ baseMTE.getYCoord(),
+ baseMTE.getZCoord()
+ )
+ ));
+ }
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected void onDroppedImpl(ForgeDirection side, int aCoverID, MetricsTransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ MinecraftForge.EVENT_BUS.post(new MetricsCoverSelfDestructEvent(aCoverVariable.frequency));
+ }
+
+ @Override
+ public void onPlayerAttach(EntityPlayer player, ItemStack aCover, ICoverable aTileEntity, ForgeDirection side) {
+ final UUID newFrequency = UUID.randomUUID();
+ final ItemStack cardStack = ItemList.NC_AdvancedSensorCard.get(1);
+
+ if (cardStack == null) {
+ return;
+ }
+
+ final NBTTagCompound tagCompound = new NBTTagCompound();
+ tagCompound.setLong(FREQUENCY_MSB_KEY, newFrequency.getMostSignificantBits());
+ tagCompound.setLong(FREQUENCY_LSB_KEY, newFrequency.getLeastSignificantBits());
+ tagCompound.setInteger(CARD_STATE_KEY, State.OPERATIONAL.getType());
+
+ if (aTileEntity instanceof final BaseMetaTileEntity baseMTE) {
+ final ItemStack baseMTEStack = baseMTE.getStackForm(1);
+ if (baseMTEStack != null) {
+ tagCompound.setTag(MACHINE_KEY, baseMTEStack.writeToNBT(new NBTTagCompound()));
+ }
+ }
+
+ cardStack.setTagCompound(tagCompound);
+ aTileEntity.getCoverInfoAtSide(side)
+ .setCoverData(new MetricsTransmitterData(newFrequency));
+
+ final EntityItem cardEntity = new EntityItem(player.worldObj, player.posX, player.posY, player.posZ, cardStack);
+ cardEntity.delayBeforeCanPickup = 0;
+ player.worldObj.spawnEntityInWorld(cardEntity);
+ }
+
+ @Override
+ public boolean allowsCopyPasteTool() {
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalTooltipImpl(MetricsTransmitterData data) {
+ return ImmutableList.of(
+ StatCollector.translateToLocalFormatted(
+ "gt.item.adv_sensor_card.tooltip.frequency",
+ EnumChatFormatting.UNDERLINE.toString() + EnumChatFormatting.YELLOW + data.frequency.toString()));
+ }
+
+ public static class MetricsTransmitterData implements ISerializableObject {
+
+ private UUID frequency;
+
+ public MetricsTransmitterData() {
+ this.frequency = UUID.randomUUID();
+ }
+
+ public MetricsTransmitterData(@NotNull UUID frequency) {
+ this.frequency = frequency;
+ }
+
+ @NotNull
+ public UUID getFrequency() {
+ return frequency;
+ }
+
+ @NotNull
+ @Override
+ public ISerializableObject copy() {
+ return new MetricsTransmitterData(frequency);
+ }
+
+ @NotNull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setLong(FREQUENCY_MSB_KEY, frequency.getMostSignificantBits());
+ tag.setLong(FREQUENCY_LSB_KEY, frequency.getLeastSignificantBits());
+ return tag;
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ if (aNBT instanceof final NBTTagCompound tag) {
+ frequency = new UUID(tag.getLong(FREQUENCY_MSB_KEY), tag.getLong(FREQUENCY_LSB_KEY));
+ }
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeLong(frequency.getMostSignificantBits());
+ aBuf.writeLong(frequency.getLeastSignificantBits());
+ }
+
+ @NotNull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, @Nullable EntityPlayerMP aPlayer) {
+ return new MetricsTransmitterData(new UUID(aBuf.readLong(), aBuf.readLong()));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/events/BaseMetricsCoverEvent.java b/src/main/java/gregtech/common/events/BaseMetricsCoverEvent.java
new file mode 100644
index 0000000000..953d6fbfcf
--- /dev/null
+++ b/src/main/java/gregtech/common/events/BaseMetricsCoverEvent.java
@@ -0,0 +1,21 @@
+package gregtech.common.events;
+
+import java.util.UUID;
+
+import org.jetbrains.annotations.NotNull;
+
+import cpw.mods.fml.common.eventhandler.Event;
+
+public abstract class BaseMetricsCoverEvent extends Event {
+
+ protected final UUID frequency;
+
+ public BaseMetricsCoverEvent(@NotNull UUID frequency) {
+ this.frequency = frequency;
+ }
+
+ @NotNull
+ public UUID getFrequency() {
+ return frequency;
+ }
+}
diff --git a/src/main/java/gregtech/common/events/MetricsCoverDataEvent.java b/src/main/java/gregtech/common/events/MetricsCoverDataEvent.java
new file mode 100644
index 0000000000..92a5aa663a
--- /dev/null
+++ b/src/main/java/gregtech/common/events/MetricsCoverDataEvent.java
@@ -0,0 +1,37 @@
+package gregtech.common.events;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.jetbrains.annotations.NotNull;
+
+import gregtech.common.misc.GlobalMetricsCoverDatabase;
+
+/**
+ * Event fired when the Metrics Transmitter cover sends an information packet.
+ */
+public class MetricsCoverDataEvent extends BaseMetricsCoverEvent {
+
+ @NotNull
+ private final List<String> payload;
+
+ @NotNull
+ private final GlobalMetricsCoverDatabase.Coordinates coordinates;
+
+ public MetricsCoverDataEvent(@NotNull UUID frequency, @NotNull List<String> payload,
+ @NotNull GlobalMetricsCoverDatabase.Coordinates coordinates) {
+ super(frequency);
+ this.payload = payload;
+ this.coordinates = coordinates;
+ }
+
+ @NotNull
+ public List<String> getPayload() {
+ return payload;
+ }
+
+ @NotNull
+ public GlobalMetricsCoverDatabase.Coordinates getCoordinates() {
+ return coordinates;
+ }
+}
diff --git a/src/main/java/gregtech/common/events/MetricsCoverHostDeconstructedEvent.java b/src/main/java/gregtech/common/events/MetricsCoverHostDeconstructedEvent.java
new file mode 100644
index 0000000000..490bd7d0b0
--- /dev/null
+++ b/src/main/java/gregtech/common/events/MetricsCoverHostDeconstructedEvent.java
@@ -0,0 +1,16 @@
+package gregtech.common.events;
+
+import java.util.UUID;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Event fired when the machine housing a Metrics Transmitter cover is deconstructed, but the cover remains
+ * attached.
+ */
+public class MetricsCoverHostDeconstructedEvent extends BaseMetricsCoverEvent {
+
+ public MetricsCoverHostDeconstructedEvent(@NotNull UUID frequency) {
+ super(frequency);
+ }
+}
diff --git a/src/main/java/gregtech/common/events/MetricsCoverSelfDestructEvent.java b/src/main/java/gregtech/common/events/MetricsCoverSelfDestructEvent.java
new file mode 100644
index 0000000000..d554cbcc2b
--- /dev/null
+++ b/src/main/java/gregtech/common/events/MetricsCoverSelfDestructEvent.java
@@ -0,0 +1,15 @@
+package gregtech.common.events;
+
+import java.util.UUID;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Event fired when a Metrics Transmitter cover is detached from its machine with a crowbar.
+ */
+public class MetricsCoverSelfDestructEvent extends BaseMetricsCoverEvent {
+
+ public MetricsCoverSelfDestructEvent(@NotNull UUID frequency) {
+ super(frequency);
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_AdvancedSensorCard_Item.java b/src/main/java/gregtech/common/items/GT_AdvancedSensorCard_Item.java
new file mode 100644
index 0000000000..820fe59952
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_AdvancedSensorCard_Item.java
@@ -0,0 +1,323 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.Mods.GregTech;
+import static gregtech.common.covers.GT_Cover_Metrics_Transmitter.CARD_STATE_KEY;
+import static gregtech.common.covers.GT_Cover_Metrics_Transmitter.FREQUENCY_LSB_KEY;
+import static gregtech.common.covers.GT_Cover_Metrics_Transmitter.FREQUENCY_MSB_KEY;
+import static gregtech.common.covers.GT_Cover_Metrics_Transmitter.MACHINE_KEY;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.ImmutableList;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.common.misc.GlobalMetricsCoverDatabase;
+import gregtech.common.misc.GlobalMetricsCoverDatabase.State;
+import shedar.mods.ic2.nuclearcontrol.api.CardState;
+import shedar.mods.ic2.nuclearcontrol.api.ICardWrapper;
+import shedar.mods.ic2.nuclearcontrol.api.IPanelDataSource;
+import shedar.mods.ic2.nuclearcontrol.api.PanelSetting;
+import shedar.mods.ic2.nuclearcontrol.api.PanelString;
+
+@SuppressWarnings("unused")
+public class GT_AdvancedSensorCard_Item extends Item implements IPanelDataSource {
+
+ public static final UUID CARD_TYPE_ID = UUID.fromString("ff952e84-7608-4c4a-85af-dd6e1aa27fc7");
+
+ // This has obfuscated formatting, so no need to localize it.
+ private static final ImmutableList<PanelString> SELF_DESTRUCTED_OUTPUT = ImmutableList
+ .of(prebakePanelString(EnumChatFormatting.OBFUSCATED + "critical error" + EnumChatFormatting.RESET, true));
+
+ private static final ImmutableList<PanelString> DECONSTRUCTED_OUTPUT = ImmutableList.of(
+ prebakePanelString(StatCollector.translateToLocal("gt.item.adv_sensor_card.error.deconstructed.1"), true),
+ prebakePanelString(StatCollector.translateToLocal("gt.item.adv_sensor_card.error.deconstructed.2"), true));
+
+ private static final ImmutableList<PanelString> NO_DATA_FOUND = ImmutableList
+ .of(prebakePanelString(StatCollector.translateToLocal("gt.item.adv_sensor_card.error.no_data"), true));
+
+ private int payloadSize = 0;
+
+ @SideOnly(Side.CLIENT)
+ private IIcon normalIcon;
+ @SideOnly(Side.CLIENT)
+ private IIcon selfDestructedIcon;
+
+ @SuppressWarnings("unused")
+ public GT_AdvancedSensorCard_Item() {
+ super();
+
+ GameRegistry.registerItem(this, "gt.advancedsensorcard", GregTech.ID);
+ setUnlocalizedName("gt.advancedsensorcard");
+ setMaxStackSize(1);
+ setNoRepair();
+ }
+
+ @Override
+ public void addInformation(final ItemStack itemStack, final EntityPlayer player, final List<String> tooltip,
+ final boolean p_77624_4_) {
+ super.addInformation(itemStack, player, tooltip, p_77624_4_);
+
+ final Optional<State> cardState = getCardState(itemStack);
+ if (cardState.isPresent()) {
+ final State state = cardState.get();
+
+ if (state == State.SELF_DESTRUCTED) {
+ tooltip.add(StatCollector.translateToLocal("gt.item.adv_sensor_card.tooltip.fried.1"));
+ tooltip.add(StatCollector.translateToLocal("gt.item.adv_sensor_card.tooltip.fried.2"));
+ tooltip.add(StatCollector.translateToLocal("gt.item.adv_sensor_card.tooltip.fried.3"));
+ } else {
+ getMachineName(itemStack).ifPresent(
+ machineName -> tooltip.add(
+ StatCollector
+ .translateToLocalFormatted("gt.item.adv_sensor_card.tooltip.machine", machineName)));
+ getUUID(itemStack).ifPresent(
+ uuid -> tooltip.add(
+ StatCollector
+ .translateToLocalFormatted("gt.item.adv_sensor_card.tooltip.frequency", uuid.toString())));
+ }
+ } else {
+ tooltip.add(StatCollector.translateToLocal("gt.item.adv_sensor_card.tooltip.recipe_hint"));
+ }
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item aItem, CreativeTabs aCreativeTab, List<ItemStack> aOutputSubItems) {}
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(final IIconRegister aIconRegister) {
+ super.registerIcons(aIconRegister);
+ itemIcon = aIconRegister.registerIcon(GregTech.ID + ":gt.advancedsensorcard");
+ normalIcon = itemIcon;
+ selfDestructedIcon = aIconRegister.registerIcon(GregTech.ID + ":gt.advancedsensorcardburned");
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(final ItemStack stack, final int renderPass) {
+ return getIconIndex(stack);
+ }
+
+ @Override
+ public IIcon getIconIndex(final ItemStack itemStack) {
+ return getCardState(itemStack).filter(Predicate.isEqual(State.SELF_DESTRUCTED))
+ .map(ignored -> selfDestructedIcon)
+ .orElse(normalIcon);
+ }
+
+ @Override
+ public CardState update(TileEntity tileEntity, ICardWrapper card, int maxRange) {
+ return update(tileEntity.getWorldObj(), card, maxRange);
+ }
+
+ @Override
+ public CardState update(World world, ICardWrapper card, int maxRange) {
+ getDataFromDatabase(card).ifPresent(data -> {
+ reconcileSelfDestructedCard(card.getItemStack(), data.getState());
+ card.setInt(
+ CARD_STATE_KEY,
+ data.getState()
+ .getType());
+ payloadSize = switch (data.getState()) {
+ case SELF_DESTRUCTED -> SELF_DESTRUCTED_OUTPUT.size();
+ case HOST_DECONSTRUCTED -> DECONSTRUCTED_OUTPUT.size() + getMachineName(card.getItemStack()).map(x -> 1)
+ .orElse(0);
+ case OPERATIONAL -> data.getPayload()
+ .map(List::size)
+ .orElse(0)
+ + getMachineName(card.getItemStack()).map(x -> 1)
+ .orElse(0)
+ + data.getCoordinates()
+ .map(x -> 2)
+ .orElse(0);
+ };
+ });
+ return CardState.OK;
+ }
+
+ @Override
+ public List<PanelString> getStringData(final int displaySettings, final ICardWrapper card,
+ final boolean showLabels) {
+ // This method needs to return a mutable list, since the calling routine in NuclearCraft appends an item to the
+ // head of the list. Hence, all the array copying.
+
+ return getCardState(card).map(state -> switch (state) {
+ case SELF_DESTRUCTED -> new ArrayList<>(SELF_DESTRUCTED_OUTPUT);
+ case HOST_DECONSTRUCTED -> {
+ final ArrayList<PanelString> list = new ArrayList<>();
+ getMachineName(card.getItemStack()).ifPresent(name -> list.add(prebakePanelString(name, true)));
+ list.addAll(DECONSTRUCTED_OUTPUT);
+ yield list;
+ }
+ case OPERATIONAL -> getDataFromDatabase(card).map(data -> {
+ final ImmutableList.Builder<String> builder = ImmutableList.builder();
+
+ getMachineName(card.getItemStack()).ifPresent(builder::add);
+ data.getCoordinates()
+ .ifPresent(
+ coordinates -> builder.add(
+ StatCollector.translateToLocalFormatted(
+ "gt.item.adv_sensor_card.dimension",
+ coordinates.getDimension()),
+ StatCollector.translateToLocalFormatted(
+ "gt.item.adv_sensor_card.coords",
+ coordinates.getLocalizedCoordinates())));
+
+ data.getPayload()
+ .ifPresent(builder::addAll);
+
+ return builder.build();
+ })
+ .filter(payload -> !payload.isEmpty())
+ .map(
+ payload -> IntStream.range(0, payload.size())
+ .filter(i -> (displaySettings & (1 << i)) != 0)
+ .mapToObj(i -> prebakePanelString(payload.get(i), i == 0))
+ .collect(Collectors.toCollection(ArrayList::new)))
+ .orElse(null);
+ })
+ .orElse(new ArrayList<>(NO_DATA_FOUND));
+ }
+
+ @Override
+ public List<PanelSetting> getSettingsList() {
+ return payloadSize == 0 ? ImmutableList.of()
+ : ImmutableList.copyOf(
+ IntStream.range(0, Math.min(payloadSize, 31))
+ .mapToObj(i -> new PanelSetting(String.valueOf(i + 1), 1 << i, getCardType()))
+ .iterator());
+ }
+
+ @Override
+ public UUID getCardType() {
+ return CARD_TYPE_ID;
+ }
+
+ @Override
+ public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int slot, boolean isHeld) {
+ super.onUpdate(stack, worldIn, entityIn, slot, isHeld);
+ // At the time of this comment's writing, there are 52 matches of the regex:
+ // /% \d+0 \)?\s*== 0/ in the code base, indicating an over-reliance on events happening on either the 10th or
+ // 20th tick. Let's tick on something slightly off of that. A prime number will do nicely.
+ if ((worldIn.getWorldTime() % 20) == 13) {
+ getDataFromDatabase(stack).ifPresent(data -> {
+ reconcileSelfDestructedCard(stack, data.getState());
+ if (!stack.hasTagCompound()) {
+ stack.setTagCompound(new NBTTagCompound());
+ }
+
+ stack.getTagCompound()
+ .setInteger(
+ CARD_STATE_KEY,
+ data.getState()
+ .getType());
+ });
+ }
+ }
+
+ private void reconcileSelfDestructedCard(ItemStack stack, State newState) {
+ getUUID(stack).ifPresent(uuid -> getCardState(stack).ifPresent(oldState -> {
+ if (newState == State.SELF_DESTRUCTED && oldState != State.SELF_DESTRUCTED) {
+ GlobalMetricsCoverDatabase.clearSelfDestructedFrequency(uuid);
+ }
+ }));
+
+ }
+
+ @NotNull
+ private Optional<State> getCardState(ICardWrapper card) {
+ return getCardState(card.getItemStack());
+ }
+
+ @NotNull
+ private Optional<State> getCardState(ItemStack itemStack) {
+ if (itemStack.hasTagCompound() && itemStack.getTagCompound()
+ .hasKey(CARD_STATE_KEY)) {
+ return State.find(
+ itemStack.getTagCompound()
+ .getInteger(CARD_STATE_KEY));
+ }
+
+ return Optional.empty();
+ }
+
+ @NotNull
+ private Optional<UUID> getUUID(ItemStack stack) {
+ if (stack.hasTagCompound()) {
+ NBTTagCompound nbt = stack.getTagCompound();
+ if (nbt.hasKey(FREQUENCY_LSB_KEY) && nbt.hasKey(FREQUENCY_MSB_KEY)) {
+ return Optional.of(new UUID(nbt.getLong(FREQUENCY_MSB_KEY), nbt.getLong(FREQUENCY_LSB_KEY)));
+ }
+ }
+
+ return Optional.empty();
+ }
+
+ @NotNull
+ private Optional<String> getMachineName(ItemStack stack) {
+ if (stack.hasTagCompound() && stack.getTagCompound()
+ .hasKey(MACHINE_KEY)) {
+ try {
+ final ItemStack machine = ItemStack.loadItemStackFromNBT(
+ stack.getTagCompound()
+ .getCompoundTag(MACHINE_KEY));
+ if (machine != null) {
+ return Optional.of(machine.getDisplayName());
+ }
+ } catch (Exception ignored) {}
+ }
+
+ return Optional.empty();
+ }
+
+ @NotNull
+ private Optional<GlobalMetricsCoverDatabase.Data> getDataFromDatabase(ICardWrapper card) {
+ return getDataFromDatabase(card.getItemStack());
+ }
+
+ @NotNull
+ private Optional<GlobalMetricsCoverDatabase.Data> getDataFromDatabase(ItemStack stack) {
+ return getUUID(stack).flatMap(GlobalMetricsCoverDatabase::getData);
+ }
+
+ @NotNull
+ private static PanelString prebakePanelString(String info) {
+ return prebakePanelString(info, false);
+ }
+
+ @NotNull
+ private static PanelString prebakePanelString(String info, boolean center) {
+ final PanelString panelString = new PanelString();
+ if (center) {
+ panelString.textCenter = info;
+ } else {
+ panelString.textLeft = info;
+ }
+ return panelString;
+
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_03.java b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_03.java
index bede46adc9..f980c8031b 100644
--- a/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_03.java
+++ b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_03.java
@@ -1,5 +1,7 @@
package gregtech.common.items;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_METRICS_TRANSMITTER;
import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_UEV;
import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_UHV;
import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_UIV;
@@ -21,6 +23,7 @@ import static gregtech.client.GT_TooltipHandler.Tier.ZPM;
import static gregtech.client.GT_TooltipHandler.registerTieredTooltip;
import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
import gregtech.api.enums.ItemList;
import gregtech.api.enums.Materials;
import gregtech.api.enums.OrePrefixes;
@@ -29,6 +32,7 @@ import gregtech.api.enums.TC_Aspects;
import gregtech.api.items.GT_MetaGenerated_Item_X32;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.common.covers.GT_Cover_Metrics_Transmitter;
import gregtech.common.covers.GT_Cover_SolarPanel;
public class GT_MetaGenerated_Item_03 extends GT_MetaGenerated_Item_X32 {
@@ -911,6 +915,22 @@ public class GT_MetaGenerated_Item_03 extends GT_MetaGenerated_Item_X32 {
"By the powers of Greg, I command this star to be really hot.",
SubTag.NO_UNIFICATION));
+ ItemList.Cover_Metrics_Transmitter.set(
+ addItem(
+ 232,
+ "Metrics Transmitter Cover",
+ String.join(
+ "/n ",
+ "Taking Information Panels to the next level!",
+ "Creates a GregTech Advanced Sensor Card when attached",
+ "Works across dimensions or if machine is dismantled",
+ "Removing this cover will destroy the linked card",
+ GT_Values.AuthorQuerns)));
+ GregTech_API.registerCover(
+ ItemList.Cover_Metrics_Transmitter.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_METRICS_TRANSMITTER)),
+ new GT_Cover_Metrics_Transmitter(TextureFactory.of(OVERLAY_METRICS_TRANSMITTER)));
+
ItemList.Optical_Cpu_Containment_Housing.set(addItem(727, "Optical CPU Containment Housing", "CPU Housing", o));
ItemList.Optically_Perfected_CPU.set(addItem(726, "Optically Perfected CPU", "Perfected CPU!", o));
ItemList.Optically_Compatible_Memory.set(addItem(725, "Optically Compatible Memory", "Its in the name!", o));
diff --git a/src/main/java/gregtech/common/items/GT_SensorCard_Item.java b/src/ma