package micdoodle8.mods.galacticraft.core.tile; import micdoodle8.mods.galacticraft.api.tile.IDisableableMachine; import micdoodle8.mods.galacticraft.api.transmission.NetworkType; import micdoodle8.mods.galacticraft.api.transmission.tile.IConnector; import micdoodle8.mods.galacticraft.api.vector.BlockVec3; import micdoodle8.mods.galacticraft.api.world.IGalacticraftWorldProvider; import micdoodle8.mods.galacticraft.api.world.ISolarLevel; import micdoodle8.mods.galacticraft.core.Constants; import micdoodle8.mods.galacticraft.core.GCBlocks; import micdoodle8.mods.galacticraft.core.blocks.BlockMulti; import micdoodle8.mods.galacticraft.core.blocks.BlockMulti.EnumBlockMultiType; import micdoodle8.mods.galacticraft.core.blocks.BlockSolar; import micdoodle8.mods.galacticraft.core.dimension.WorldProviderSpaceStation; import micdoodle8.mods.galacticraft.core.energy.item.ItemElectricBase; import micdoodle8.mods.galacticraft.core.energy.tile.TileBaseUniversalElectricalSource; import micdoodle8.mods.galacticraft.core.inventory.IInventoryDefaults; import micdoodle8.mods.galacticraft.core.util.GCCoreUtil; import micdoodle8.mods.galacticraft.planets.venus.dimension.WorldProviderVenus; import micdoodle8.mods.miccore.Annotations.NetworkedField; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; 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.client.FMLClientHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import java.util.ArrayList; import java.util.EnumSet; import java.util.LinkedList; import java.util.List; public class TileEntitySolar extends TileBaseUniversalElectricalSource implements IMultiBlock, IDisableableMachine, IInventoryDefaults, ISidedInventory, IConnector { @NetworkedField(targetSide = Side.CLIENT) public int solarStrength = 0; public float targetAngle; public float currentAngle; @NetworkedField(targetSide = Side.CLIENT) public boolean disabled = false; @NetworkedField(targetSide = Side.CLIENT) public int disableCooldown = 0; private ItemStack[] containingItems = new ItemStack[1]; public static final int MAX_GENERATE_WATTS = 200; @NetworkedField(targetSide = Side.CLIENT) public int generateWatts = 0; private boolean initialised = false; private boolean initialisedMulti = false; private AxisAlignedBB renderAABB; public TileEntitySolar() { this(1); } /* * @param tier: 1 = Basic Solar 2 = Advanced Solar */ public TileEntitySolar(int tier) { this.storage.setMaxExtract(TileEntitySolar.MAX_GENERATE_WATTS); this.storage.setMaxReceive(TileEntitySolar.MAX_GENERATE_WATTS); if (tier == 2) { this.storage.setCapacity(30000); } this.setTierGC(tier); this.initialised = true; } @Override public void update() { if (!this.initialised) { int metadata = this.getBlockMetadata(); if (metadata >= BlockSolar.ADVANCED_METADATA) { this.storage.setCapacity(30000); this.setTierGC(2); } this.initialised = true; } if (!this.initialisedMulti) { this.initialisedMulti = this.initialiseMultiTiles(this.getPos(), this.worldObj); } if (!this.worldObj.isRemote) { this.receiveEnergyGC(null, this.generateWatts, false); } super.update(); if (!this.worldObj.isRemote) { this.recharge(this.containingItems[0]); if (this.disableCooldown > 0) { this.disableCooldown--; } if (!this.getDisabled(0) && this.ticks % 20 == 0) { this.solarStrength = 0; if (this.worldObj.isDaytime() && (this.worldObj.provider instanceof IGalacticraftWorldProvider || !this.worldObj.isRaining() && !this.worldObj.isThundering())) { double distance = 100.0D; double sinA = -Math.sin((this.currentAngle - 77.5D) * Constants.RADIANS_TO_DEGREES_D); double cosA = Math.abs(Math.cos((this.currentAngle - 77.5D) * Constants.RADIANS_TO_DEGREES_D)); for (int x = -1; x <= 1; x++) { for (int z = -1; z <= 1; z++) { if (this.tierGC == 1) { if (this.worldObj.canBlockSeeSky(this.getPos().add(x, 2, z))) { boolean valid = true; for (int y = this.getPos().getY() + 3; y < 256; y++) { Block block = this.worldObj.getBlockState(new BlockPos(this.getPos().getX() + x, y, this.getPos().getZ() + z)).getBlock(); if (block.isOpaqueCube()) { valid = false; break; } } if (valid) { this.solarStrength++; } } } else { boolean valid = true; BlockVec3 blockVec = new BlockVec3(this).translate(x, 3, z); for (double d = 0.0D; d < distance; d++) { BlockVec3 blockAt = blockVec.clone().translate((int) (d * sinA), (int) (d * cosA), 0); Block block = blockAt.getBlock(this.worldObj); if (block.isOpaqueCube()) { valid = false; break; } } if (valid) { this.solarStrength++; } } } } } } } float angle = this.worldObj.getCelestialAngle(1.0F) - 0.7845194F < 0 ? 1.0F - 0.7845194F : -0.7845194F; float celestialAngle = (this.worldObj.getCelestialAngle(1.0F) + angle) * 360.0F; if (!(this.worldObj.provider instanceof WorldProviderSpaceStation)) celestialAngle += 12.5F; if (this.worldObj.provider instanceof WorldProviderVenus) celestialAngle = 180F - celestialAngle; celestialAngle %= 360; boolean isDaytime = this.worldObj.isDaytime() && (celestialAngle < 180.5F || celestialAngle > 359.5F) || this.worldObj.provider instanceof WorldProviderSpaceStation; if (this.tierGC == 1) { if (!isDaytime || this.worldObj.isRaining() || this.worldObj.isThundering()) { this.targetAngle = 77.5F + 180.0F; } else { this.targetAngle = 77.5F; } } else { if (!isDaytime || this.worldObj.isRaining() || this.worldObj.isThundering()) { this.targetAngle = 77.5F + 180F; } else if (celestialAngle > 27.5F && celestialAngle < 152.5F) { float difference = this.targetAngle - celestialAngle + 12.5F; this.targetAngle -= difference / 20.0F; } else if (celestialAngle <= 27.5F || celestialAngle > 270F) { this.targetAngle = 15F; } else if (celestialAngle >= 152.5F) { this.targetAngle = 140F; } } float difference = this.targetAngle - this.currentAngle; this.currentAngle += difference / 20.0F; if (!this.worldObj.isRemote) { int generated = this.getGenerate(); if (generated > 0) { this.generateWatts = Math.min(Math.max(generated, 0), TileEntitySolar.MAX_GENERATE_WATTS); } else { this.generateWatts = 0; } } this.produce(); } protected boolean initialiseMultiTiles(BlockPos pos, World world) { //Client can create its own fake blocks and tiles - no need for networking in 1.8+ if (world.isRemote) this.onCreate(world, pos); List<BlockPos> positions = new ArrayList(); this.getPositions(pos, positions); boolean result = true; for (BlockPos vecToAdd : positions) { TileEntity tile = world.getTileEntity(vecToAdd); if (tile instanceof TileEntityMulti) { ((TileEntityMulti) tile).mainBlockPosition = pos; } else { result = false; } } return result; } public int getGenerate() { if (this.getDisabled(0)) { return 0; } float angle = this.worldObj.getCelestialAngle(1.0F) - 0.784690560F < 0 ? 1.0F - 0.784690560F : -0.784690560F; float celestialAngle = (this.worldObj.getCelestialAngle(1.0F) + angle) * 360.0F; celestialAngle %= 360; float difference = (180.0F - Math.abs(this.currentAngle % 180 - celestialAngle)) / 180.0F; return MathHelper.floor_float(0.01F * difference * difference * (this.solarStrength * (Math.abs(difference) * 500.0F)) * this.getSolarBoost()); } public float getSolarBoost() { return (float) (this.worldObj.provider instanceof ISolarLevel ? ((ISolarLevel) this.worldObj.provider).getSolarEnergyMultiplier() : 1.0F); } @Override public boolean onActivated(EntityPlayer entityPlayer) { return this.getBlockType().onBlockActivated(this.worldObj, this.getPos(), this.worldObj.getBlockState(getPos()), entityPlayer, EnumFacing.DOWN, this.getPos().getX(), this.getPos().getY(), this.getPos().getZ()); } // @Override // public boolean canUpdate() // { // return true; // } @Override public void onCreate(World world, BlockPos placedPosition) { List<BlockPos> positions = new LinkedList(); this.getPositions(placedPosition, positions); if (positions.size() > 0) { ((BlockMulti) GCBlocks.fakeBlock).makeFakeBlock(world, positions.get(0), placedPosition, EnumBlockMultiType.SOLAR_PANEL_0.getMeta()); positions.remove(0); } ((BlockMulti) GCBlocks.fakeBlock).makeFakeBlock(world, positions, placedPosition, this.getMultiType()); } @Override public BlockMulti.EnumBlockMultiType getMultiType() { return (this.getTierGC() == 1) ? EnumBlockMultiType.SOLAR_PANEL_1 : EnumBlockMultiType.SOLAR_PANEL_0; } @Override public void getPositions(BlockPos placedPosition, List<BlockPos> positions) { int buildHeight = this.worldObj.getHeight() - 1; int y = placedPosition.getY() + 1; if (y > buildHeight) { return; } positions.add(new BlockPos(placedPosition.getX(), y, placedPosition.getZ())); y++; if (y > buildHeight) { return; } for (int x = -1; x < 2; x++) { for (int z = -1; z < 2; z++) { positions.add(new BlockPos(placedPosition.getX() + x, y, placedPosition.getZ() + z)); } } } @Override public void onDestroy(TileEntity callingBlock) { final BlockPos thisBlock = getPos(); List<BlockPos> positions = new ArrayList(); this.getPositions(thisBlock, positions); for (BlockPos pos : positions) { IBlockState stateAt = this.worldObj.getBlockState(pos); if (stateAt.getBlock() == GCBlocks.fakeBlock) { EnumBlockMultiType type = (EnumBlockMultiType) stateAt.getValue(BlockMulti.MULTI_TYPE); if ((type == EnumBlockMultiType.SOLAR_PANEL_0 || type == EnumBlockMultiType.SOLAR_PANEL_1)) { if (this.worldObj.isRemote && this.worldObj.rand.nextDouble() < 0.1D) { FMLClientHandler.instance().getClient().effectRenderer.addBlockDestroyEffects(pos, GCBlocks.solarPanel.getDefaultState()); } this.worldObj.setBlockToAir(pos); } } } this.worldObj.destroyBlock(getPos(), true); } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); this.storage.setCapacity(nbt.getFloat("maxEnergy")); this.currentAngle = nbt.getFloat("currentAngle"); this.targetAngle = nbt.getFloat("targetAngle"); this.setDisabled(0, nbt.getBoolean("disabled")); this.disableCooldown = nbt.getInteger("disabledCooldown"); final NBTTagList var2 = nbt.getTagList("Items", 10); this.containingItems = new ItemStack[this.getSizeInventory()]; for (int var3 = 0; var3 < var2.tagCount(); ++var3) { final NBTTagCompound var4 = var2.getCompoundTagAt(var3); final int var5 = var4.getByte("Slot") & 255; if (var5 < this.containingItems.length) { this.containingItems[var5] = ItemStack.loadItemStackFromNBT(var4); } } this.initialised = false; } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); nbt.setFloat("maxEnergy", this.getMaxEnergyStoredGC()); nbt.setFloat("currentAngle", this.currentAngle); nbt.setFloat("targetAngle", this.targetAngle); nbt.setInteger("disabledCooldown", this.disableCooldown); nbt.setBoolean("disabled", this.getDisabled(0)); final NBTTagList list = new NBTTagList(); for (int var3 = 0; var3 < this.containingItems.length; ++var3) { if (this.containingItems[var3] != null) { final NBTTagCompound var4 = new NBTTagCompound(); var4.setByte("Slot", (byte) var3); this.containingItems[var3].writeToNBT(var4); list.appendTag(var4); } } nbt.setTag("Items", list); } /*@Override public float getRequest(EnumFacing direction) { return 0; } */ @Override public EnumSet<EnumFacing> getElectricalInputDirections() { return EnumSet.noneOf(EnumFacing.class); } public EnumFacing getFront() { return ((EnumFacing) this.worldObj.getBlockState(getPos()).getValue(BlockSolar.FACING)); } @Override public EnumSet<EnumFacing> getElectricalOutputDirections() { return EnumSet.of(getFront()); } @Override public EnumFacing getElectricOutputDirection() { return getFront(); } @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_LONG; } @Override public boolean hasCustomName() { return true; } @Override public String getName() { return GCCoreUtil.translate(this.tierGC == 1 ? "container.solarbasic.name" : "container.solaradvanced.name"); } @Override public void setDisabled(int index, boolean disabled) { if (this.disableCooldown == 0) { this.disabled = disabled; this.disableCooldown = 20; } } @Override public boolean getDisabled(int index) { return this.disabled; } public int getScaledElecticalLevel(int i) { return (int) Math.floor(this.getEnergyStoredGC() * i / this.getMaxEnergyStoredGC()); } @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) { final 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(); } } @Override public int getInventoryStackLimit() { return 64; } @Override public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) { return this.worldObj.getTileEntity(this.getPos()) == this && par1EntityPlayer.getDistanceSq(this.getPos().getX() + 0.5D, this.getPos().getY() + 0.5D, this.getPos().getZ() + 0.5D) <= 64.0D; } @Override public int[] getSlotsForFace(EnumFacing side) { return new int[] { 0 }; } @Override public boolean canInsertItem(int slotID, ItemStack itemstack, EnumFacing side) { return this.isItemValidForSlot(slotID, itemstack); } @Override public boolean canExtractItem(int slotID, ItemStack itemstack, EnumFacing side) { return slotID == 0; } @Override public boolean isItemValidForSlot(int slotID, ItemStack itemstack) { return slotID == 0 && ItemElectricBase.isElectricItem(itemstack.getItem()); } @Override public boolean canConnect(EnumFacing direction, NetworkType type) { if (direction == null || type != NetworkType.POWER) { return false; } return direction == this.getElectricOutputDirection(); } }