92331b4d2e
The export bus will now no longer speed up, if more than 1 of the last crafting requests failed and slow down, if more then 5 failed. Some code cleanup and moved the custom iterator into the helper package as it is clearly related to the craftingtracker and not the export bus.
406 lines
12 KiB
Java
406 lines
12 KiB
Java
/*
|
|
* 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 <http://www.gnu.org/licenses/lgpl>.
|
|
*/
|
|
|
|
package appeng.parts.automation;
|
|
|
|
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.collect.ImmutableSet;
|
|
|
|
import net.minecraft.client.renderer.RenderBlocks;
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.util.Vec3;
|
|
|
|
import cpw.mods.fml.relauncher.Side;
|
|
import cpw.mods.fml.relauncher.SideOnly;
|
|
|
|
import appeng.api.config.Actionable;
|
|
import appeng.api.config.FuzzyMode;
|
|
import appeng.api.config.PowerMultiplier;
|
|
import appeng.api.config.RedstoneMode;
|
|
import appeng.api.config.SchedulingMode;
|
|
import appeng.api.config.Settings;
|
|
import appeng.api.config.Upgrades;
|
|
import appeng.api.config.YesNo;
|
|
import appeng.api.networking.IGridNode;
|
|
import appeng.api.networking.crafting.ICraftingGrid;
|
|
import appeng.api.networking.crafting.ICraftingLink;
|
|
import appeng.api.networking.crafting.ICraftingRequester;
|
|
import appeng.api.networking.energy.IEnergyGrid;
|
|
import appeng.api.networking.security.BaseActionSource;
|
|
import appeng.api.networking.security.MachineSource;
|
|
import appeng.api.networking.ticking.TickRateModulation;
|
|
import appeng.api.networking.ticking.TickingRequest;
|
|
import appeng.api.parts.IPartCollisionHelper;
|
|
import appeng.api.parts.IPartRenderHelper;
|
|
import appeng.api.storage.IMEInventory;
|
|
import appeng.api.storage.IMEMonitor;
|
|
import appeng.api.storage.data.IAEItemStack;
|
|
import appeng.client.texture.CableBusTextures;
|
|
import appeng.core.AELog;
|
|
import appeng.core.settings.TickRates;
|
|
import appeng.core.sync.GuiBridge;
|
|
import appeng.helpers.MultiCraftingTracker;
|
|
import appeng.helpers.Reflected;
|
|
import appeng.me.GridAccessException;
|
|
import appeng.util.InventoryAdaptor;
|
|
import appeng.util.Platform;
|
|
import appeng.util.item.AEItemStack;
|
|
|
|
|
|
public class PartExportBus extends PartSharedItemBus implements ICraftingRequester
|
|
{
|
|
private final MultiCraftingTracker craftingTracker = new MultiCraftingTracker( this, 9 );
|
|
private final BaseActionSource mySrc;
|
|
private long itemToSend = 1;
|
|
private boolean didSomething = false;
|
|
private int nextSlot = 0;
|
|
|
|
@Reflected
|
|
public PartExportBus( ItemStack is )
|
|
{
|
|
super( is );
|
|
|
|
this.getConfigManager().registerSetting( Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE );
|
|
this.getConfigManager().registerSetting( Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL );
|
|
this.getConfigManager().registerSetting( Settings.CRAFT_ONLY, YesNo.NO );
|
|
this.getConfigManager().registerSetting( Settings.SCHEDULING_MODE, SchedulingMode.DEFAULT );
|
|
this.mySrc = new MachineSource( this );
|
|
}
|
|
|
|
@Override
|
|
public void readFromNBT( NBTTagCompound extra )
|
|
{
|
|
super.readFromNBT( extra );
|
|
this.craftingTracker.readFromNBT( extra );
|
|
this.nextSlot = extra.getInteger( "nextSlot" );
|
|
}
|
|
|
|
@Override
|
|
public void writeToNBT( NBTTagCompound extra )
|
|
{
|
|
super.writeToNBT( extra );
|
|
this.craftingTracker.writeToNBT( extra );
|
|
extra.setInteger( "nextSlot", this.nextSlot );
|
|
}
|
|
|
|
@Override
|
|
protected TickRateModulation doBusWork()
|
|
{
|
|
if( !this.proxy.isActive() || !this.canDoBusWork() )
|
|
{
|
|
return TickRateModulation.IDLE;
|
|
}
|
|
|
|
this.itemToSend = this.calculateItemsToSend();
|
|
this.didSomething = false;
|
|
|
|
try
|
|
{
|
|
final InventoryAdaptor destination = this.getHandler();
|
|
final IMEMonitor<IAEItemStack> inv = this.proxy.getStorage().getItemInventory();
|
|
final IEnergyGrid energy = this.proxy.getEnergy();
|
|
final ICraftingGrid cg = this.proxy.getCrafting();
|
|
final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE );
|
|
final SchedulingMode schedulingMode = (SchedulingMode) this.getConfigManager().getSetting( Settings.SCHEDULING_MODE );
|
|
|
|
if( destination != null )
|
|
{
|
|
int x = 0;
|
|
|
|
for( x = 0; x < this.availableSlots() && this.itemToSend > 0; x++ )
|
|
{
|
|
int slotToExport = this.getStartingSlot( schedulingMode, x );
|
|
|
|
final IAEItemStack ais = this.config.getAEStackInSlot( slotToExport );
|
|
|
|
if( ais == null || this.itemToSend <= 0 || this.craftOnly() )
|
|
{
|
|
if( this.isCraftingEnabled() )
|
|
{
|
|
this.didSomething = this.craftingTracker.handleCrafting( slotToExport, this.itemToSend, ais, destination, this.getTile().getWorldObj(), this.proxy.getGrid(), cg, this.mySrc ) || this.didSomething;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
final long before = this.itemToSend;
|
|
|
|
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
|
|
{
|
|
for( IAEItemStack o : ImmutableList.copyOf( inv.getStorageList().findFuzzy( ais, fzMode ) ) )
|
|
{
|
|
this.pushItemIntoTarget( destination, energy, inv, o );
|
|
if( this.itemToSend <= 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.pushItemIntoTarget( destination, energy, inv, ais );
|
|
}
|
|
|
|
if( this.itemToSend == before && this.isCraftingEnabled() )
|
|
{
|
|
this.didSomething = this.craftingTracker.handleCrafting( slotToExport, this.itemToSend, ais, destination, this.getTile().getWorldObj(), this.proxy.getGrid(), cg, this.mySrc ) || this.didSomething;
|
|
}
|
|
}
|
|
|
|
this.updateSchedulingMode( schedulingMode, x );
|
|
}
|
|
else
|
|
{
|
|
return TickRateModulation.SLEEP;
|
|
}
|
|
}
|
|
catch( GridAccessException e )
|
|
{
|
|
// :P
|
|
}
|
|
|
|
final int failedAttempts = this.craftingTracker.getFailedCraftingAttempts();
|
|
|
|
if( this.isCraftingEnabled() && failedAttempts > 0 )
|
|
{
|
|
return this.getFailedCraftingPenalty( failedAttempts );
|
|
}
|
|
|
|
return this.didSomething ? TickRateModulation.FASTER : TickRateModulation.SLOWER;
|
|
}
|
|
|
|
@Override
|
|
public void getBoxes( IPartCollisionHelper bch )
|
|
{
|
|
bch.addBox( 4, 4, 12, 12, 12, 14 );
|
|
bch.addBox( 5, 5, 14, 11, 11, 15 );
|
|
bch.addBox( 6, 6, 15, 10, 10, 16 );
|
|
bch.addBox( 6, 6, 11, 10, 10, 12 );
|
|
}
|
|
|
|
@Override
|
|
@SideOnly( Side.CLIENT )
|
|
public void renderInventory( IPartRenderHelper rh, RenderBlocks renderer )
|
|
{
|
|
rh.setTexture( CableBusTextures.PartExportSides.getIcon(), CableBusTextures.PartExportSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), this.is.getIconIndex(), CableBusTextures.PartExportSides.getIcon(), CableBusTextures.PartExportSides.getIcon() );
|
|
|
|
rh.setBounds( 4, 4, 12, 12, 12, 14 );
|
|
rh.renderInventoryBox( renderer );
|
|
|
|
rh.setBounds( 5, 5, 14, 11, 11, 15 );
|
|
rh.renderInventoryBox( renderer );
|
|
|
|
rh.setBounds( 6, 6, 15, 10, 10, 16 );
|
|
rh.renderInventoryBox( renderer );
|
|
}
|
|
|
|
@Override
|
|
@SideOnly( Side.CLIENT )
|
|
public void renderStatic( int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer )
|
|
{
|
|
this.renderCache = rh.useSimplifiedRendering( x, y, z, this, this.renderCache );
|
|
rh.setTexture( CableBusTextures.PartExportSides.getIcon(), CableBusTextures.PartExportSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), this.is.getIconIndex(), CableBusTextures.PartExportSides.getIcon(), CableBusTextures.PartExportSides.getIcon() );
|
|
|
|
rh.setBounds( 4, 4, 12, 12, 12, 14 );
|
|
rh.renderBlock( x, y, z, renderer );
|
|
|
|
rh.setBounds( 5, 5, 14, 11, 11, 15 );
|
|
rh.renderBlock( x, y, z, renderer );
|
|
|
|
rh.setBounds( 6, 6, 15, 10, 10, 16 );
|
|
rh.renderBlock( x, y, z, renderer );
|
|
|
|
rh.setTexture( CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), this.is.getIconIndex(), CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon() );
|
|
|
|
rh.setBounds( 6, 6, 11, 10, 10, 12 );
|
|
rh.renderBlock( x, y, z, renderer );
|
|
|
|
this.renderLights( x, y, z, rh, renderer );
|
|
}
|
|
|
|
@Override
|
|
public int cableConnectionRenderTo()
|
|
{
|
|
return 5;
|
|
}
|
|
|
|
@Override
|
|
public boolean onPartActivate( EntityPlayer player, Vec3 pos )
|
|
{
|
|
if( !player.isSneaking() )
|
|
{
|
|
if( Platform.isClient() )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
Platform.openGUI( player, this.getHost().getTile(), this.side, GuiBridge.GUI_BUS );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public TickingRequest getTickingRequest( IGridNode node )
|
|
{
|
|
return new TickingRequest( TickRates.ExportBus.min, TickRates.ExportBus.max, this.isSleeping(), false );
|
|
}
|
|
|
|
@Override
|
|
public RedstoneMode getRSMode()
|
|
{
|
|
return (RedstoneMode) this.getConfigManager().getSetting( Settings.REDSTONE_CONTROLLED );
|
|
}
|
|
|
|
@Override
|
|
public TickRateModulation tickingRequest( IGridNode node, int ticksSinceLastCall )
|
|
{
|
|
return this.doBusWork();
|
|
}
|
|
|
|
@Override
|
|
public ImmutableSet<ICraftingLink> getRequestedJobs()
|
|
{
|
|
return this.craftingTracker.getRequestedJobs();
|
|
}
|
|
|
|
@Override
|
|
public IAEItemStack injectCraftedItems( ICraftingLink link, IAEItemStack items, Actionable mode )
|
|
{
|
|
final InventoryAdaptor d = this.getHandler();
|
|
|
|
try
|
|
{
|
|
if( d != null && this.proxy.isActive() )
|
|
{
|
|
final IEnergyGrid energy = this.proxy.getEnergy();
|
|
final double power = items.getStackSize();
|
|
|
|
if( energy.extractAEPower( power, mode, PowerMultiplier.CONFIG ) > power - 0.01 )
|
|
{
|
|
if( mode == Actionable.MODULATE )
|
|
{
|
|
return AEItemStack.create( d.addItems( items.getItemStack() ) );
|
|
}
|
|
return AEItemStack.create( d.simulateAdd( items.getItemStack() ) );
|
|
}
|
|
}
|
|
}
|
|
catch( GridAccessException e )
|
|
{
|
|
AELog.error( e );
|
|
}
|
|
|
|
return items;
|
|
}
|
|
|
|
@Override
|
|
public void jobStateChange( ICraftingLink link )
|
|
{
|
|
this.craftingTracker.jobStateChange( link );
|
|
}
|
|
|
|
@Override
|
|
protected boolean isSleeping()
|
|
{
|
|
return this.getHandler() == null || super.isSleeping();
|
|
}
|
|
|
|
private boolean craftOnly()
|
|
{
|
|
return this.getConfigManager().getSetting( Settings.CRAFT_ONLY ) == YesNo.YES;
|
|
}
|
|
|
|
private boolean isCraftingEnabled()
|
|
{
|
|
return this.getInstalledUpgrades( Upgrades.CRAFTING ) > 0;
|
|
}
|
|
|
|
private void pushItemIntoTarget( InventoryAdaptor d, IEnergyGrid energy, IMEInventory<IAEItemStack> inv, IAEItemStack ais )
|
|
{
|
|
final ItemStack is = ais.getItemStack();
|
|
is.stackSize = (int) this.itemToSend;
|
|
|
|
final ItemStack o = d.simulateAdd( is );
|
|
long canFit = o == null ? this.itemToSend : this.itemToSend - o.stackSize;
|
|
|
|
if( canFit > 0 )
|
|
{
|
|
ais = ais.copy();
|
|
ais.setStackSize( canFit );
|
|
IAEItemStack itemsToAdd = Platform.poweredExtraction( energy, inv, ais, this.mySrc );
|
|
|
|
if( itemsToAdd != null )
|
|
{
|
|
this.itemToSend -= itemsToAdd.getStackSize();
|
|
|
|
final ItemStack failed = d.addItems( itemsToAdd.getItemStack() );
|
|
if( failed != null )
|
|
{
|
|
ais.setStackSize( failed.stackSize );
|
|
inv.injectItems( ais, Actionable.MODULATE, this.mySrc );
|
|
}
|
|
else
|
|
{
|
|
this.didSomething = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private int getStartingSlot( SchedulingMode schedulingMode, int x )
|
|
{
|
|
if( schedulingMode == SchedulingMode.RANDOM )
|
|
{
|
|
return Platform.getRandom().nextInt( this.availableSlots() );
|
|
}
|
|
|
|
if( schedulingMode == SchedulingMode.ROUNDROBIN )
|
|
{
|
|
return ( this.nextSlot + x ) % this.availableSlots();
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
private void updateSchedulingMode( SchedulingMode schedulingMode, int x )
|
|
{
|
|
if( schedulingMode == SchedulingMode.ROUNDROBIN )
|
|
{
|
|
this.nextSlot = ( this.nextSlot + x ) % this.availableSlots();
|
|
}
|
|
}
|
|
|
|
private TickRateModulation getFailedCraftingPenalty( int failedAttempts )
|
|
{
|
|
if( failedAttempts > 5 )
|
|
{
|
|
return TickRateModulation.SLOWER;
|
|
}
|
|
else if( failedAttempts > 1 )
|
|
{
|
|
return TickRateModulation.SAME;
|
|
}
|
|
|
|
return TickRateModulation.FASTER;
|
|
}
|
|
}
|