package zmaster587.advancedRocketry.tile.multiblock;
import io.netty.buffer.ByteBuf;
import java.util.List;
import cpw.mods.fml.relauncher.Side;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SoundCategory;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.MathHelper;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
import net.minecraftforge.common.ForgeChunkManager.Type;
import net.minecraftforge.common.util.ForgeDirection;
import zmaster587.advancedRocketry.AdvancedRocketry;
import zmaster587.advancedRocketry.entity.EntityItemAbducted;
import zmaster587.libVulpes.api.LibVulpesBlocks;
import zmaster587.libVulpes.block.BlockMeta;
import zmaster587.libVulpes.block.RotatableBlock;
import zmaster587.libVulpes.interfaces.ILinkableTile;
import zmaster587.libVulpes.inventory.modules.IGuiCallback;
import zmaster587.libVulpes.inventory.modules.ModuleBase;
import zmaster587.libVulpes.inventory.modules.ModuleNumericTextbox;
import zmaster587.libVulpes.inventory.modules.ModuleRedstoneOutputButton;
import zmaster587.libVulpes.inventory.modules.ModuleSlotArray;
import zmaster587.libVulpes.inventory.modules.ModuleText;
import zmaster587.libVulpes.items.ItemLinker;
import zmaster587.libVulpes.network.PacketHandler;
import zmaster587.libVulpes.network.PacketMachine;
import zmaster587.libVulpes.tile.multiblock.TileMultiPowerConsumer;
import zmaster587.libVulpes.util.BlockPosition;
import zmaster587.libVulpes.util.EmbeddedInventory;
import zmaster587.libVulpes.util.ZUtils;
import zmaster587.libVulpes.util.ZUtils.RedstoneState;
public class TileRailgun extends TileMultiPowerConsumer implements IInventory, ILinkableTile, IGuiCallback {
private EmbeddedInventory inv;
Ticket ticket;
public long recoil;
int minStackTransferSize = 1;
ModuleNumericTextbox textBox;
RedstoneState state;
ModuleRedstoneOutputButton redstoneControl;
public static final Object[][][] structure = {
{ {null, null, null, null, null},
{null, null, "coilCopper" , null, null},
{null, "coilCopper", "coilCopper" , "coilCopper", null},
{null, null, "coilCopper" , null, null},
{null, null, null, null, null}},
{ {null, null, null, null, null},
{null, null, "coilCopper" , null, null},
{null, "coilCopper", Blocks.air , "coilCopper", null},
{null, null, "coilCopper" , null, null},
{null, null, null, null, null}},
{ {null, null, null, null, null},
{null, null, "coilCopper" , null, null},
{null, "coilCopper", Blocks.air , "coilCopper", null},
{null, null, "coilCopper" , null, null},
{null, null, null, null, null}},
{ {null, null, null, null, null},
{null, null, "coilCopper" , null, null},
{null, "coilCopper", Blocks.air , "coilCopper", null},
{null, null, "coilCopper" , null, null},
{null, null, null, null, null}},
{ {null, null, null, null, null},
{null, null, "coilCopper" , null, null},
{null, "coilCopper", Blocks.air , "coilCopper", null},
{null, null, "coilCopper" , null, null},
{null, null, null, null, null}},
{ {null, null, null, null, null},
{null, null, "coilCopper" , null, null},
{null, "coilCopper", Blocks.air , "coilCopper", null},
{null, null, "coilCopper" , null, null},
{null, null, null, null, null}},
{ {null, null, null, null, null},
{null, null, "coilCopper" , null, null},
{null, "coilCopper", Blocks.air , "coilCopper", null},
{null, null, "coilCopper" , null, null},
{null, null, null, null, null}},
{ {'*', '*', '*', '*', '*'},
{'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'},
{'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'},
{'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'},
{'*', '*', '*', '*', '*'}},
{{'*', '*', 'c', '*', '*'},
{'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'},
{'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'},
{'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'},
{'*', '*', '*', '*', '*'}}
};
public TileRailgun() {
inv = new EmbeddedInventory(1);
powerPerTick = 100000;
redstoneControl = new ModuleRedstoneOutputButton(174, 4, -1, "", this);
state = RedstoneState.OFF;
}
@Override
protected int requiredPowerPerTick() {
BlockPosition pos = getDestPosition();
if(pos != null) {
int distance = (int)Math.sqrt(Math.pow(pos.x - this.xCoord,2) + Math.pow(pos.z - this.zCoord, 2));;
if(getDestDimId() == this.worldObj.provider.dimensionId)
distance = distance*10 + 50000;
return Math.min(distance, super.requiredPowerPerTick());
}
return super.requiredPowerPerTick();
}
/**
* @return the destionation DIMID or -1 if not valid
*/
private int getDestDimId() {
ItemStack stack = inv.getStackInSlot(0);
if(stack != null && stack.getItem() instanceof ItemLinker) {
return ItemLinker.getDimId(stack);
}
return -1;
}
/**
* @return the destionation DIMID or null if not valid
*/
private BlockPosition getDestPosition() {
ItemStack stack = inv.getStackInSlot(0);
if(stack != null && stack.getItem() instanceof ItemLinker && ItemLinker.isSet(stack)) {
return new BlockPosition(ItemLinker.getMasterX(stack), ItemLinker.getMasterY(stack), ItemLinker.getMasterZ(stack));
}
return null;
}
@Override
public List<BlockMeta> getAllowableWildCardBlocks() {
List<BlockMeta> blocks = super.getAllowableWildCardBlocks();
blocks.addAll(getAllowableBlocks('P'));
blocks.addAll(getAllowableBlocks('I'));
blocks.addAll(getAllowableBlocks('O'));
blocks.add(new BlockMeta(LibVulpesBlocks.blockAdvStructureBlock));
return blocks;
}
@Override
public Object[][][] getStructure() {
return structure;
}
@Override
public List<ModuleBase> getModules(int ID, EntityPlayer player) {
List<ModuleBase> modules = super.getModules(ID, player);
modules.add(new ModuleSlotArray(40, 40, this, 0, 1));
if(worldObj.isRemote) {
//if(textBox == null) {
textBox = new ModuleNumericTextbox(this, 80, 40, 32, 12, 2);
//}
textBox.setText(String.valueOf(minStackTransferSize));
modules.add(new ModuleText(60, 25, "Min Transfer Size", 0x2b2b2b));
modules.add(textBox);
}
modules.add(redstoneControl);
return modules;
}
@Override
protected void onCreated() {
if(ticket == null) {
ticket = ForgeChunkManager.requestTicket(AdvancedRocketry.instance, this.worldObj, Type.NORMAL);
if(ticket != null)
ForgeChunkManager.forceChunk(ticket, new ChunkCoordIntPair(this.xCoord / 16 - (this.xCoord < 0 ? 1 : 0), this.zCoord / 16 - (this.zCoord < 0 ? 1 : 0)));
}
}
@Override
public void invalidate() {
super.invalidate();
ForgeChunkManager.releaseTicket(ticket);
}
@Override
public void onInventoryUpdated() {
//Needs completion
if(itemInPorts.isEmpty() /*&& !worldObj.isRemote*/) {
attemptCompleteStructure();
}
}
@Override
public void onInventoryButtonPressed(int buttonId) {
super.onInventoryButtonPressed(buttonId);
if(buttonId == -1) {
state = redstoneControl.getState();
PacketHandler.sendToServer(new PacketMachine(this, (byte)5));
}
}
@Override
protected void onRunningPoweredTick() {
//Do nothing, or add charge effect
}
@Override
public void useEnergy(int amt) {
if(!worldObj.isRemote && enabled && isRedstoneStateSatisfied() && attemptCargoTransfer())
super.useEnergy(amt);
}
@Override
public boolean isRunning() {
return isComplete();
}
private boolean isRedstoneStateSatisfied() {
if(state == RedstoneState.OFF)
return true;
boolean powered = worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord);
return (state == RedstoneState.ON && powered) || (!powered && state == RedstoneState.INVERTED);
}
private boolean attemptCargoTransfer() {
if(worldObj.isRemote)
return false;
ItemStack tfrStack = null;
IInventory inv2 = null;
int index = 0;
int xPos = 0,yPos = 0,zPos = 0;
out:
for(IInventory inv : this.itemInPorts) {
for(int i = inv.getSizeInventory() - 1; i >= 0 ; i--) {
if((tfrStack = inv.getStackInSlot(i)) != null && inv.getStackInSlot(i).stackSize >= minStackTransferSize) {
inv2 = inv;
index = i;
xPos = ((TileEntity)inv).xCoord;
yPos = ((TileEntity)inv).yCoord;
zPos = ((TileEntity)inv).zCoord;
break out;
}
else tfrStack = null;
}
}
if(tfrStack != null) {
BlockPosition pos = getDestPosition();
if(pos != null) {
int dimId;
dimId = getDestDimId();
if(dimId != -1) {
World world = DimensionManager.getWorld(dimId);
TileEntity tile;
if(world != null && (tile = world.getTileEntity(pos.x, pos.y, pos.z)) instanceof TileRailgun && ((TileRailgun)tile).canRecieveCargo(tfrStack) &&
zmaster587.advancedRocketry.dimension.DimensionManager.getInstance().areDimensionsInSamePlanetMoonSystem(this.worldObj.provider.dimensionId,
zmaster587.advancedRocketry.dimension.DimensionManager.getEffectiveDimId(world, tile.xCoord, tile.zCoord).getId())) {
((TileRailgun)tile).onRecieveCargo(tfrStack);
inv2.setInventorySlotContents(index, null);
inv2.markDirty();
world.markBlockForUpdate(xPos, yPos, zPos);
ForgeDirection dir = RotatableBlock.getFront(this.getBlockMetadata());
EntityItemAbducted ent = new EntityItemAbducted(this.worldObj, this.xCoord - 2*dir.offsetX + 0.5f, this.yCoord + 9, this.zCoord - 2*dir.offsetZ + 0.5f, tfrStack);
this.worldObj.spawnEntityInWorld(ent);
PacketHandler.sendToNearby(new PacketMachine(this, (byte) 3), this.worldObj.provider.dimensionId, this.xCoord - dir.offsetX, this.yCoord + 5, this.zCoord - dir.offsetZ, 64);
return true;
}
}
}
}
return false;
}
public boolean canRecieveCargo(ItemStack stack) {
for(IInventory inv : this.itemOutPorts) {
if(ZUtils.numEmptySlots(inv) > 0)
return true;
}
return false;
}
public void onRecieveCargo(ItemStack stack) {
for(IInventory inv : this.itemOutPorts) {
if(ZUtils.doesInvHaveRoom(stack, inv)) {
ZUtils.mergeInventory(stack, inv);
break;
}
}
}
@Override
public String getMachineName() {
return "tile.railgun.name";
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
return AxisAlignedBB.getBoundingBox(xCoord -5,yCoord, zCoord -5, xCoord + 5, yCoord + 8, zCoord + 5);
}
@Override
public int getSizeInventory() {
return 1;
}
@Override
public ItemStack getStackInSlot(int i) {
return inv.getStackInSlot(i);
}
@Override
public ItemStack decrStackSize(int i, int j) {
return inv.decrStackSize(i, j);
}
@Override
public ItemStack getStackInSlotOnClosing(int i) {
return inv.getStackInSlotOnClosing(i);
}
@Override
public void setInventorySlotContents(int i, ItemStack j) {
inv.setInventorySlotContents(i, j);
}
@Override
public String getInventoryName() {
return getMachineName();
}
@Override
public boolean hasCustomInventoryName() {
return false;
}
@Override
public int getInventoryStackLimit() {
return 1;
}
@Override
public boolean isUseableByPlayer(EntityPlayer player) {
return true;
}
@Override
public void openInventory() {
}
@Override
public void closeInventory() {
}
@Override
public boolean isItemValidForSlot(int i, ItemStack stack) {
return stack == null || stack.getItem() instanceof ItemLinker;
}
@Override
public boolean onLinkStart(ItemStack item, TileEntity entity,
EntityPlayer player, World world) {
ItemLinker.setMasterCoords(item, this.xCoord, this.yCoord, this.zCoord);
ItemLinker.setDimId(item, world.provider.dimensionId);
if(!world.isRemote)
player.addChatMessage(new ChatComponentText("Coordinates programmed into Linker"));
return true;
}
@Override
public boolean onLinkComplete(ItemStack item, TileEntity entity,
EntityPlayer player, World world) {
return false;
}
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
inv.writeToNBT(nbt);
nbt.setInteger("minTfrSize", minStackTransferSize);
nbt.setByte("redstoneState", (byte) state.ordinal());
}
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
inv.readFromNBT(nbt);
minStackTransferSize = nbt.getInteger("minTfrSize");
state = RedstoneState.values()[nbt.getByte("redstoneState")];
redstoneControl.setRedstoneState(state);
}
@Override
public void writeDataToNetwork(ByteBuf out, byte id) {
if(id == 4)
out.writeInt(minStackTransferSize);
else if(id == 5)
out.writeByte(state.ordinal());
else
super.writeDataToNetwork(out, id);
}
@Override
public void readDataFromNetwork(ByteBuf in, byte packetId,
NBTTagCompound nbt) {
if(packetId == 4)
nbt.setInteger("minTransferSize", in.readInt());
else if(packetId == 5)
nbt.setByte("state", in.readByte());
else
super.readDataFromNetwork(in, packetId, nbt);
}
@Override
public void useNetworkData(EntityPlayer player, Side side, byte id,
NBTTagCompound nbt) {
if(side.isClient()) {
if(id == 3) {
ForgeDirection dir = RotatableBlock.getFront(this.getBlockMetadata());
worldObj.playSound(xCoord + dir.offsetX, yCoord + 5, zCoord + dir.offsetZ, "advancedrocketry:railgunBang", Minecraft.getMinecraft().gameSettings.getSoundLevel(SoundCategory.BLOCKS), 0.975f + worldObj.rand.nextFloat()*0.05f, false);
recoil = worldObj.getTotalWorldTime();
}
}
else if(id == 4) {
minStackTransferSize = nbt.getInteger("minTransferSize");
}
else if(id == 5) {
state = RedstoneState.values()[nbt.getByte("state")];
}
else
super.useNetworkData(player, side, id, nbt);
}
@Override
public void onModuleUpdated(ModuleBase module) {
if(module == textBox) {
if(textBox.getText().isEmpty())
minStackTransferSize = 1;
else
minStackTransferSize = MathHelper.clamp_int(Integer.parseInt(textBox.getText()),1, 64);
PacketHandler.sendToServer(new PacketMachine(this, (byte)4));
}
}
@Override
protected void writeNetworkData(NBTTagCompound nbt) {
super.writeNetworkData(nbt);
nbt.setByte("state", (byte)state.ordinal());
}
@Override
protected void readNetworkData(NBTTagCompound nbt) {
super.readNetworkData(nbt);
state = RedstoneState.values()[nbt.getInteger("state")];
redstoneControl.setRedstoneState(state);
}
}