package eiteam.esteemedinnovation.transport.entity;
import eiteam.esteemedinnovation.api.steamnet.SteamNetwork;
import eiteam.esteemedinnovation.api.tile.SteamTransporterTileEntity;
import eiteam.esteemedinnovation.api.wrench.WrenchDisplay;
import eiteam.esteemedinnovation.api.wrench.Wrenchable;
import eiteam.esteemedinnovation.commons.Config;
import eiteam.esteemedinnovation.commons.EsteemedInnovation;
import eiteam.esteemedinnovation.commons.util.MathUtility;
import eiteam.esteemedinnovation.transport.TransportationModule;
import net.minecraft.block.Block;
import net.minecraft.block.BlockCrops;
import net.minecraft.block.BlockTrapDoor;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderGameOverlayEvent.Post;
import net.minecraftforge.fluids.BlockFluidBase;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.opengl.GL11;
import java.util.List;
public class TileEntityFan extends SteamTransporterTileEntity implements Wrenchable, WrenchDisplay {
public boolean active;
public boolean powered = false;
public boolean lastSteam = false;
public int rotateTicks = 0;
public int range = 9;
private static final int STEAM_CONSUMPTION = Config.fanConsumption;
public TileEntityFan() {
addSidesToGaugeBlacklist(EnumFacing.HORIZONTALS);
}
@Override
public NBTTagCompound getUpdateTag() {
return writeToNBT(new NBTTagCompound());
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound access) {
super.writeToNBT(access);
access.setBoolean("powered", powered);
access.setShort("range", (short) range);
return access;
}
@Override
public void readFromNBT(NBTTagCompound access) {
super.readFromNBT(access);
powered = access.getBoolean("powered");
range = access.getShort("range");
}
@Override
public SPacketUpdateTileEntity getUpdatePacket() {
NBTTagCompound access = super.getUpdateTag();
access.setBoolean("active", getSteamShare() > 0 && !powered);
access.setShort("range", (short) range);
return new SPacketUpdateTileEntity(pos, 1, access);
}
@Override
public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) {
super.onDataPacket(net, pkt);
NBTTagCompound access = pkt.getNbtCompound();
active = access.getBoolean("active");
range = access.getShort("range");
markForResync();
}
/**
* Gets either a random double, or 0.5 based on the offset.
* @param offset The front offset for the direction
* @return double
*/
private double getRandomOrSlight(int offset) {
return offset == 0 ? Math.random() : 0.5D;
}
/**
* Gets the X, Y, Z positions for the smoke particles.
* @param dir The dir
* @return {double, double, double}
*/
private double[] getSmokePositions(EnumFacing dir) {
return new double[] {
pos.getX() + getRandomOrSlight(dir.getFrontOffsetX()),
pos.getY() + getRandomOrSlight(dir.getFrontOffsetY()),
pos.getZ() + getRandomOrSlight(dir.getFrontOffsetZ())
};
}
/**
* Gets the X, Y, Z speeds for the smoke particles.
* @param dir The dir
* @return {double, double, double}
*/
private double[] getSmokeSpeeds(EnumFacing dir) {
return new double[] {
dir.getFrontOffsetX() * 0.2F,
dir.getFrontOffsetY() * 0.2F,
dir.getFrontOffsetZ() * 0.2F
};
}
@Override
public boolean canUpdate(IBlockState target) {
return target.getBlock() == TransportationModule.FAN;
}
@Override
public void initialUpdate() {
super.initialUpdate();
powered = worldObj.isBlockPowered(pos);
setDistributionDirections(new EnumFacing[] { worldObj.getBlockState(pos).getValue(BlockFan.FACING).getOpposite() });
}
@Override
public void safeUpdate() {
if (lastSteam != getSteamShare() >= STEAM_CONSUMPTION) {
markForResync();
}
lastSteam = getSteamShare() > STEAM_CONSUMPTION;
if (!lastSteam && !worldObj.isRemote && active) {
markForResync();
}
if (active && worldObj.isRemote) {
rotateTicks++;
}
if (active && worldObj.isRemote || (getSteamShare() >= STEAM_CONSUMPTION && !powered)) {
if (!worldObj.isRemote) {
decrSteam(STEAM_CONSUMPTION);
}
EnumFacing dir = worldObj.getBlockState(pos).getValue(BlockFan.FACING);
double[] positions = getSmokePositions(dir);
double[] speeds = getSmokeSpeeds(dir);
worldObj.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, positions[0], positions[1], positions[2],
speeds[0], speeds[1], speeds[2]);
int blocksInFront = 0;
boolean blocked = false;
for (int i = 1; i < range; i++) {
int x = pos.getX() + dir.getFrontOffsetX() * i;
int y = pos.getY() + dir.getFrontOffsetY() * i;
int z = pos.getZ() + dir.getFrontOffsetZ() * i;
BlockPos offsetPos = new BlockPos(x, y, z);
IBlockState offsetState = worldObj.getBlockState(offsetPos);
Block offsetBlock = offsetState.getBlock();
if (!worldObj.isRemote && worldObj.rand.nextInt(20) == 0 && !blocked && offsetBlock != Blocks.AIR &&
offsetBlock.isReplaceable(worldObj, offsetPos) || offsetBlock instanceof BlockCrops) {
// We don't need to check the other FluidBlock classes because they all inherit Base.
if (offsetBlock instanceof BlockFluidBase) {
for (int v = 0; v < 5; v++) {
EsteemedInnovation.proxy.spawnBreakParticles(worldObj, x + 0.5F, y + 0.5F, z + 0.5F, offsetBlock, 0F, 0F, 0F);
}
}
worldObj.setBlockToAir(offsetPos);
}
if (!blocked && (offsetBlock.isReplaceable(worldObj, offsetPos) || worldObj.isAirBlock(offsetPos) ||
offsetBlock instanceof BlockTrapDoor || offsetState.getCollisionBoundingBox(worldObj, offsetPos) == null)) {
blocksInFront = i;
if (i != range - 1) {
worldObj.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x + getRandomOrSlight(dir.getFrontOffsetX()),
y + getRandomOrSlight(dir.getFrontOffsetY()), z + getRandomOrSlight(dir.getFrontOffsetZ()),
speeds[0], speeds[1], speeds[2]);
}
} else {
blocked = true;
}
}
List<Entity> entities = worldObj.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(pos.getX() + (dir.getFrontOffsetX() < 0 ? dir.getFrontOffsetX() * blocksInFront : 0), pos.getY() + (dir.getFrontOffsetY() < 0 ? dir.getFrontOffsetY() * blocksInFront : 0), pos.getZ() + (dir.getFrontOffsetZ() < 0 ? dir.getFrontOffsetZ() * blocksInFront : 0), pos.getX() + 1 + (dir.getFrontOffsetX() > 0 ? dir.getFrontOffsetX() * blocksInFront : 0), pos.getY() + 1 + (dir.getFrontOffsetY() > 0 ? dir.getFrontOffsetY() * blocksInFront : 0), pos.getZ() + 1 + (dir.getFrontOffsetZ() > 0 ? dir.getFrontOffsetZ() * blocksInFront : 0)));
for (Entity entity : entities) {
if (!(entity instanceof EntityPlayer) || !(((EntityPlayer) entity).capabilities.isFlying && ((EntityPlayer) entity).capabilities.isCreativeMode)) {
if (entity instanceof EntityPlayer && entity.isSneaking()) {
entity.motionX += dir.getFrontOffsetX() * 0.025F;
entity.motionY += dir.getFrontOffsetY() * 0.05F;
entity.motionZ += dir.getFrontOffsetZ() * 0.025F;
} else {
entity.motionX += dir.getFrontOffsetX() * 0.075F;
entity.motionY += dir.getFrontOffsetY() * 0.1F;
entity.motionZ += dir.getFrontOffsetZ() * 0.075F;
}
entity.fallDistance = 0.0F;
}
}
}
super.safeUpdate();
}
public void updateRedstoneState(boolean flag) {
if (flag != powered) {
powered = flag;
markForResync();
}
}
@Override
public boolean onWrench(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, IBlockState state, float hitX, float hitY, float hitZ) {
if (player.isSneaking()) {
range = MathUtility.minWithDefault(19, range + 2, 5);
markForResync(state);
} else {
int steam = getSteamShare();
getNetwork().split(this, true);
setDistributionDirections(new EnumFacing[] { world.getBlockState(pos).getValue(BlockFan.FACING).getOpposite() });
SteamNetwork.newOrJoin(this);
getNetwork().addSteam(steam);
}
return true;
}
public static void rangeDisplay(Post event, int range) {
GL11.glPushMatrix();
Minecraft mc = Minecraft.getMinecraft();
int color = mc.thePlayer.isSneaking() ? 0xC6C6C6 : 0x777777;
int x = event.getResolution().getScaledWidth() / 2 - 8;
int y = event.getResolution().getScaledHeight() / 2 - 8;
mc.fontRendererObj.drawStringWithShadow(I18n.format("esteemedinnovation.fan.range", range), x + 15, y + 13, color);
GL11.glPopMatrix();
}
@SideOnly(Side.CLIENT)
@Override
public void displayWrench(Post event) {
rangeDisplay(event, range);
}
}