package micdoodle8.mods.galacticraft.planets.asteroids.tile;
import io.netty.buffer.ByteBuf;
import micdoodle8.mods.galacticraft.api.vector.BlockVec3;
import micdoodle8.mods.galacticraft.api.vector.Vector3;
import micdoodle8.mods.galacticraft.core.Constants;
import micdoodle8.mods.galacticraft.core.GalacticraftCore;
import micdoodle8.mods.galacticraft.core.blocks.BlockMulti;
import micdoodle8.mods.galacticraft.core.blocks.BlockMulti.EnumBlockMultiType;
import micdoodle8.mods.galacticraft.core.energy.item.ItemElectricBase;
import micdoodle8.mods.galacticraft.core.energy.tile.TileBaseElectricBlock;
import micdoodle8.mods.galacticraft.core.inventory.IInventoryDefaults;
import micdoodle8.mods.galacticraft.core.tile.IMultiBlock;
import micdoodle8.mods.galacticraft.core.util.ConfigManagerCore;
import micdoodle8.mods.galacticraft.core.util.EnumColor;
import micdoodle8.mods.galacticraft.core.util.GCCoreUtil;
import micdoodle8.mods.galacticraft.planets.GalacticraftPlanets;
import micdoodle8.mods.galacticraft.planets.GuiIdsPlanets;
import micdoodle8.mods.galacticraft.planets.asteroids.blocks.AsteroidBlocks;
import micdoodle8.mods.galacticraft.planets.asteroids.blocks.BlockTelepadFake;
import micdoodle8.mods.galacticraft.planets.asteroids.dimension.ShortRangeTelepadHandler;
import micdoodle8.mods.galacticraft.planets.asteroids.network.PacketSimpleAsteroids;
import micdoodle8.mods.miccore.Annotations.NetworkedField;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.*;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
public class TileEntityShortRangeTelepad extends TileBaseElectricBlock implements IMultiBlock, IInventoryDefaults, ISidedInventory
{
public static enum EnumTelepadSearchResult
{
VALID,
NOT_FOUND,
TOO_FAR,
WRONG_DIM
}
public static final int MAX_TELEPORT_TIME = 150;
public static final int TELEPORTER_RANGE = 256;
public static final int ENERGY_USE_ON_TELEPORT = 2500;
@NetworkedField(targetSide = Side.CLIENT)
public int address = -1;
@NetworkedField(targetSide = Side.CLIENT)
public boolean addressValid = false;
@NetworkedField(targetSide = Side.CLIENT)
public int targetAddress = -1;
public EnumTelepadSearchResult targetAddressResult = EnumTelepadSearchResult.NOT_FOUND;
@NetworkedField(targetSide = Side.CLIENT)
public int teleportTime = 0;
@NetworkedField(targetSide = Side.CLIENT)
public String owner = "";
private ItemStack[] containingItems = new ItemStack[1];
@NetworkedField(targetSide = Side.CLIENT)
public boolean teleporting;
private AxisAlignedBB renderAABB;
public TileEntityShortRangeTelepad()
{
super();
this.storage.setMaxExtract(ConfigManagerCore.hardMode ? 115 : 50);
}
public int canTeleportHere()
{
if (this.worldObj.isRemote)
{
return -1;
}
this.setAddress(this.address);
this.setTargetAddress(this.targetAddress);
if (!this.addressValid)
{
return 1;
}
if (this.getEnergyStoredGC() < ENERGY_USE_ON_TELEPORT)
{
return 2;
}
return 0; // GOOD
}
@Override
public void update()
{
if (this.ticks % 40 == 0 && !worldObj.isRemote)
{
this.setAddress(this.address);
this.setTargetAddress(this.targetAddress);
}
if (!this.worldObj.isRemote)
{
if (this.targetAddressResult == EnumTelepadSearchResult.VALID && (this.ticks % 5 == 0 || teleporting))
{
List containedEntities = worldObj.getEntitiesWithinAABB(EntityLivingBase.class, AxisAlignedBB.fromBounds(this.getPos().getX(), this.getPos().getY(), this.getPos().getZ(),
this.getPos().getX() + 1, this.getPos().getY() + 2, this.getPos().getZ() + 1));
if (containedEntities.size() > 0 && this.getEnergyStoredGC() >= ENERGY_USE_ON_TELEPORT)
{
ShortRangeTelepadHandler.TelepadEntry entry = ShortRangeTelepadHandler.getLocationFromAddress(this.targetAddress);
if (entry != null)
{
teleporting = true;
}
}
else
{
teleporting = false;
}
}
if (this.teleporting)
{
this.teleportTime++;
if (teleportTime >= MAX_TELEPORT_TIME)
{
ShortRangeTelepadHandler.TelepadEntry entry = ShortRangeTelepadHandler.getLocationFromAddress(this.targetAddress);
BlockVec3 finalPos = (entry == null) ? null : entry.position;
if (finalPos != null)
{
TileEntity tileAt = finalPos.getTileEntity(this.worldObj);
List<EntityLivingBase> containedEntities = worldObj.getEntitiesWithinAABB(EntityLivingBase.class, AxisAlignedBB.fromBounds(this.getPos().getX(), this.getPos().getY(), this.getPos().getZ(),
this.getPos().getX() + 1, this.getPos().getY() + 2, this.getPos().getZ() + 1));
if (tileAt != null && tileAt instanceof TileEntityShortRangeTelepad)
{
TileEntityShortRangeTelepad destTelepad = (TileEntityShortRangeTelepad) tileAt;
int teleportResult = destTelepad.canTeleportHere();
if (teleportResult == 0)
{
for (EntityLivingBase e : containedEntities)
{
e.setPosition(finalPos.x + 0.5F, finalPos.y + 1.0F, finalPos.z + 0.5F);
this.worldObj.updateEntityWithOptionalForce(e, true);
if (e instanceof EntityPlayerMP)
{
((EntityPlayerMP) e).playerNetServerHandler.setPlayerLocation(finalPos.x, finalPos.y, finalPos.z, e.rotationYaw, e.rotationPitch);
}
GalacticraftCore.packetPipeline.sendToDimension(new PacketSimpleAsteroids(PacketSimpleAsteroids.EnumSimplePacketAsteroids.C_TELEPAD_SEND, GCCoreUtil.getDimensionID(this.worldObj), new Object[] { finalPos, e.getEntityId() }), GCCoreUtil.getDimensionID(this.worldObj));
}
if (containedEntities.size() > 0)
{
this.storage.setEnergyStored(this.storage.getEnergyStoredGC() - ENERGY_USE_ON_TELEPORT);
destTelepad.storage.setEnergyStored(this.storage.getEnergyStoredGC() - ENERGY_USE_ON_TELEPORT);
}
}
else
{
switch (teleportResult)
{
case -1:
for (EntityLivingBase e : containedEntities)
{
if (e instanceof EntityPlayer)
{
((EntityPlayer) e).addChatComponentMessage(new ChatComponentText("Cannot Send client-side")); // No need for translation, since this should never happen
}
}
break;
case 1:
for (EntityLivingBase e : containedEntities)
{
if (e instanceof EntityPlayer)
{
((EntityPlayer) e).addChatComponentMessage(new ChatComponentText("Target address invalid")); // No need for translation, since this should never happen
}
}
break;
case 2:
for (EntityLivingBase e : containedEntities)
{
if (e instanceof EntityPlayer)
{
((EntityPlayer) e).addChatComponentMessage(new ChatComponentText(GCCoreUtil.translate("gui.message.target_no_energy.name")));
}
}
break;
}
}
}
}
this.teleportTime = 0;
this.teleporting = false;
}
}
else
{
this.teleportTime = Math.max(--this.teleportTime, 0);
}
}
super.update();
}
@Override
public void readFromNBT(NBTTagCompound nbt)
{
super.readFromNBT(nbt);
NBTTagList var2 = nbt.getTagList("Items", 10);
this.containingItems = new ItemStack[this.getSizeInventory()];
for (int var3 = 0; var3 < var2.tagCount(); ++var3)
{
NBTTagCompound var4 = var2.getCompoundTagAt(var3);
int var5 = var4.getByte("Slot") & 255;
if (var5 < this.containingItems.length)
{
this.containingItems[var5] = ItemStack.loadItemStackFromNBT(var4);
}
}
this.setAddress(nbt.getInteger("Address"));
this.targetAddress = nbt.getInteger("TargetAddress");
this.owner = nbt.getString("Owner");
}
@Override
public void writeToNBT(NBTTagCompound nbt)
{
super.writeToNBT(nbt);
NBTTagList var2 = new NBTTagList();
for (int var3 = 0; var3 < this.containingItems.length; ++var3)
{
if (this.containingItems[var3] != null)
{
NBTTagCompound var4 = new NBTTagCompound();
var4.setByte("Slot", (byte) var3);
this.containingItems[var3].writeToNBT(var4);
var2.appendTag(var4);
}
}
nbt.setTag("Items", var2);
nbt.setInteger("TargetAddress", this.targetAddress);
nbt.setInteger("Address", this.address);
nbt.setString("Owner", this.owner);
}
@Override
public void addExtraNetworkedData(List<Object> networkedList)
{
super.addExtraNetworkedData(networkedList);
networkedList.add(targetAddressResult.ordinal());
}
@Override
public void readExtraNetworkedData(ByteBuf dataStream)
{
super.readExtraNetworkedData(dataStream);
targetAddressResult = EnumTelepadSearchResult.values()[dataStream.readInt()];
}
@Override
public double getPacketRange()
{
return 24.0D;
}
@Override
public boolean onActivated(EntityPlayer entityPlayer)
{
entityPlayer.openGui(GalacticraftPlanets.instance, GuiIdsPlanets.MACHINE_ASTEROIDS, this.worldObj, this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
return true;
}
@Override
public void onCreate(World world, BlockPos placedPosition)
{
List<BlockPos> positions = new LinkedList();
this.getPositions(placedPosition, positions);
for (BlockPos vecToAdd : positions)
((BlockTelepadFake) AsteroidBlocks.fakeTelepad).makeFakeBlock(world, vecToAdd, placedPosition, AsteroidBlocks.fakeTelepad.getDefaultState().withProperty(BlockTelepadFake.TOP, vecToAdd.getY() == placedPosition.getY() + 2));
}
@Override
public BlockMulti.EnumBlockMultiType getMultiType()
{
//Not actually used - maybe this shouldn't be an IMultiBlock at all?
return EnumBlockMultiType.MINER_BASE;
}
@Override
public void getPositions(BlockPos placedPosition, List<BlockPos> positions)
{
int buildHeight = this.worldObj.getHeight() - 1;
for (int y = 0; y < 3; y += 2)
{
if (placedPosition.getY() + y > buildHeight)
{
return;
}
for (int x = -1; x <= 1; x++)
{
for (int z = -1; z <= 1; z++)
{
if (x == 0 && y == 0 && z == 0) continue;
positions.add(placedPosition.add(x, y, z));
}
}
}
}
@Override
public void onDestroy(TileEntity callingBlock)
{
final BlockPos thisBlock = getPos();
List<BlockPos> positions = new LinkedList();
this.getPositions(thisBlock, positions);
for (BlockPos pos : positions)
{
IBlockState stateAt = this.worldObj.getBlockState(pos);
if (stateAt.getBlock() == AsteroidBlocks.fakeTelepad)
{
this.worldObj.destroyBlock(pos, false);
}
}
this.worldObj.destroyBlock(thisBlock, true);
}
@Override
@SideOnly(Side.CLIENT)
public AxisAlignedBB getRenderBoundingBox()
{
if (this.renderAABB == null)
{
this.renderAABB = new AxisAlignedBB(getPos().getX() - 1, getPos().getY(), getPos().getZ() - 1, getPos().getX() + 2, getPos().getY() + 4, getPos().getZ() + 2);
}
return this.renderAABB;
}
@Override
@SideOnly(Side.CLIENT)
public double getMaxRenderDistanceSquared()
{
return Constants.RENDERDISTANCE_MEDIUM;
}
@Override
public String getName()
{
return GCCoreUtil.translate("container.short_range_telepad.name");
}
@Override
public int[] getSlotsForFace(EnumFacing side)
{
return new int[] { 0 };
}
@Override
public boolean hasCustomName()
{
return true;
}
@Override
public IChatComponent getDisplayName()
{
return (this.hasCustomName() ? new ChatComponentText(this.getName()) : new ChatComponentTranslation(this.getName(), new Object[0]));
}
@Override
public int getInventoryStackLimit()
{
return 64;
}
@Override
public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
{
return this.worldObj.getTileEntity(getPos()) == this && par1EntityPlayer.getDistanceSq(this.getPos().getX() + 0.5D, this.getPos().getY() + 0.5D, this.getPos().getZ() + 0.5D) <= 64.0D;
}
@Override
public boolean isItemValidForSlot(int slotID, ItemStack itemStack)
{
return slotID == 0 && ItemElectricBase.isElectricItem(itemStack.getItem());
}
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction)
{
return index == 0;
}
@Override
public boolean canInsertItem(int index, ItemStack itemStackIn, EnumFacing direction)
{
return this.isItemValidForSlot(index, itemStackIn);
}
@Override
public EnumSet<EnumFacing> getElectricalOutputDirections()
{
return EnumSet.noneOf(EnumFacing.class);
}
@Override
public boolean shouldUseEnergy()
{
return !this.getDisabled(0);
}
@Override
public EnumFacing getElectricInputDirection()
{
return EnumFacing.getFront((this.getBlockMetadata() & 3) + 2);
}
@Override
public ItemStack getBatteryInSlot()
{
return this.getStackInSlot(0);
}
@Override
public void setDisabled(int index, boolean disabled)
{
if (this.disableCooldown == 0)
{
switch (index)
{
case 0:
this.disabled = disabled;
this.disableCooldown = 10;
break;
default:
break;
}
}
}
@Override
public boolean getDisabled(int index)
{
switch (index)
{
case 0:
return this.disabled;
default:
break;
}
return true;
}
public void setAddress(int address)
{
if (this.worldObj != null && address != this.address)
{
ShortRangeTelepadHandler.removeShortRangeTeleporter(this);
}
this.address = address;
if (this.address >= 0)
{
ShortRangeTelepadHandler.TelepadEntry entry = ShortRangeTelepadHandler.getLocationFromAddress(this.address);
this.addressValid = entry == null || (this.worldObj != null && (entry.dimensionID == GCCoreUtil.getDimensionID(this.worldObj) && entry.position.x == this.getPos().getX() && entry.position.y == this.getPos().getY() && entry.position.z == this.getPos().getZ()));
}
else
{
this.addressValid = false;
}
if (worldObj != null && !worldObj.isRemote)
{
ShortRangeTelepadHandler.addShortRangeTelepad(this);
}
}
public boolean updateTarget()
{
if (this.targetAddress >= 0 && !this.worldObj.isRemote)
{
this.targetAddressResult = EnumTelepadSearchResult.NOT_FOUND;
ShortRangeTelepadHandler.TelepadEntry addressResult = ShortRangeTelepadHandler.getLocationFromAddress(this.targetAddress);
if (addressResult != null)
{
if (GCCoreUtil.getDimensionID(this.worldObj) == addressResult.dimensionID)
{
double distance = this.getDistanceSq(addressResult.position.x + 0.5F, addressResult.position.y + 0.5F, addressResult.position.z + 0.5F);
if (distance < Math.pow(TELEPORTER_RANGE * TELEPORTER_RANGE, 2))
{
this.targetAddressResult = EnumTelepadSearchResult.VALID;
return true;
}
else
{
this.targetAddressResult = EnumTelepadSearchResult.TOO_FAR;
return false;
}
}
else
{
this.targetAddressResult = EnumTelepadSearchResult.WRONG_DIM;
return false;
}
}
else
{
this.targetAddressResult = EnumTelepadSearchResult.NOT_FOUND;
return false;
}
}
else
{
this.targetAddressResult = EnumTelepadSearchResult.NOT_FOUND;
return false;
}
}
public void setTargetAddress(int address)
{
this.targetAddress = address;
this.updateTarget();
}
@Override
public int getSizeInventory()
{
return this.containingItems.length;
}
@Override
public ItemStack getStackInSlot(int par1)
{
return this.containingItems[par1];
}
@Override
public ItemStack decrStackSize(int par1, int par2)
{
if (this.containingItems[par1] != null)
{
ItemStack var3;
if (this.containingItems[par1].stackSize <= par2)
{
var3 = this.containingItems[par1];
this.containingItems[par1] = null;
return var3;
}
else
{
var3 = this.containingItems[par1].splitStack(par2);
if (this.containingItems[par1].stackSize == 0)
{
this.containingItems[par1] = null;
}
return var3;
}
}
else
{
return null;
}
}
@Override
public ItemStack removeStackFromSlot(int par1)
{
if (this.containingItems[par1] != null)
{
ItemStack var2 = this.containingItems[par1];
this.containingItems[par1] = null;
return var2;
}
else
{
return null;
}
}
@Override
public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
{
this.containingItems[par1] = par2ItemStack;
if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit())
{
par2ItemStack.stackSize = this.getInventoryStackLimit();
}
}
public void setOwner(String owner)
{
this.owner = owner;
}
public String getOwner()
{
return this.owner;
}
@SideOnly(Side.CLIENT)
public String getReceivingStatus()
{
if (!this.addressValid)
{
return EnumColor.RED + GCCoreUtil.translate("gui.message.invalid_address.name");
}
if (this.getEnergyStoredGC() <= 0.0F)
{
return EnumColor.RED + GCCoreUtil.translate("gui.message.no_energy.name");
}
if (this.getEnergyStoredGC() <= ENERGY_USE_ON_TELEPORT)
{
return EnumColor.RED + GCCoreUtil.translate("gui.message.not_enough_energy.name");
}
if (this.getDisabled(0))
{
return EnumColor.ORANGE + GCCoreUtil.translate("gui.status.disabled.name");
}
return EnumColor.BRIGHT_GREEN + GCCoreUtil.translate("gui.message.receiving_active.name");
}
@SideOnly(Side.CLIENT)
public String getSendingStatus()
{
if (!this.addressValid)
{
return EnumColor.RED + GCCoreUtil.translate("gui.message.invalid_target_address.name");
}
if (this.targetAddressResult == TileEntityShortRangeTelepad.EnumTelepadSearchResult.TOO_FAR)
{
return EnumColor.RED + GCCoreUtil.translateWithFormat("gui.message.telepad_too_far.name", TELEPORTER_RANGE);
}
if (this.targetAddressResult == TileEntityShortRangeTelepad.EnumTelepadSearchResult.WRONG_DIM)
{
return EnumColor.RED + GCCoreUtil.translate("gui.message.telepad_wrong_dim.name");
}
if (this.targetAddressResult == TileEntityShortRangeTelepad.EnumTelepadSearchResult.NOT_FOUND)
{
return EnumColor.RED + GCCoreUtil.translate("gui.message.telepad_not_found.name");
}
if (this.getEnergyStoredGC() <= 0.0F)
{
return EnumColor.RED + GCCoreUtil.translate("gui.message.no_energy.name");
}
if (this.getEnergyStoredGC() <= ENERGY_USE_ON_TELEPORT)
{
return EnumColor.RED + GCCoreUtil.translate("gui.message.not_enough_energy.name");
}
if (this.getDisabled(0))
{
return EnumColor.ORANGE + GCCoreUtil.translate("gui.status.disabled.name");
}
return EnumColor.BRIGHT_GREEN + GCCoreUtil.translate("gui.message.sending_active.name");
}
@SideOnly(Side.CLIENT)
public Vector3 getParticleColor(Random rand, boolean sending)
{
float teleportTimeScaled = Math.min(1.0F, this.teleportTime / (float) TileEntityShortRangeTelepad.MAX_TELEPORT_TIME);
float f;
f = rand.nextFloat() * 0.6F + 0.4F;
if (sending && this.targetAddressResult != EnumTelepadSearchResult.VALID)
{
return new Vector3(f, f * 0.3F, f * 0.3F);
}
if (!sending && !this.addressValid)
{
return new Vector3(f, f * 0.3F, f * 0.3F);
}
if (this.getEnergyStoredGC() < ENERGY_USE_ON_TELEPORT)
{
return new Vector3(f, f * 0.6F, f * 0.3F);
}
float r = f * 0.3F;
float g = f * (0.3F + (teleportTimeScaled * 0.7F));
float b = f * (1.0F - (teleportTimeScaled * 0.7F));
return new Vector3(r, g, b);
}
@Override
public EnumFacing getFront()
{
return EnumFacing.NORTH;
}
}