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()));
}
}
}