/* * This file is part of Applied Energistics 2. * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. * * Applied Energistics 2 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Applied Energistics 2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Applied Energistics 2. If not, see . */ package appeng.tile.misc; import java.io.IOException; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraftforge.common.util.ForgeDirection; import appeng.api.AEApi; import appeng.api.config.Actionable; import appeng.api.config.PowerMultiplier; import appeng.api.config.PowerUnits; import appeng.api.implementations.items.IAEItemPowerStorage; import appeng.api.implementations.tiles.ICrankable; import appeng.api.storage.data.IAEItemStack; import appeng.api.util.AECableType; import appeng.api.util.DimensionalCoord; import appeng.me.GridAccessException; import appeng.tile.TileEvent; import appeng.tile.events.TileEventType; import appeng.tile.grid.AENetworkPowerTile; import appeng.tile.inventory.AppEngInternalInventory; import appeng.tile.inventory.InvOperation; import appeng.util.Platform; import appeng.util.item.AEItemStack; public class TileCharger extends AENetworkPowerTile implements ICrankable { final int[] sides = new int[] { 0 }; final AppEngInternalInventory inv = new AppEngInternalInventory( this, 1 ); int tickTickTimer = 0; int lastUpdate = 0; boolean requiresUpdate = false; @Override public AECableType getCableConnectionType(ForgeDirection dir) { return AECableType.COVERED; } @TileEvent(TileEventType.NETWORK_READ) public boolean readFromStream_TileCharger(ByteBuf data) { try { IAEItemStack item = AEItemStack.loadItemStackFromPacket( data ); ItemStack is = item.getItemStack(); this.inv.setInventorySlotContents( 0, is ); } catch (Throwable t) { this.inv.setInventorySlotContents( 0, null ); } return false; // TESR doesn't need updates! } @TileEvent(TileEventType.NETWORK_WRITE) public void writeToStream_TileCharger(ByteBuf data) throws IOException { AEItemStack is = AEItemStack.create( this.getStackInSlot( 0 ) ); if ( is != null ) is.writeToPacket( data ); } @TileEvent(TileEventType.TICK) public void Tick_TileCharger() { if ( this.lastUpdate > 60 && this.requiresUpdate ) { this.requiresUpdate = false; this.markForUpdate(); this.lastUpdate = 0; } this.lastUpdate++; this.tickTickTimer++; if ( this.tickTickTimer < 20 ) return; this.tickTickTimer = 0; ItemStack myItem = this.getStackInSlot( 0 ); // charge from the network! if ( this.internalCurrentPower < 1499 ) { try { this.injectExternalPower( PowerUnits.AE, this.gridProxy.getEnergy().extractAEPower( Math.min( 150.0, 1500.0 - this.internalCurrentPower ), Actionable.MODULATE, PowerMultiplier.ONE ) ); this.tickTickTimer = 20; // keep ticking... } catch (GridAccessException e) { // continue! } } if ( myItem == null ) return; if ( this.internalCurrentPower > 149 && Platform.isChargeable( myItem ) ) { IAEItemPowerStorage ps = (IAEItemPowerStorage) myItem.getItem(); if ( ps.getAEMaxPower( myItem ) > ps.getAECurrentPower( myItem ) ) { double oldPower = this.internalCurrentPower; double adjustment = ps.injectAEPower( myItem, this.extractAEPower( 150.0, Actionable.MODULATE, PowerMultiplier.CONFIG ) ); this.internalCurrentPower += adjustment; if ( oldPower > this.internalCurrentPower ) this.requiresUpdate = true; this.tickTickTimer = 20; // keep ticking... } } else if ( this.internalCurrentPower > 1499 && AEApi.instance().materials().materialCertusQuartzCrystal.sameAsStack( myItem ) ) { if ( Platform.getRandomFloat() > 0.8f ) // simulate wait { this.extractAEPower( this.internalMaxPower, Actionable.MODULATE, PowerMultiplier.CONFIG );// 1500 this.setInventorySlotContents( 0, AEApi.instance().materials().materialCertusQuartzCrystalCharged.stack( myItem.stackSize ) ); } } } public TileCharger() { this.gridProxy.setValidSides( EnumSet.noneOf( ForgeDirection.class ) ); this.gridProxy.setFlags(); this.internalMaxPower = 1500; this.gridProxy.setIdlePowerUsage( 0 ); } @Override public void setOrientation(ForgeDirection inForward, ForgeDirection inUp) { super.setOrientation( inForward, inUp ); this.gridProxy.setValidSides( EnumSet.of( this.getUp(), this.getUp().getOpposite() ) ); this.setPowerSides( EnumSet.of( this.getUp(), this.getUp().getOpposite() ) ); } @Override public boolean canTurn() { return this.internalCurrentPower < this.internalMaxPower; } @Override public void applyTurn() { this.injectExternalPower( PowerUnits.AE, 150 ); ItemStack myItem = this.getStackInSlot( 0 ); if ( this.internalCurrentPower > 1499 && AEApi.instance().materials().materialCertusQuartzCrystal.sameAsStack( myItem ) ) { this.extractAEPower( this.internalMaxPower, Actionable.MODULATE, PowerMultiplier.CONFIG );// 1500 this.setInventorySlotContents( 0, AEApi.instance().materials().materialCertusQuartzCrystalCharged.stack( myItem.stackSize ) ); } } @Override public boolean canCrankAttach(ForgeDirection directionToCrank) { return this.getUp() == directionToCrank || this.getUp().getOpposite() == directionToCrank; } @Override public IInventory getInternalInventory() { return this.inv; } @Override public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) { this.markForUpdate(); } @Override public int[] getAccessibleSlotsBySide(ForgeDirection whichSide) { return this.sides; } @Override public int getInventoryStackLimit() { return 1; } @Override public boolean isItemValidForSlot(int i, ItemStack itemstack) { return Platform.isChargeable( itemstack ) || AEApi.instance().materials().materialCertusQuartzCrystal.sameAsStack( itemstack ); } @Override public boolean canExtractItem(int slotIndex, ItemStack extractedItem, int side ) { if ( Platform.isChargeable( extractedItem ) ) { IAEItemPowerStorage ips = (IAEItemPowerStorage) extractedItem.getItem(); if ( ips.getAECurrentPower( extractedItem ) >= ips.getAEMaxPower( extractedItem ) ) return true; } return AEApi.instance().materials().materialCertusQuartzCrystalCharged.sameAsStack( extractedItem ); } public void activate(EntityPlayer player) { if ( !Platform.hasPermissions( new DimensionalCoord( this ), player ) ) return; ItemStack myItem = this.getStackInSlot( 0 ); if ( myItem == null ) { ItemStack held = player.inventory.getCurrentItem(); if ( AEApi.instance().materials().materialCertusQuartzCrystal.sameAsStack( held ) || Platform.isChargeable( held ) ) { held = player.inventory.decrStackSize( player.inventory.currentItem, 1 ); this.setInventorySlotContents( 0, held ); } } else { List drops = new ArrayList(); drops.add( myItem ); this.setInventorySlotContents( 0, null ); Platform.spawnDrops( this.worldObj, this.xCoord + this.getForward().offsetX, this.yCoord + this.getForward().offsetY, this.zCoord + this.getForward().offsetZ, drops ); } } @Override public boolean requiresTESR() { return true; } }