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.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. *

* This cover will retrieve information, preferentially, using {@link IMetricsExporter#reportMetrics()}. Absent this * method, it will resort to {@link BaseMetaTileEntity#getInfoData()} instead. */ public class CoverMetricsTransmitter extends CoverBehaviorBase { @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 CoverMetricsTransmitter() { this(null); } public CoverMetricsTransmitter(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 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 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())); } } }