electrodynamics/archive/java/resonantinduction/electrical/multimeter/PartMultimeter.java
2014-01-11 17:44:07 +08:00

380 lines
8.5 KiB
Java

/**
*
*/
package resonantinduction.electrical.multimeter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MovingObjectPosition;
import net.minecraftforge.common.ForgeDirection;
import resonantinduction.core.ResonantInduction;
import resonantinduction.electrical.Electrical;
import universalelectricity.api.CompatibilityModule;
import universalelectricity.api.energy.IConductor;
import universalelectricity.api.energy.IEnergyNetwork;
import calclavia.lib.network.IPacketReceiver;
import codechicken.lib.data.MCDataInput;
import codechicken.lib.data.MCDataOutput;
import codechicken.lib.vec.Cuboid6;
import codechicken.lib.vec.Rotation;
import codechicken.lib.vec.Transformation;
import codechicken.lib.vec.Vector3;
import codechicken.microblock.FaceMicroClass;
import codechicken.multipart.JCuboidPart;
import codechicken.multipart.JNormalOcclusion;
import codechicken.multipart.NormalOcclusionTest;
import codechicken.multipart.TFacePart;
import codechicken.multipart.TMultiPart;
import com.google.common.io.ByteArrayDataInput;
import cpw.mods.fml.common.network.PacketDispatcher;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
/**
* Block that detects power.
*
* @author Calclavia
*
*/
public class PartMultimeter extends JCuboidPart implements IPacketReceiver, TFacePart, JNormalOcclusion
{
public static Cuboid6[][] bounds = new Cuboid6[6][2];
static
{
bounds[0][0] = new Cuboid6(1 / 8D, 0, 0, 7 / 8D, 1 / 8D, 1);
bounds[0][1] = new Cuboid6(0, 0, 1 / 8D, 1, 1 / 8D, 7 / 8D);
for (int s = 1; s < 6; s++)
{
Transformation t = Rotation.sideRotations[s].at(Vector3.center);
bounds[s][0] = bounds[0][0].copy().apply(t);
bounds[s][1] = bounds[0][1].copy().apply(t);
}
}
public Set<EntityPlayer> playersUsing = new HashSet<EntityPlayer>();
public enum DetectMode
{
NONE("none"), LESS_THAN("lessThan"), LESS_THAN_EQUAL("lessThanOrEqual"), EQUAL("equal"),
GREATER_THAN("greaterThanOrEqual"), GREATER_THAN_EQUAL("greaterThan");
public String display;
private DetectMode(String s)
{
display = s;
}
}
private DetectMode detectMode = DetectMode.NONE;
private long peakDetection;
private long energyLimit;
private long detectedEnergy;
private long detectedAverageEnergy;
public boolean redstoneOn;
private byte side;
private int ticks;
public void preparePlacement(int side, int itemDamage)
{
this.side = (byte) (side ^ 1);
}
@Override
public boolean activate(EntityPlayer player, MovingObjectPosition part, ItemStack item)
{
player.openGui(ResonantInduction.INSTANCE, this.side, world(), x(), y(), z());
return true;
}
@Override
public void update()
{
super.update();
this.ticks++;
if (!world().isRemote)
{
if (ticks % 20 == 0)
{
long prevDetectedEnergy = detectedEnergy;
updateDetection(doGetDetectedEnergy());
boolean outputRedstone = false;
switch (detectMode)
{
default:
break;
case EQUAL:
outputRedstone = detectedEnergy == energyLimit;
break;
case GREATER_THAN:
outputRedstone = detectedEnergy > energyLimit;
break;
case GREATER_THAN_EQUAL:
outputRedstone = detectedEnergy >= energyLimit;
break;
case LESS_THAN:
outputRedstone = detectedEnergy < energyLimit;
break;
case LESS_THAN_EQUAL:
outputRedstone = detectedEnergy <= energyLimit;
break;
}
if (outputRedstone != redstoneOn)
{
redstoneOn = outputRedstone;
this.tile().notifyTileChange();
}
if (prevDetectedEnergy != detectedEnergy)
{
this.getWriteStream().writeByte(3).writeByte((byte) detectMode.ordinal()).writeLong(detectedEnergy).writeLong(detectedAverageEnergy).writeLong(energyLimit);
}
}
}
if (!world().isRemote)
{
for (EntityPlayer player : playersUsing)
{
this.getWriteStream().writeByte(3).writeByte((byte) detectMode.ordinal()).writeLong(detectedEnergy).writeLong(detectedAverageEnergy).writeLong(energyLimit);
}
}
}
@Override
public void readDesc(MCDataInput packet)
{
this.side = packet.readByte();
detectMode = DetectMode.values()[packet.readByte()];
detectedEnergy = packet.readLong();
detectedAverageEnergy = packet.readLong();
energyLimit = packet.readLong();
}
@Override
public void writeDesc(MCDataOutput packet)
{
packet.writeByte(this.side);
packet.writeByte((byte) detectMode.ordinal());
packet.writeLong(detectedEnergy);
packet.writeLong(detectedAverageEnergy);
packet.writeLong(energyLimit);
}
@Override
public void read(MCDataInput packet)
{
read(packet, packet.readUByte());
}
public void read(MCDataInput packet, int packetID)
{
if (packetID == 1)
{
energyLimit = packet.readLong();
}
else if (packetID == 3)
{
this.detectMode = DetectMode.values()[packet.readByte()];
this.detectedEnergy = packet.readLong();
this.detectedAverageEnergy = packet.readLong();
this.energyLimit = packet.readLong();
}
}
@Override
public void onReceivePacket(ByteArrayDataInput data, EntityPlayer player, Object... extra)
{
toggleMode();
}
public long doGetDetectedEnergy()
{
return getDetectedEnergy(getDirection().getOpposite(), getDetectedTile());
}
public TileEntity getDetectedTile()
{
ForgeDirection direction = getDirection();
return world().getBlockTileEntity(x() + direction.offsetX, y() + direction.offsetY, z() + direction.offsetZ);
}
public ForgeDirection getDirection()
{
return ForgeDirection.getOrientation(this.side);
}
public static long getDetectedEnergy(ForgeDirection side, TileEntity tileEntity)
{
if (tileEntity instanceof IConductor)
{
IEnergyNetwork network = ((IConductor) tileEntity).getNetwork();
return network.getLastBuffer();
}
return CompatibilityModule.getEnergy(tileEntity, side);
}
public void updateDetection(long detected)
{
detectedEnergy = detected;
detectedAverageEnergy = (detectedAverageEnergy + detectedEnergy) / 2;
peakDetection = Math.max(peakDetection, detectedEnergy);
}
public long getDetectedEnergy()
{
return detectedEnergy;
}
public long getAverageDetectedEnergy()
{
return detectedAverageEnergy;
}
public void toggleMode()
{
if (!this.world().isRemote)
{
detectMode = DetectMode.values()[(detectMode.ordinal() + 1) % DetectMode.values().length];
}
else
{
PacketDispatcher.sendPacketToServer(ResonantInduction.PACKET_MULTIPART.getPacket(new universalelectricity.api.vector.Vector3(x(), y(), z()), getPartID()));
}
}
public int getPartID()
{
for (int i = 0; i < this.tile().partList().size(); i++)
{
if (this.tile().partMap(i) == this)
{
return i;
}
}
return 0;
}
@Override
public void load(NBTTagCompound nbt)
{
super.load(nbt);
side = nbt.getByte("side");
detectMode = DetectMode.values()[nbt.getByte("detectMode")];
energyLimit = nbt.getLong("energyLimit");
}
@Override
public void save(NBTTagCompound nbt)
{
super.save(nbt);
nbt.setByte("side", this.side);
nbt.setByte("detectMode", (byte) detectMode.ordinal());
nbt.setLong("energyLimit", energyLimit);
}
public DetectMode getMode()
{
return detectMode;
}
public float getLimit()
{
return energyLimit;
}
public float getPeak()
{
return peakDetection;
}
@Override
public String getType()
{
return "resonant_induction_multimeter";
}
@Override
public int getSlotMask()
{
return 1 << this.side;
}
@Override
public Cuboid6 getBounds()
{
return FaceMicroClass.aBounds()[0x10 | this.side];
}
@Override
public Iterable<Cuboid6> getOcclusionBoxes()
{
return Arrays.asList(bounds[this.side]);
}
@Override
public boolean occlusionTest(TMultiPart npart)
{
return NormalOcclusionTest.apply(this, npart);
}
@Override
public int redstoneConductionMap()
{
return 0;
}
@Override
public boolean solid(int arg0)
{
return true;
}
protected ItemStack getItem()
{
return new ItemStack(Electrical.itemMultimeter);
}
@Override
public Iterable<ItemStack> getDrops()
{
List<ItemStack> drops = new ArrayList<ItemStack>();
drops.add(getItem());
return drops;
}
@Override
public ItemStack pickItem(MovingObjectPosition hit)
{
return getItem();
}
@Override
@SideOnly(Side.CLIENT)
public void renderDynamic(Vector3 pos, float frame, int pass)
{
if (pass == 0)
{
RenderMultimeter.render(this, pos.x, pos.y, pos.z);
}
}
}