Compare commits

...

57 Commits

Author SHA1 Message Date
PrototypeTrousers 7d1c502b41 workss 2022-04-04 15:44:22 -03:00
PrototypeTrousers 63653c1833 added packets for missing items report 2022-04-04 03:55:51 -03:00
PrototypeTrousers 6cadfbdcdc 3 2022-04-01 19:30:18 -03:00
PrototypeTrousers d054c6ab91 2 2022-04-01 19:30:18 -03:00
PrototypeTrousers 234b1c5dc6 meh. crafting gets stuck if the output loops 2022-04-01 19:30:18 -03:00
PrototypeTrousers 8cc29734a2 positive loop support 2022-04-01 19:30:18 -03:00
PrototypeTrousers 1e9e8d2639 more checks if "gregtech" mod is loaded 2022-03-31 21:16:14 -03:00
PrototypeTrousers 19c6e2ff2d support for IC2 damageable items 2022-03-27 08:52:37 -03:00
PrototypeTrousers 4f25c1551b increase internal buffer of ME Chest
Fix item amount not refreshing when inserted/extracted
2022-03-27 08:10:02 -03:00
PrototypeTrousers 3b94e9420d fix NPE with ae2fc and blocking mode 2022-03-25 23:46:52 -03:00
PrototypeTrousers f30f334a23 move nonblocking call out of method used by ae2fc coremod 2022-03-24 23:25:28 -03:00
PrototypeTrousers 706e577dab Fix container item crafting (again)
avoid making some copies
fix crash without JEI
2022-03-16 00:52:38 -03:00
PrototypeTrousers ccc8486571 check if gregtech is loaded before checking for MetaTools 2022-03-12 22:36:22 -03:00
PrototypeTrousers 3e8440644e fix autocrafting with container items 2022-03-12 22:21:04 -03:00
PrototypeTrousers 50f4e08b64 Merge remote-tracking branch 'origin/AE2-Omnifactory' into AE2-Omnifactory 2022-03-12 17:27:17 -03:00
PrototypeTrousers cfa9fa2843 invalidate cached itemstack if its gonna be used in a real insertion 2022-03-12 17:14:37 -03:00
PrototypeTrousers 47f819e021 invalidate cached itemstack if its gonna be used in a real insertion 2022-03-12 11:03:04 -03:00
PrototypeTrousers 6d151bb890 GTCEu blocking mode fix 2022-03-11 23:11:52 -03:00
PrototypeTrousers 3305270a71 clean-up 2022-03-11 22:04:58 -03:00
PrototypeTrousers f824bfd2e1 small optimization 2022-03-10 21:35:18 -03:00
PrototypeTrousers 036f4e1c5b heavily tweaked auto-crafting 2022-03-09 23:14:02 -03:00
PrototypeTrousers 146d3f5628 fix fluid dupe 2022-03-06 08:24:29 -03:00
PrototypeTrousers 9c821cb015 cleaning 2022-03-05 23:29:20 -03:00
PrototypeTrousers 3a83c99b1f fix container items return properly 2022-03-05 11:15:32 -03:00
PrototypeTrousers 447c6debab account for interfaces priority affecting which items are extractable 2022-03-04 22:49:55 -03:00
PrototypeTrousers 50470ae3cf version 2022-03-04 21:44:58 -03:00
PrototypeTrousers 993be652c9 delay container item return when simulating crafting tree 2022-03-04 21:30:26 -03:00
PrototypeTrousers b3bfbd0b58 remove debugging log 2022-03-04 17:08:23 -03:00
PrototypeTrousers 49b3dc8b60 undo partially pattern cache rebuild optimization
enabled pattern substitution now can use substitute patterned items
2022-03-03 22:25:10 -03:00
PrototypeTrousers 71ffcfb839 JEI transfer handler OutOfBounds fix 2022-03-01 13:02:09 -03:00
PrototypeTrousers 73f76a6654 clean up 2022-02-28 23:30:52 -03:00
PrototypeTrousers 645de1d868 Merge branch 'craftingtree-tweaks' into AE2-Omnifactory 2022-02-28 23:17:21 -03:00
PrototypeTrousers 8f40478695 version 2022-02-28 23:16:53 -03:00
PrototypeTrousers 056fcc3818 switch to extractable instead of cached item list 2022-02-28 23:16:53 -03:00
PrototypeTrousers 0ed0eb9d5f better logging 2022-02-28 23:16:49 -03:00
PrototypeTrousers 3ddc846648 Merge branch 'craftingtree-tweaks' into AE2-Omnifactory 2022-02-28 23:06:11 -03:00
PrototypeTrousers f98f6ef852 misc cleaning 2022-02-28 22:57:35 -03:00
PrototypeTrousers 4192d721a0 only fire simulation if a player requested it 2022-02-28 21:25:33 -03:00
PrototypeTrousers a0f3ef9d86 cut crafting tree earlier if ingredients are available 2022-02-28 21:25:13 -03:00
PrototypeTrousers 6b29288de6 remove crafting penalties 2022-02-28 00:13:07 -03:00
PrototypeTrousers 285fc6314c small optimization to crafting tree 2022-02-27 23:04:29 -03:00
PrototypeTrousers 50fd83e96b adjust default blocking mode settings 2022-02-25 00:09:33 -03:00
PrototypeTrousers cc51138a6a blocking mode changes again
misc cleaning
2022-02-24 23:54:50 -03:00
PrototypeTrousers 918df0bf7f clean up 2022-02-22 23:55:52 -03:00
PrototypeTrousers c852199901 bump version 2022-02-22 22:55:44 -03:00
PrototypeTrousers fd95d3de47 fixed typo gtceu -> gteu 2022-02-22 22:37:28 -03:00
PrototypeTrousers c3dd6dabe1 fix blocking mode again... 2022-02-22 22:11:57 -03:00
PrototypeTrousers b0e81ac2d1 fix blocking mode somehow voiding items 2022-02-22 19:40:15 -03:00
PrototypeTrousers 30f4cdf545 attempt at pattern rebuild optimization 2022-02-22 00:02:17 -03:00
PrototypeTrousers ee9441474e tweak cache reset on interface config 2022-02-21 18:25:58 -03:00
PrototypeTrousers 8846202270 More itemstacks caching
Micro optimization on molecular assemblers
2022-02-21 15:11:16 -03:00
PrototypeTrousers 17a900ae9a actually return if a crafting job is running 2022-02-19 23:03:33 -03:00
PrototypeTrousers 66bc243b41 cache more itemstacks 2022-02-19 23:02:40 -03:00
PrototypeTrousers a2bda8f449 tile fluid textures on fluid interfaces properly 2022-02-17 20:15:29 -03:00
PrototypeTrousers a2c2a4df0f oops, add integrated circuit to default non blocking items 2022-02-15 19:33:56 -03:00
PrototypeTrousers b4e237244a fix interfaces with crafting cards attached to storage bus not working
add missing buttons to oredict storagebus
2022-02-14 17:15:51 -03:00
PrototypeTrousers b541ad8d18 misc cleaning
add lenses to non blocking list
2022-02-10 20:15:58 -03:00
63 changed files with 3357 additions and 2717 deletions
+2 -1
View File
@@ -4,7 +4,7 @@ aebuild=7
aegroup=appeng
aebasename=appliedenergistics2
extended=extended_life
extendedversion=v49ac
extendedversion=v52b
#########################################################
# Versions #
#########################################################
@@ -26,6 +26,7 @@ cofhcore_version=1.12.2-4.5.2.19
crafttweaker_version=4.1.8.9
inventorytweaks_version=1.63
ctm_version=MC1.12.2-0.3.1.16
forestry_version=5.8.2.387
#########################################################
# Deployment #
#########################################################
+2
View File
@@ -97,6 +97,8 @@ dependencies {
compileOnly "inventory-tweaks:InventoryTweaks:${inventorytweaks_version}:api"
compileOnly "team.chisel.ctm:CTM:${ctm_version}"
compileOnly "de.ellpeck.actuallyadditions:ActuallyAdditions:1.12.2-r152.16:api"
deobfCompile "net.sengir.forestry:forestry_${minecraft_version}:$forestry_version"
// at runtime, use the full JEI jar
runtime "mezz.jei:jei_${minecraft_version}:${jei_version}"
@@ -29,7 +29,7 @@ public enum PowerUnits
AE( "gui.appliedenergistics2.units.appliedenergstics" ), // Native Units - AE Energy
EU( "gui.appliedenergistics2.units.ic2" ), // IndustrialCraft 2 - Energy Units
RF( "gui.appliedenergistics2.units.rf" ), // RF - Redstone Flux
GTCEU( "gui.appliedenergistics2.units.gtceu" ); // RF - Redstone Flux
GTEU( "gui.appliedenergistics2.units.gteu" ); // RF - Redstone Flux
/**
* unlocalized name for the power unit.
@@ -47,14 +47,13 @@ public enum PowerUnits
/**
* do power conversion using AE's conversion rates.
*
* <p>
* Example: PowerUnits.EU.convertTo( PowerUnits.AE, 32 );
*
* <p>
* will normally returns 64, as it will convert the EU, to AE with AE's power settings.
*
* @param target target power unit
* @param value value
*
* @param value value
* @return value converted to target units, from this units.
*/
public double convertTo( final PowerUnits target, final double value )
@@ -29,7 +29,7 @@ public enum TunnelType
ME, // Network Tunnel
IC2_POWER, // EU Tunnel
FE_POWER, // Forge Energy tunnel
GTCEU_POWER, // Forge Energy tunnel
GTEU_POWER, // Forge Energy tunnel
REDSTONE, // Redstone Tunnel
FLUID, // Fluid Tunnel
ITEM, // Item Tunnel
@@ -88,7 +88,7 @@ public interface IParts
IItemDefinition p2PTunnelFE();
IItemDefinition p2PTunnelGTCEU();
IItemDefinition p2PTunnelGTEU();
IItemDefinition p2PTunnelLight();
@@ -56,7 +56,7 @@ public class BlockMolecularAssembler extends AEBaseTileBlock
@Override
protected IProperty[] getAEStates()
{
return new IProperty[] { POWERED };
return new IProperty[]{POWERED};
}
@Override
@@ -108,4 +108,14 @@ public class BlockMolecularAssembler extends AEBaseTileBlock
return super.onBlockActivated( w, pos, state, p, hand, side, hitX, hitY, hitZ );
}
@Override
public void onNeighborChange( IBlockAccess world, BlockPos pos, BlockPos neighbor )
{
final TileMolecularAssembler tg = this.getTileEntity( world, pos );
if( tg != null )
{
tg.updateNeighbors( world, pos, neighbor );
}
}
}
+24 -37
View File
@@ -33,6 +33,7 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import appeng.container.slot.*;
import appeng.util.Platform;
import com.google.common.base.Joiner;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
@@ -159,7 +160,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
final List<Slot> slots = this.getInventorySlots();
final Iterator<Slot> i = slots.iterator();
while( i.hasNext() )
while ( i.hasNext() )
{
if( i.next() instanceof SlotME )
{
@@ -208,13 +209,17 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
}
}
GlStateManager.enableDepth();
bookmarkedJEIghostItem(mouseX,mouseY);
if( Platform.isModLoaded( "jei" ) )
{
bookmarkedJEIghostItem( mouseX, mouseY );
}
GlStateManager.disableDepth();
}
void bookmarkedJEIghostItem(final int mouseX, final int mouseY) {
if (!isJeiGhostItem)
@Optional.Method( modid = "jei" )
void bookmarkedJEIghostItem( final int mouseX, final int mouseY )
{
if( !isJeiGhostItem )
{
bookmarkedIngredient = runtime.getBookmarkOverlay().getIngredientUnderMouse();
}
@@ -248,7 +253,9 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
}
}
}
private void drawTargets(int mouseX, int mouseY) {
private void drawTargets( int mouseX, int mouseY )
{
GlStateManager.disableLighting();
for( IGhostIngredientHandler.Target target : hoveredIngredientTargets )
{
@@ -377,17 +384,13 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
final AppEngSlot aeSlot = (AppEngSlot) slot;
if( aeSlot.isSlotEnabled() )
{
this.drawTexturedModalRect( ox + aeSlot.xPos - 1, oy + aeSlot.yPos - 1, optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1,
18,
18 );
this.drawTexturedModalRect( ox + aeSlot.xPos - 1, oy + aeSlot.yPos - 1, optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, 18, 18 );
}
else
{
GlStateManager.color( 1.0F, 1.0F, 1.0F, 0.4F );
GlStateManager.enableBlend();
this.drawTexturedModalRect( ox + aeSlot.xPos - 1, oy + aeSlot.yPos - 1, optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1,
18,
18 );
this.drawTexturedModalRect( ox + aeSlot.xPos - 1, oy + aeSlot.yPos - 1, optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, 18, 18 );
GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F );
}
}
@@ -506,7 +509,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
{
final EntityPlayer player = Minecraft.getMinecraft().player;
if( this.isJeiGhostItem && isDraggingJeiGhostItem)
if( this.isJeiGhostItem && isDraggingJeiGhostItem )
{
for( IGhostIngredientHandler.Target target : hoveredIngredientTargets )
{
@@ -759,7 +762,8 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
this.disableShiftClick = false;
}
if (clickType == ClickType.PICKUP && isJeiGhostItem && !isDraggingJeiGhostItem) {
if( clickType == ClickType.PICKUP && isJeiGhostItem && !isDraggingJeiGhostItem )
{
this.isDraggingJeiGhostItem = true;
return;
}
@@ -879,7 +883,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
if( stack != ItemStack.EMPTY )
{
InventoryAction direction = wheel > 0 ? InventoryAction.PLACE_SINGLE : InventoryAction.PICKUP_SINGLE;
final PacketInventoryAction p = new PacketInventoryAction( direction , slot.slotNumber , 0);
final PacketInventoryAction p = new PacketInventoryAction( direction, slot.slotNumber, 0 );
NetworkHandler.instance().sendToServer( p );
}
}
@@ -1032,27 +1036,11 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
final float f1 = 0.00390625F;
final float f = 0.00390625F;
final float par6 = 16;
vb.pos( par1 + 0, par2 + par6, this.zLevel )
.tex( ( par3 + 0 ) * f, ( par4 + par6 ) * f1 )
.color( 1.0f, 1.0f, 1.0f,
aes.getOpacityOfIcon() )
.endVertex();
vb.pos( par1 + 0, par2 + par6, this.zLevel ).tex( ( par3 + 0 ) * f, ( par4 + par6 ) * f1 ).color( 1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon() ).endVertex();
final float par5 = 16;
vb.pos( par1 + par5, par2 + par6, this.zLevel )
.tex( ( par3 + par5 ) * f, ( par4 + par6 ) * f1 )
.color( 1.0f, 1.0f, 1.0f,
aes.getOpacityOfIcon() )
.endVertex();
vb.pos( par1 + par5, par2 + 0, this.zLevel )
.tex( ( par3 + par5 ) * f, ( par4 + 0 ) * f1 )
.color( 1.0f, 1.0f, 1.0f,
aes.getOpacityOfIcon() )
.endVertex();
vb.pos( par1 + 0, par2 + 0, this.zLevel )
.tex( ( par3 + 0 ) * f, ( par4 + 0 ) * f1 )
.color( 1.0f, 1.0f, 1.0f,
aes.getOpacityOfIcon() )
.endVertex();
vb.pos( par1 + par5, par2 + par6, this.zLevel ).tex( ( par3 + par5 ) * f, ( par4 + par6 ) * f1 ).color( 1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon() ).endVertex();
vb.pos( par1 + par5, par2 + 0, this.zLevel ).tex( ( par3 + par5 ) * f, ( par4 + 0 ) * f1 ).color( 1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon() ).endVertex();
vb.pos( par1 + 0, par2 + 0, this.zLevel ).tex( ( par3 + 0 ) * f, ( par4 + 0 ) * f1 ).color( 1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon() ).endVertex();
tessellator.draw();
}
@@ -1066,8 +1054,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
{
if( ( (AppEngSlot) s ).getIsValid() == hasCalculatedValidness.NotAvailable )
{
boolean isValid = s.isItemValid(
is ) || s instanceof SlotOutput || s instanceof AppEngCraftingSlot || s instanceof SlotDisabled || s instanceof SlotInaccessible || s instanceof SlotFake || s instanceof SlotRestrictedInput || s instanceof SlotDisconnected;
boolean isValid = s.isItemValid( is ) || s instanceof SlotOutput || s instanceof AppEngCraftingSlot || s instanceof SlotDisabled || s instanceof SlotInaccessible || s instanceof SlotFake || s instanceof SlotRestrictedInput || s instanceof SlotDisconnected;
if( isValid && s instanceof SlotRestrictedInput )
{
try
@@ -1,38 +1,46 @@
package appeng.client.gui.implementations;
import appeng.api.config.AccessRestriction;
import appeng.api.config.ActionItems;
import appeng.api.config.Settings;
import appeng.api.config.StorageFilter;
import appeng.client.gui.AEBaseGui;
import appeng.client.gui.widgets.GuiImgButton;
import appeng.client.gui.widgets.GuiTabButton;
import appeng.client.gui.widgets.MEGuiTextField;
import appeng.container.implementations.ContainerPartOreDictStorageBus;
import appeng.container.implementations.ContainerOreDictStorageBus;
import appeng.core.AELog;
import appeng.core.localization.GuiText;
import appeng.core.sync.GuiBridge;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketConfigButton;
import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.core.sync.packets.PacketValueConfig;
import appeng.parts.misc.PartOreDicStorageBus;
import appeng.util.item.OreDictFilterMatcher;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.entity.player.InventoryPlayer;
import org.lwjgl.input.Mouse;
import java.io.IOException;
import java.util.regex.Pattern;
public class GuiPartOreDictStorageBus extends AEBaseGui
public class GuiOreDictStorageBus extends AEBaseGui
{
private final ContainerOreDictStorageBus container;
PartOreDicStorageBus part;
private GuiTabButton priority;
private GuiImgButton partition;
private GuiImgButton storageFilter;
private GuiImgButton rwMode;
private static final Pattern ORE_DICTIONARY_FILTER = Pattern.compile( "[(!]* *[0-9a-zA-Z*]* *\\)*( *[&|^]? *[(!]* *[0-9a-zA-Z*]* *\\)*)*" );
private MEGuiTextField searchFieldInputs;
public GuiPartOreDictStorageBus( final InventoryPlayer inventoryPlayer, final PartOreDicStorageBus te )
public GuiOreDictStorageBus( final InventoryPlayer inventoryPlayer, final PartOreDicStorageBus te )
{
super( new ContainerPartOreDictStorageBus( inventoryPlayer, te ) );
super( new ContainerOreDictStorageBus( inventoryPlayer, te ) );
this.container = (ContainerOreDictStorageBus) super.inventorySlots;
part = te;
this.ySize = 84;
}
@@ -52,6 +60,8 @@ public class GuiPartOreDictStorageBus extends AEBaseGui
this.buttonList.add( this.priority = new GuiTabButton( this.guiLeft + 154, this.guiTop, 2 + 4 * 16, GuiText.Priority.getLocal(), this.itemRender ) );
this.buttonList.add( this.partition = new GuiImgButton( this.guiLeft - 18, this.guiTop + 28, Settings.ACTIONS, ActionItems.WRENCH ) );
this.buttonList.add( this.rwMode = new GuiImgButton( this.guiLeft - 18, this.guiTop + 48, Settings.ACCESS, AccessRestriction.READ_WRITE ) );
this.buttonList.add( this.storageFilter = new GuiImgButton( this.guiLeft - 18, this.guiTop + 68, Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY ) );
try
{
@@ -73,21 +83,31 @@ public class GuiPartOreDictStorageBus extends AEBaseGui
protected void actionPerformed( final GuiButton btn ) throws IOException
{
super.actionPerformed( btn );
if( btn == this.priority )
final boolean backwards = Mouse.isButtonDown( 1 );
try
{
NetworkHandler.instance().sendToServer( new PacketSwitchGuis( GuiBridge.GUI_PRIORITY ) );
if( btn == this.priority )
{
NetworkHandler.instance().sendToServer( new PacketSwitchGuis( GuiBridge.GUI_PRIORITY ) );
}
else if( btn == this.partition )
{
NetworkHandler.instance().sendToServer( new PacketValueConfig( "StorageBus.Action", "Partition" ) );
}
else if( btn == this.rwMode )
{
NetworkHandler.instance().sendToServer( new PacketConfigButton( this.rwMode.getSetting(), backwards ) );
}
else if( btn == this.storageFilter )
{
NetworkHandler.instance().sendToServer( new PacketConfigButton( this.storageFilter.getSetting(), backwards ) );
}
}
if( btn == this.partition )
catch( final IOException e )
{
NetworkHandler.instance().sendToServer( new PacketValueConfig( "StorageBus.Action", "Partition" ) );
try
{
NetworkHandler.instance().sendToServer( new PacketValueConfig( "OreDictStorageBus.getRegex", "1" ) );
}
catch( IOException e )
{
e.printStackTrace();
}
AELog.debug( e );
}
}
@@ -132,6 +152,16 @@ public class GuiPartOreDictStorageBus extends AEBaseGui
this.fontRenderer.drawString( "^ = XOR " + "! = NOT", 8, 48, 4210752 );
this.fontRenderer.drawString( "() for priority " + "* for wildcard", 8, 60, 4210752 );
this.fontRenderer.drawString( "Ex.: *Redstone*&!dustRedstone", 8, 72, 4210752 );
if( this.storageFilter != null )
{
this.storageFilter.set( container.getStorageFilter() );
}
if( this.rwMode != null )
{
this.rwMode.set( container.getReadWriteMode() );
}
}
@Override
@@ -87,7 +87,7 @@ public class GuiImgButton extends GuiButton implements ITooltip
this.registerApp( 16 * 10, Settings.POWER_UNITS, PowerUnits.AE, ButtonToolTips.PowerUnits, PowerUnits.AE.unlocalizedName );
this.registerApp( 16 * 10 + 1, Settings.POWER_UNITS, PowerUnits.EU, ButtonToolTips.PowerUnits, PowerUnits.EU.unlocalizedName );
this.registerApp( 16 * 10 + 4, Settings.POWER_UNITS, PowerUnits.RF, ButtonToolTips.PowerUnits, PowerUnits.RF.unlocalizedName );
this.registerApp( 16 * 10 + 1, Settings.POWER_UNITS, PowerUnits.GTCEU, ButtonToolTips.PowerUnits, PowerUnits.EU.unlocalizedName );
this.registerApp( 16 * 10 + 1, Settings.POWER_UNITS, PowerUnits.GTEU, ButtonToolTips.PowerUnits, PowerUnits.EU.unlocalizedName );
this.registerApp( 3, Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE, ButtonToolTips.RedstoneMode, ButtonToolTips.AlwaysActive );
this.registerApp( 0, Settings.REDSTONE_CONTROLLED, RedstoneMode.LOW_SIGNAL, ButtonToolTips.RedstoneMode, ButtonToolTips.ActiveWithoutSignal );
@@ -109,15 +109,11 @@ public class GuiImgButton extends GuiButton implements ITooltip
this.registerApp( 16 * 2 + 3, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_Auto );
this.registerApp( 16 * 2 + 4, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_Standard );
this.registerApp( 16 * 2 + 5, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIAuto );
this.registerApp( 16 * 2 + 6, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_JEIStandard );
this.registerApp( 16 * 2 + 6, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIStandard );
this.registerApp( 16 * 2 + 7, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH_KEEP, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_AutoKeep );
this.registerApp( 16 * 2 + 8, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH_KEEP, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_StandardKeep );
this.registerApp( 16 * 2 + 9, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH_KEEP, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_JEIAutoKeep );
this.registerApp( 16 * 2 + 10, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH_KEEP, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_JEIStandardKeep );
this.registerApp( 16 * 2 + 8, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH_KEEP, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_StandardKeep );
this.registerApp( 16 * 2 + 9, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH_KEEP, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIAutoKeep );
this.registerApp( 16 * 2 + 10, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH_KEEP, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIStandardKeep );
this.registerApp( 16 * 5 + 3, Settings.LEVEL_TYPE, LevelType.ENERGY_LEVEL, ButtonToolTips.LevelType, ButtonToolTips.LevelType_Energy );
this.registerApp( 16 * 4 + 3, Settings.LEVEL_TYPE, LevelType.ITEM_LEVEL, ButtonToolTips.LevelType, ButtonToolTips.LevelType_Item );
@@ -175,19 +171,15 @@ public class GuiImgButton extends GuiButton implements ITooltip
this.registerApp( 16 * 11 + 2, Settings.CRAFT_VIA_REDSTONE, YesNo.YES, ButtonToolTips.EmitterMode, ButtonToolTips.CraftViaRedstone );
this.registerApp( 16 * 11 + 1, Settings.CRAFT_VIA_REDSTONE, YesNo.NO, ButtonToolTips.EmitterMode, ButtonToolTips.EmitWhenCrafting );
this.registerApp( 16 * 3 + 5, Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY, ButtonToolTips.ReportInaccessibleItems,
ButtonToolTips.ReportInaccessibleItemsNo );
this.registerApp( 16 * 3 + 6, Settings.STORAGE_FILTER, StorageFilter.NONE, ButtonToolTips.ReportInaccessibleItems,
ButtonToolTips.ReportInaccessibleItemsYes );
this.registerApp( 16 * 3 + 5, Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY, ButtonToolTips.ReportInaccessibleItems, ButtonToolTips.ReportInaccessibleItemsNo );
this.registerApp( 16 * 3 + 6, Settings.STORAGE_FILTER, StorageFilter.NONE, ButtonToolTips.ReportInaccessibleItems, ButtonToolTips.ReportInaccessibleItemsYes );
this.registerApp( 16 * 14, Settings.PLACE_BLOCK, YesNo.YES, ButtonToolTips.BlockPlacement, ButtonToolTips.BlockPlacementYes );
this.registerApp( 16 * 14 + 1, Settings.PLACE_BLOCK, YesNo.NO, ButtonToolTips.BlockPlacement, ButtonToolTips.BlockPlacementNo );
this.registerApp( 16 * 15, Settings.SCHEDULING_MODE, SchedulingMode.DEFAULT, ButtonToolTips.SchedulingMode, ButtonToolTips.SchedulingModeDefault );
this.registerApp( 16 * 15 + 1, Settings.SCHEDULING_MODE, SchedulingMode.ROUNDROBIN, ButtonToolTips.SchedulingMode,
ButtonToolTips.SchedulingModeRoundRobin );
this.registerApp( 16 * 15 + 2, Settings.SCHEDULING_MODE, SchedulingMode.RANDOM, ButtonToolTips.SchedulingMode,
ButtonToolTips.SchedulingModeRandom );
this.registerApp( 16 * 15 + 1, Settings.SCHEDULING_MODE, SchedulingMode.ROUNDROBIN, ButtonToolTips.SchedulingMode, ButtonToolTips.SchedulingModeRoundRobin );
this.registerApp( 16 * 15 + 2, Settings.SCHEDULING_MODE, SchedulingMode.RANDOM, ButtonToolTips.SchedulingMode, ButtonToolTips.SchedulingModeRandom );
}
}
@@ -337,7 +329,7 @@ public class GuiImgButton extends GuiButton implements ITooltip
{
i = 0;
}
while( i + 30 < sb.length() && ( i = sb.lastIndexOf( " ", i + 30 ) ) != -1 )
while ( i + 30 < sb.length() && ( i = sb.lastIndexOf( " ", i + 30 ) ) != -1 )
{
sb.replace( i, i + 1, "\n" );
}
@@ -150,6 +150,7 @@ public class ContainerCraftConfirm extends AEBaseContainer
if( ccr.getCpu() == c )
{
found = true;
break;
}
}
@@ -1,10 +1,12 @@
package appeng.container.implementations;
import appeng.api.AEApi;
import appeng.api.config.*;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.container.AEBaseContainer;
import appeng.container.guisync.GuiSync;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketValueConfig;
import appeng.parts.misc.PartOreDicStorageBus;
@@ -21,11 +23,17 @@ import java.util.Iterator;
import java.util.Set;
public class ContainerPartOreDictStorageBus extends AEBaseContainer
public class ContainerOreDictStorageBus extends AEBaseContainer
{
private final PartOreDicStorageBus part;
public ContainerPartOreDictStorageBus( final InventoryPlayer ip, final PartOreDicStorageBus anchor )
@GuiSync( 3 )
public AccessRestriction rwMode = AccessRestriction.READ_WRITE;
@GuiSync( 4 )
public StorageFilter storageFilter = StorageFilter.EXTRACTABLE_ONLY;
public ContainerOreDictStorageBus( final InventoryPlayer ip, final PartOreDicStorageBus anchor )
{
super( ip, anchor );
this.part = anchor;
@@ -36,9 +44,12 @@ public class ContainerPartOreDictStorageBus extends AEBaseContainer
@Override
public void detectAndSendChanges()
{
if( Platform.isClient() )
this.verifyPermissions( SecurityPermissions.BUILD, false );
if( Platform.isServer() )
{
return;
this.setReadWriteMode( (AccessRestriction) part.getConfigManager().getSetting( Settings.ACCESS ) );
this.setStorageFilter( (StorageFilter) part.getConfigManager().getSetting( Settings.STORAGE_FILTER ) );
}
super.detectAndSendChanges();
@@ -106,4 +117,24 @@ public class ContainerPartOreDictStorageBus extends AEBaseContainer
e.printStackTrace();
}
}
public AccessRestriction getReadWriteMode()
{
return this.rwMode;
}
private void setReadWriteMode( final AccessRestriction rwMode )
{
this.rwMode = rwMode;
}
public StorageFilter getStorageFilter()
{
return this.storageFilter;
}
private void setStorageFilter( final StorageFilter storageFilter )
{
this.storageFilter = storageFilter;
}
}
+31 -14
View File
@@ -74,18 +74,20 @@ public final class AEConfig extends Configuration implements IConfigurableObject
};
private String[] nonBlockingItems = {
"[gregtech]", "gregtech:shape.mold.plate",
"gregtech:shape.mold.gear", "gregtech:shape.mold.credit",
"gregtech:shape.mold.bottle", "gregtech:shape.mold.ingot",
"gregtech:shape.mold.ball", "gregtech:shape.mold.block",
"gregtech:shape.mold.nugget", "gregtech:shape.mold.cylinder",
"gregtech:shape.mold.anvil", "gregtech:shape.mold.name",
"gregtech:shape.mold.gear.small", "gregtech:shape.mold.rotor",
"gregtech:shape.extruder.plate", "gregtech:shape.extruder.rod",
"gregtech:shape.extruder.bolt", "gregtech:shape.extruder.ring",
"gregtech:shape.extruder.cell", "gregtech:shape.extruder.ingot",
"gregtech:shape.extruder.wire", "gregtech:shape.extruder.pipe.tiny",
"[gregtech|actuallyadditions]", "gregtech:circuit.integrated",
"gregtech:shape.mold.plate", "gregtech:shape.mold.gear",
"gregtech:shape.mold.credit", "gregtech:shape.mold.bottle",
"gregtech:shape.mold.ingot", "gregtech:shape.mold.ball",
"gregtech:shape.mold.block", "gregtech:shape.mold.nugget",
"gregtech:shape.mold.cylinder", "gregtech:shape.mold.anvil",
"gregtech:shape.mold.name", "gregtech:shape.mold.gear.small",
"gregtech:shape.mold.rotor", "gregtech:shape.extruder.plate",
"gregtech:shape.extruder.rod", "gregtech:shape.extruder.bolt",
"gregtech:shape.extruder.ring", "gregtech:shape.extruder.cell",
"gregtech:shape.extruder.ingot", "gregtech:shape.extruder.wire",
"gregtech:shape.extruder.pipe.tiny",
"gregtech:shape.extruder.pipe.small",
"gregtech:shape.extruder.pipe.medium",
"gregtech:shape.extruder.pipe.normal",
"gregtech:shape.extruder.pipe.large",
"gregtech:shape.extruder.pipe.huge",
@@ -97,13 +99,28 @@ public final class AEConfig extends Configuration implements IConfigurableObject
"gregtech:shape.extruder.bottle", "gregtech:shape.extruder.foil",
"gregtech:shape.extruder.gear_small",
"gregtech:shape.extruder.rod_long", "gregtech:shape.extruder.rotor",
"gregtech:glass_lens.white", "gregtech:glass_lens.orange",
"gregtech:glass_lens.magenta", "gregtech:glass_lens.light_blue",
"gregtech:glass_lens.yellow", "gregtech:glass_lens.lime",
"gregtech:glass_lens.pink", "gregtech:glass_lens.gray",
"gregtech:glass_lens.light_gray", "gregtech:glass_lens.cyan",
"gregtech:glass_lens.purple", "gregtech:glass_lens.blue",
"gregtech:glass_lens.brown", "gregtech:glass_lens.green",
"gregtech:glass_lens.red", "gregtech:glass_lens.black",
"contenttweaker:smallgearextrudershape",
"contenttweaker:creativeportabletankmold"
"contenttweaker:creativeportabletankmold", "ore:lensAlmandine",
"ore:lensBlueTopaz", "ore:lensDiamond", "ore:lensEmerald",
"ore:lensGreenSapphire", "ore:lensRutile", "ore:lensRuby",
"ore:lensSapphire", "ore:lensTopaz", "ore:lensJasper",
"ore:lensGlass", "ore:lensOlivine", "ore:lensOpal",
"ore:lensAmethyst", "ore:lensLapis", "ore:lensEnderPearl",
"ore:lensEnderEye", "ore:lensGarnetRed", "ore:lensGarnetYellow",
"ore:lensVinteum", "ore:lensNetherStar",
};
// Default Energy Conversion Rates
private static final double DEFAULT_IC2_EXCHANGE = 2.0;
private static final double DEFAULT_GTCEU_EXCHANGE = 2.0;
private static final double DEFAULT_GTEU_EXCHANGE = 2.0;
private static final double DEFAULT_RF_EXCHANGE = 0.5;
private final IConfigManager settings = new ConfigManager( this );
@@ -181,7 +198,7 @@ public final class AEConfig extends Configuration implements IConfigurableObject
PowerUnits.EU.conversionRatio = this.get( "PowerRatios", "IC2", DEFAULT_IC2_EXCHANGE ).getDouble( DEFAULT_IC2_EXCHANGE );
PowerUnits.RF.conversionRatio = this.get( "PowerRatios", "ForgeEnergy", DEFAULT_RF_EXCHANGE ).getDouble( DEFAULT_RF_EXCHANGE );
PowerUnits.GTCEU.conversionRatio = this.get( "PowerRatios", "GTCEU", DEFAULT_GTCEU_EXCHANGE ).getDouble( DEFAULT_GTCEU_EXCHANGE );
PowerUnits.GTEU.conversionRatio = this.get( "PowerRatios", "GTEU", DEFAULT_GTEU_EXCHANGE ).getDouble( DEFAULT_GTEU_EXCHANGE );
final double usageEffective = this.get( "PowerRatios", "UsageMultiplier", 1.0 ).getDouble( 1.0 );
PowerMultiplier.CONFIG.multiplier = Math.max( 0.01, usageEffective );
+3
View File
@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import appeng.helpers.NonBlockingItems;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
@@ -238,6 +239,8 @@ public final class AppEng
AppEng.proxy.postInit();
AEConfig.instance().save();
NonBlockingItems.INSTANCE.init();
NetworkRegistry.INSTANCE.registerGuiHandler( this, GuiBridge.GUI_Handler );
NetworkHandler.init( "AE2" );
@@ -70,7 +70,7 @@ public final class ApiParts implements IParts
private final IItemDefinition p2PTunnelFluids;
private final IItemDefinition p2PTunnelEU;
private final IItemDefinition p2PTunnelFE;
private final IItemDefinition p2PTunnelGTCEU;
private final IItemDefinition p2PTunnelGTEU;
private final IItemDefinition p2PTunnelLight;
// private final IItemDefinition p2PTunnelOpenComputers;
private final IItemDefinition cableAnchor;
@@ -92,9 +92,7 @@ public final class ApiParts implements IParts
public ApiParts( FeatureFactory registry, PartModels partModels )
{
final ItemPart itemPart = new ItemPart();
registry.item( "part", () -> itemPart )
.rendering( new ItemPartRendering( partModels, itemPart ) )
.build();
registry.item( "part", () -> itemPart ).rendering( new ItemPartRendering( partModels, itemPart ) ).build();
// Register all part models
for( PartType partType : PartType.values() )
@@ -123,8 +121,7 @@ public final class ApiParts implements IParts
this.levelEmitter = new DamagedItemDefinition( "part.level_emitter", itemPart.createPart( PartType.LEVEL_EMITTER ) );
this.fluidLevelEmitter = new DamagedItemDefinition( "part.fluid_level_emitter", itemPart.createPart( PartType.FLUID_LEVEL_EMITTER ) );
this.annihilationPlane = new DamagedItemDefinition( "part.plane.annihilation", itemPart.createPart( PartType.ANNIHILATION_PLANE ) );
this.identityAnnihilationPlane = new DamagedItemDefinition( "part.plane.annihiliation.identity", itemPart
.createPart( PartType.IDENTITY_ANNIHILATION_PLANE ) );
this.identityAnnihilationPlane = new DamagedItemDefinition( "part.plane.annihiliation.identity", itemPart.createPart( PartType.IDENTITY_ANNIHILATION_PLANE ) );
this.fluidAnnihilationPlane = new DamagedItemDefinition( "part.plane.fluid_annihilation", itemPart.createPart( PartType.FLUID_ANNIHILATION_PLANE ) );
this.formationPlane = new DamagedItemDefinition( "part.plane.formation", itemPart.createPart( PartType.FORMATION_PLANE ) );
this.fluidFormationPlane = new DamagedItemDefinition( "part.plane.fluid_formation", itemPart.createPart( PartType.FLUID_FORMATION_PLANE ) );
@@ -134,7 +131,7 @@ public final class ApiParts implements IParts
this.p2PTunnelFluids = new DamagedItemDefinition( "part.tunnel.fluid", itemPart.createPart( PartType.P2P_TUNNEL_FLUIDS ) );
this.p2PTunnelEU = new DamagedItemDefinition( "part.tunnel.eu", itemPart.createPart( PartType.P2P_TUNNEL_IC2 ) );
this.p2PTunnelFE = new DamagedItemDefinition( "part.tunnel.fe", itemPart.createPart( PartType.P2P_TUNNEL_FE ) );
this.p2PTunnelGTCEU = new DamagedItemDefinition( "part.tunnel.gtceu", itemPart.createPart( PartType.P2P_TUNNEL_GTCEU ) );
this.p2PTunnelGTEU = new DamagedItemDefinition( "part.tunnel.gteu", itemPart.createPart( PartType.P2P_TUNNEL_GTEU ) );
this.p2PTunnelLight = new DamagedItemDefinition( "part.tunnel.light", itemPart.createPart( PartType.P2P_TUNNEL_LIGHT ) );
// this.p2PTunnelOpenComputers = new DamagedItemDefinition( itemMultiPart.createPart(
// PartType.P2PTunnelOpenComputers ) );
@@ -340,10 +337,10 @@ public final class ApiParts implements IParts
{
return this.p2PTunnelFE;
}
public IItemDefinition p2PTunnelGTCEU()
public IItemDefinition p2PTunnelGTEU()
{
return this.p2PTunnelGTCEU;
return this.p2PTunnelGTEU;
}
@Override
@@ -126,7 +126,7 @@ public enum AEFeature
P2P_TUNNEL_REDSTONE( "P2PTunnelRedstone", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_EU( "P2PTunnelEU", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_FE( "P2PTunnelFE", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_GTCEU( "P2PTunnelGTCEU", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_GTEU( "P2PTunnelGTEU", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_FLUIDS( "P2PTunnelFluids", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_LIGHT( "P2PTunnelLight", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_OPEN_COMPUTERS( "P2PTunnelOpenComputers", Constants.CATEGORY_P2P_TUNNELS ),
@@ -55,7 +55,8 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
private final Map<String, TunnelType> modIdTunnels = new HashMap<>( INITIAL_CAPACITY );
private final Map<Capability<?>, TunnelType> capTunnels = new HashMap<>( INITIAL_CAPACITY );
public void configure() {
public void configure()
{
final IDefinitions definitions = AEApi.instance().definitions();
final IBlocks blocks = definitions.blocks();
@@ -64,31 +65,32 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
/**
* light!
*/
this.addNewAttunement(new ItemStack(Blocks.TORCH), TunnelType.LIGHT);
this.addNewAttunement(new ItemStack(Blocks.GLOWSTONE), TunnelType.LIGHT);
this.addNewAttunement( new ItemStack( Blocks.TORCH ), TunnelType.LIGHT );
this.addNewAttunement( new ItemStack( Blocks.GLOWSTONE ), TunnelType.LIGHT );
List<String> gtceOreDict = new ArrayList<>();
gtceOreDict.add("wireGtHex");
gtceOreDict.add("wireGtOctal");
gtceOreDict.add("wireGtQuadruple");
gtceOreDict.add("wireGtDouble");
gtceOreDict.add("wireGtSingle");
gtceOreDict.add("cableGtHex");
gtceOreDict.add("cableGtOctal");
gtceOreDict.add("cableGtQuadruple");
gtceOreDict.add("cableGtDouble");
gtceOreDict.add("cableGtSingle");
gtceOreDict.add( "wireGtHex" );
gtceOreDict.add( "wireGtOctal" );
gtceOreDict.add( "wireGtQuadruple" );
gtceOreDict.add( "wireGtDouble" );
gtceOreDict.add( "wireGtSingle" );
gtceOreDict.add( "cableGtHex" );
gtceOreDict.add( "cableGtOctal" );
gtceOreDict.add( "cableGtQuadruple" );
gtceOreDict.add( "cableGtDouble" );
gtceOreDict.add( "cableGtSingle" );
for(String oreDict : gtceOreDict) {
for( String oreDict : gtceOreDict )
{
Arrays.stream( OreDictionary.getOreNames() ).filter( oreName -> oreName.startsWith( oreDict ) ).forEach( oreName -> {
OreHelper.INSTANCE.getCachedOres( oreName ).forEach( stack -> this.addNewAttunement( stack, TunnelType.GTCEU_POWER ) );
OreHelper.INSTANCE.getCachedOres( oreName ).forEach( stack -> this.addNewAttunement( stack, TunnelType.GTEU_POWER ) );
} );
}
/**
* Forge energy tunnel items
*/
this.addNewAttunement( blocks.energyCellDense(), TunnelType.FE_POWER );
this.addNewAttunement( blocks.energyAcceptor(), TunnelType.FE_POWER );
this.addNewAttunement( blocks.energyCell(), TunnelType.FE_POWER );
@@ -145,12 +147,12 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
this.addNewAttunement( this.getModItem( "enderio", "itemitemconduit", OreDictionary.WILDCARD_VALUE ), TunnelType.ITEM );
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 0 ), TunnelType.ITEM ); // itemduct
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 1 ), TunnelType.ITEM ); // itemduct
// (opaque)
// (opaque)
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 2 ), TunnelType.ITEM ); // impulse
// itemduct
// itemduct
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 3 ), TunnelType.ITEM ); // impulse
// itemduct
// (opaque)
// itemduct
// (opaque)
/**
* attune based on lots of random item related stuff
@@ -166,12 +168,12 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
this.addNewAttunement( this.getModItem( "enderio", "itemliquidconduit", OreDictionary.WILDCARD_VALUE ), TunnelType.FLUID );
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 0 ), TunnelType.FLUID ); // fluiduct
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 1 ), TunnelType.FLUID ); // fluiduct
// (opaque)
// (opaque)
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 2 ), TunnelType.FLUID ); // fluiduct
// hardened
// hardened
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 3 ), TunnelType.FLUID ); // fluiduct
// hardened
// (opaque)
// hardened
// (opaque)
for( final AEColor c : AEColor.values() )
{
@@ -99,7 +99,7 @@ public enum GuiText
OCTunnel,
LightTunnel,
FETunnel,
GTCEUTunnel,
GTEUTunnel,
PressureTunnel,
// spatial
@@ -24,34 +24,9 @@ import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import appeng.core.sync.packets.*;
import io.netty.buffer.ByteBuf;
import appeng.core.sync.packets.PacketAssemblerAnimation;
import appeng.core.sync.packets.PacketClick;
import appeng.core.sync.packets.PacketCompassRequest;
import appeng.core.sync.packets.PacketCompassResponse;
import appeng.core.sync.packets.PacketCompressedNBT;
import appeng.core.sync.packets.PacketConfigButton;
import appeng.core.sync.packets.PacketCraftRequest;
import appeng.core.sync.packets.PacketFluidSlot;
import appeng.core.sync.packets.PacketInventoryAction;
import appeng.core.sync.packets.PacketJEIRecipe;
import appeng.core.sync.packets.PacketLightning;
import appeng.core.sync.packets.PacketMEFluidInventoryUpdate;
import appeng.core.sync.packets.PacketMEInventoryUpdate;
import appeng.core.sync.packets.PacketMatterCannon;
import appeng.core.sync.packets.PacketMockExplosion;
import appeng.core.sync.packets.PacketPaintedEntity;
import appeng.core.sync.packets.PacketPartPlacement;
import appeng.core.sync.packets.PacketPatternSlot;
import appeng.core.sync.packets.PacketProgressBar;
import appeng.core.sync.packets.PacketSwapSlots;
import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.core.sync.packets.PacketTargetFluidStack;
import appeng.core.sync.packets.PacketTargetItemStack;
import appeng.core.sync.packets.PacketTransitionEffect;
import appeng.core.sync.packets.PacketValueConfig;
public class AppEngPacketHandlerBase
{
@@ -107,7 +82,10 @@ public class AppEngPacketHandlerBase
PACKET_PAINTED_ENTITY( PacketPaintedEntity.class ),
PACKET_FLUID_TANK( PacketFluidSlot.class );
PACKET_FLUID_TANK( PacketFluidSlot.class ),
PACKET_INFORM_PLAYER( PacketInformPlayer.class );
private final Class<? extends AppEngPacket> packetClass;
private final Constructor<? extends AppEngPacket> packetConstructor;
@@ -141,7 +141,7 @@ public enum GuiBridge implements IGuiHandler
GUI_STORAGEBUS( ContainerStorageBus.class, PartStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_OREDICTSTORAGEBUS( ContainerPartOreDictStorageBus.class, PartOreDicStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_OREDICTSTORAGEBUS( ContainerOreDictStorageBus.class, PartOreDicStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_STORAGEBUS_FLUID( ContainerFluidStorageBus.class, PartFluidStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
@@ -0,0 +1,89 @@
package appeng.core.sync.packets;
import appeng.api.storage.data.IAEItemStack;
import appeng.core.AppEng;
import appeng.core.sync.AppEngPacket;
import appeng.core.sync.network.INetworkInfo;
import appeng.util.item.AEItemStack;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.text.TextComponentString;
import java.io.IOException;
public class PacketInformPlayer extends AppEngPacket
{
private IAEItemStack actualItem = null;
private IAEItemStack reportedItem = null;
private final InfoType type;
public PacketInformPlayer( ByteBuf stream ) throws IOException
{
this.type = InfoType.values()[stream.readInt()];
if( type == InfoType.PARTIAL_ITEM_EXTRACTION )
{
this.reportedItem = AEItemStack.fromPacket( stream );
this.actualItem = AEItemStack.fromPacket( stream );
}
else if( type == InfoType.NO_ITEMS_EXTRACTED )
{
this.reportedItem = AEItemStack.fromPacket( stream );
}
}
public PacketInformPlayer( final IAEItemStack iaeItemStack ) throws IOException
{
this( iaeItemStack, null );
}
public PacketInformPlayer( IAEItemStack extra, IAEItemStack result ) throws IOException
{
this.reportedItem = extra;
this.actualItem = result;
if( actualItem == null )
{
this.type = InfoType.NO_ITEMS_EXTRACTED;
}
else
{
this.type = InfoType.PARTIAL_ITEM_EXTRACTION;
}
final ByteBuf data = Unpooled.buffer();
data.writeInt( this.getPacketID() );
data.writeInt( type.ordinal() );
reportedItem.writeToPacket( data );
if( actualItem != null )
{
actualItem.writeToPacket( data );
}
this.configureWrite( data );
}
@Override
public void clientPacketData( final INetworkInfo network, final AppEngPacket packet, final EntityPlayer player )
{
TextComponentString msg = null;
if( this.type == InfoType.PARTIAL_ITEM_EXTRACTION )
{
AppEng.proxy.getPlayers().get( 0 ).sendStatusMessage( new TextComponentString( "System reported " + reportedItem.getStackSize() + " " + reportedItem.getItem().getItemStackDisplayName( reportedItem.getDefinition() ) + " available but could only extract" + actualItem.getStackSize() ), false );
}
else if( this.type == InfoType.NO_ITEMS_EXTRACTED )
{
AppEng.proxy.getPlayers().get( 0 ).sendStatusMessage( new TextComponentString( "System reported " + reportedItem.getStackSize() + " " + reportedItem.getItem().getItemStackDisplayName( reportedItem.getDefinition() ) + " available but could not extract anything" ), false );
}
}
public enum InfoType
{
PARTIAL_ITEM_EXTRACTION,
NO_ITEMS_EXTRACTED
}
}
@@ -30,7 +30,6 @@ import java.util.List;
import appeng.api.config.FuzzyMode;
import appeng.container.implementations.ContainerExpandedProcessingPatternTerm;
import appeng.container.implementations.ContainerPatternTerm;
import gregtech.common.items.MetaTool;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@@ -41,6 +40,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.fml.common.Optional;
import net.minecraftforge.items.IItemHandler;
import appeng.api.AEApi;
@@ -175,7 +175,8 @@ public class PacketJEIRecipe extends AppEngPacket
{
ItemStack currentItem = craftMatrix.getStackInSlot( x );
if (x >= this.recipe.size()) {
if( x >= this.recipe.size() )
{
currentItem = ItemStack.EMPTY;
}
@@ -228,7 +229,7 @@ public class PacketJEIRecipe extends AppEngPacket
out = Platform.poweredExtraction( energy, storage, request, cct.getActionSource() );
if( out == null )
{
if( request.getItem().isDamageable() || ( Platform.isModLoaded( "gregtech" ) && request.getItem() instanceof MetaTool ) )
if( request.getItem().isDamageable() || Platform.isGTDamageableItem( request.getItem() ) )
{
Collection<IAEItemStack> outList = inv.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).getStorageList().findFuzzy( request, FuzzyMode.IGNORE_ALL );
for( IAEItemStack is : outList )
@@ -261,7 +262,7 @@ public class PacketJEIRecipe extends AppEngPacket
if( out != null )
{
if (!cct.useRealItems())
if( !cct.useRealItems() )
{
out.setStackSize( recipe.get( x )[y].getCount() );
}
@@ -285,7 +286,7 @@ public class PacketJEIRecipe extends AppEngPacket
}
}
}
if (!cct.useRealItems())
if( !cct.useRealItems() )
{
if( currentItem.isEmpty() && recipe.size() > x && this.recipe.get( x ) != null )
{
@@ -301,24 +302,25 @@ public class PacketJEIRecipe extends AppEngPacket
if( this.output != null && ( ( con instanceof ContainerPatternTerm && !( (ContainerPatternTerm) con ).isCraftingMode() ) || con instanceof ContainerExpandedProcessingPatternTerm ) )
{
IItemHandler outputSlots = cct.getInventoryByName( "output" );
for( int i = 0; i < this.output.size(); ++i )
for( int i = 0; i < outputSlots.getSlots(); ++i )
{
if( this.output.get( i ) == null )
ItemHandlerUtil.setStackInSlot( outputSlots, i, ItemStack.EMPTY );
}
for( int i = 0; i < this.output.size() && i < outputSlots.getSlots(); ++i )
{
if( this.output.get( i ) == null || this.output.get( i ) == ItemStack.EMPTY )
{
continue;
}
ItemHandlerUtil.setStackInSlot( outputSlots, i, this.output.get( i ) );
}
}
}
}
/**
*
* @param slot
* @param is itemstack
* @param is itemstack
* @return is if it can be used, else EMPTY
*/
private ItemStack canUseInSlot( int slot, ItemStack is )
@@ -24,7 +24,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import appeng.client.gui.implementations.GuiPartOreDictStorageBus;
import appeng.client.gui.implementations.GuiOreDictStorageBus;
import appeng.container.implementations.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@@ -276,9 +276,10 @@ public class PacketValueConfig extends AppEngPacket
{
( (ContainerFluidStorageBus) c ).partition();
}
else if( c instanceof ContainerPartOreDictStorageBus )
else if( c instanceof ContainerOreDictStorageBus )
{
( (ContainerPartOreDictStorageBus) c ).partition();
( (ContainerOreDictStorageBus) c ).partition();
( (ContainerOreDictStorageBus) c ).sendRegex();
}
}
else if( this.Value.equals( "Clear" ) )
@@ -296,15 +297,15 @@ public class PacketValueConfig extends AppEngPacket
}
else if( this.Name.startsWith( "OreDictStorageBus" ) )
{
if( c instanceof ContainerPartOreDictStorageBus )
if( c instanceof ContainerOreDictStorageBus )
{
if( this.Name.equals( "OreDictStorageBus.save" ) )
{
( (ContainerPartOreDictStorageBus) c ).saveOreMatch( this.Value );
( (ContainerOreDictStorageBus) c ).saveOreMatch( this.Value );
}
if( this.Name.equals( "OreDictStorageBus.getRegex" ) )
{
( (ContainerPartOreDictStorageBus) c ).sendRegex();
( (ContainerOreDictStorageBus) c ).sendRegex();
}
}
}
@@ -387,9 +388,9 @@ public class PacketValueConfig extends AppEngPacket
else if( this.Name.equals( "OreDictStorageBus.sendRegex" ) )
{
final GuiScreen gs = Minecraft.getMinecraft().currentScreen;
if( gs instanceof GuiPartOreDictStorageBus )
if( gs instanceof GuiOreDictStorageBus )
{
( (GuiPartOreDictStorageBus) gs ).fillRegex( this.Value );
( (GuiOreDictStorageBus) gs ).fillRegex( this.Value );
}
}
else if( c instanceof IConfigurableObject )
+94 -62
View File
@@ -19,15 +19,6 @@
package appeng.crafting;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import com.google.common.base.Stopwatch;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.networking.IGrid;
@@ -36,7 +27,6 @@ import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingCallback;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingJob;
import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.security.IActionHost;
import appeng.api.networking.security.IActionSource;
import appeng.api.networking.storage.IStorageGrid;
@@ -46,56 +36,64 @@ import appeng.api.storage.data.IItemList;
import appeng.api.util.DimensionalCoord;
import appeng.core.AELog;
import appeng.hooks.TickHandler;
import appeng.me.cache.GridStorageCache;
import com.google.common.base.Stopwatch;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
public class CraftingJob implements Runnable, ICraftingJob
{
private static final String LOG_CRAFTING_JOB = "CraftingJob (%s) issued by %s requesting [%s] using %s bytes took %s ms";
private static final String LOG_CRAFTING_JOB = "CraftingJob (%s) issued by %s requesting [%s] using %s bytes took %s us";
private static final String LOG_MACHINE_SOURCE_DETAILS = "Machine[object=%s, %s]";
private final MECraftingInventory original;
private final World world;
private final IItemList<IAEItemStack> crafting = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final IItemList<IAEItemStack> missing = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final IItemList<IAEItemStack> neededForLoop = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final Object2ObjectOpenHashMap<CraftingTreeNode, IAEItemStack> reserved = new Object2ObjectOpenHashMap<>();
private final HashMap<String, TwoIntegers> opsAndMultiplier = new HashMap<>();
private final Object monitor = new Object();
private final Stopwatch watch = Stopwatch.createUnstarted();
private CraftingTreeNode tree;
private final Stopwatch tickSpreadingWatch = Stopwatch.createUnstarted();
private final Stopwatch craftingTreeWatch = Stopwatch.createUnstarted();
private final IAEItemStack output;
private final IActionSource actionSrc;
private final ICraftingCallback callback;
private CraftingTreeNode tree;
private boolean simulate = false;
private MECraftingInventory availableCheck;
private long bytes = 0;
private final IActionSource actionSrc;
private final ICraftingCallback callback;
private boolean running = false;
private boolean done = false;
private int time;
private int incTime;
private World wrapWorld( final World w )
{
return w;
}
public CraftingJob( final World w, final IGrid grid, final IActionSource actionSrc, final IAEItemStack what, final ICraftingCallback callback )
{
this.world = this.wrapWorld( w );
this.world = w;
this.output = what.copy();
this.actionSrc = actionSrc;
this.callback = callback;
final ICraftingGrid cc = grid.getCache( ICraftingGrid.class );
final IStorageGrid sg = grid.getCache( IStorageGrid.class );
this.original = new MECraftingInventory( sg
.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), actionSrc, false, false, false );
ICraftingGrid cc = grid.getCache( ICraftingGrid.class );
final GridStorageCache sg = grid.getCache( IStorageGrid.class );
this.original = sg.getExtractableList( actionSrc );
this.availableCheck = new MECraftingInventory( this.original, false, false, false );
this.setTree( this.getCraftingTree( cc, what ) );
this.availableCheck = null;
}
private CraftingTreeNode getCraftingTree( final ICraftingGrid cc, final IAEItemStack what )
{
return new CraftingTreeNode( cc, this, what, null, -1, 0 );
return new CraftingTreeNode( cc, this, what, what.getStackSize(), null, -1 );
}
void refund( final IAEItemStack o )
@@ -108,12 +106,12 @@ public class CraftingJob implements Runnable, ICraftingJob
return this.availableCheck.extractItems( available, Actionable.MODULATE, this.actionSrc );
}
public void writeToNBT( final NBTTagCompound out )
IAEItemStack checkAvailable( final IAEItemStack available )
{
return this.availableCheck.extractItems( available, Actionable.SIMULATE, this.actionSrc );
}
void addTask( IAEItemStack what, final long crafts, final ICraftingPatternDetails details, final int depth )
void addTask( IAEItemStack what, final long crafts )
{
if( crafts > 0 )
{
@@ -129,6 +127,22 @@ public class CraftingJob implements Runnable, ICraftingJob
this.missing.add( what );
}
public void reserve( CraftingTreeNode node, IAEItemStack stack )
{
this.checkUse( stack );
reserved.put( node, stack );
}
public IItemList<IAEItemStack> getNeededForLoop()
{
return neededForLoop;
}
public Object2ObjectOpenHashMap<CraftingTreeNode, IAEItemStack> getReserved()
{
return reserved;
}
@Override
public void run()
{
@@ -139,13 +153,15 @@ public class CraftingJob implements Runnable, ICraftingJob
TickHandler.INSTANCE.registerCraftingSimulation( this.world, this );
this.handlePausing();
final Stopwatch timer = Stopwatch.createStarted();
final MECraftingInventory craftingInventory = new MECraftingInventory( this.original, true, false, true );
craftingInventory.ignore( this.output );
this.availableCheck = new MECraftingInventory( this.original, false, false, false );
this.reserved.values().forEach( availableCheck::reserve );
this.reserved.values().forEach( craftingInventory::reserve );
craftingTreeWatch.start();
this.getTree().request( craftingInventory, this.output.getStackSize(), this.actionSrc );
craftingTreeWatch.stop();
this.getTree().dive( this );
for( final String s : this.opsAndMultiplier.keySet() )
@@ -154,9 +170,14 @@ public class CraftingJob implements Runnable, ICraftingJob
AELog.crafting( s + " * " + ti.times + " = " + ( ti.perOp * ti.times ) );
}
this.logCraftingJob( "real", timer );
// if ( mode == Actionable.MODULATE )
// craftingInventory.moveItemsToStorage( storage );
if( actionSrc.player().isPresent() )
{
this.logCraftingJob( "simulated, success", craftingTreeWatch );
}
else
{
this.logCraftingJob( "real, success", craftingTreeWatch );
}
}
catch( final CraftBranchFailure e )
{
@@ -164,23 +185,32 @@ public class CraftingJob implements Runnable, ICraftingJob
try
{
final Stopwatch timer = Stopwatch.createStarted();
final MECraftingInventory craftingInventory = new MECraftingInventory( this.original, true, false, true );
craftingInventory.ignore( this.output );
this.availableCheck = new MECraftingInventory( this.original, false, false, false );
this.getTree().setSimulate();
this.getTree().request( craftingInventory, this.output.getStackSize(), this.actionSrc );
this.getTree().dive( this );
for( final String s : this.opsAndMultiplier.keySet() )
if( actionSrc.player().isPresent() )
{
final TwoIntegers ti = this.opsAndMultiplier.get( s );
AELog.crafting( s + " * " + ti.times + " = " + ( ti.perOp * ti.times ) );
}
final MECraftingInventory craftingInventory = new MECraftingInventory( this.original, true, false, true );
this.getTree().setSimulate();
this.logCraftingJob( "simulate", timer );
this.availableCheck = new MECraftingInventory( this.original, false, false, false );
this.reserved.values().forEach( availableCheck::reserve );
this.reserved.values().forEach( craftingInventory::reserve );
craftingTreeWatch.reset().start();
this.getTree().request( craftingInventory, this.output.getStackSize(), this.actionSrc );
craftingTreeWatch.stop();
this.getTree().dive( this );
for( final String s : this.opsAndMultiplier.keySet() )
{
final TwoIntegers ti = this.opsAndMultiplier.get( s );
AELog.crafting( s + " * " + ti.times + " = " + ( ti.perOp * ti.times ) );
}
this.logCraftingJob( "simulated, failed", craftingTreeWatch );
}
else
{
this.logCraftingJob( "real, failed", craftingTreeWatch );
}
}
catch( final CraftBranchFailure e1 )
{
@@ -226,10 +256,11 @@ public class CraftingJob implements Runnable, ICraftingJob
this.incTime = 0;
synchronized ( this.monitor )
{
if( this.watch.elapsed( TimeUnit.MICROSECONDS ) > this.time )
if( this.tickSpreadingWatch.elapsed( TimeUnit.MICROSECONDS ) > this.time )
{
this.running = false;
this.watch.stop();
this.craftingTreeWatch.stop();
this.tickSpreadingWatch.stop();
this.monitor.notify();
}
@@ -245,12 +276,13 @@ public class CraftingJob implements Runnable, ICraftingJob
AELog.craftingDebug( "crafting job now active" );
}
}
if( Thread.interrupted() )
{
throw new InterruptedException();
}
}
if( Thread.interrupted() )
{
throw new InterruptedException();
}
this.incTime++;
}
@@ -263,7 +295,7 @@ public class CraftingJob implements Runnable, ICraftingJob
this.availableCheck = null;
synchronized( this.monitor )
synchronized ( this.monitor )
{
this.running = false;
this.done = true;
@@ -311,7 +343,7 @@ public class CraftingJob implements Runnable, ICraftingJob
/**
* @return true if this needs more simulation
*/
public boolean simulateFor(final int milli)
public boolean simulateFor( final int milli )
{
this.time = milli;
@@ -323,8 +355,8 @@ public class CraftingJob implements Runnable, ICraftingJob
}
if( !this.actionSrc.player().isPresent() )
{
this.watch.reset();
this.watch.start();
this.tickSpreadingWatch.reset();
this.tickSpreadingWatch.start();
this.monitor.notify();
}
this.running = true;
@@ -353,7 +385,7 @@ public class CraftingJob implements Runnable, ICraftingJob
if( AELog.isCraftingLogEnabled() )
{
final String itemToOutput = this.output.toString();
final long elapsedTime = timer.elapsed( TimeUnit.MILLISECONDS );
final long elapsedTime = timer.elapsed( TimeUnit.MICROSECONDS );
final String actionSource;
if( this.actionSrc.player().isPresent() )
@@ -19,15 +19,6 @@
package appeng.crafting;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.Lists;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.World;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode;
@@ -37,9 +28,22 @@ import appeng.api.networking.security.IActionSource;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketInformPlayer;
import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.util.Platform;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.Optional;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@Optional.Interface( iface = "gregtech.api.items.IToolItem", modid = "gregtech" )
public class CraftingTreeNode
{
@@ -54,22 +58,20 @@ public class CraftingTreeNode
private final IAEItemStack what;
// what are the crafting patterns for this?
private final ArrayList<CraftingTreeProcess> nodes = new ArrayList<>();
private final boolean canEmit;
private CraftingTreeNode loopHead;
private int bytes = 0;
private boolean canEmit = false;
private long missing = 0;
private long howManyEmitted = 0;
private boolean exhausted = false;
private boolean sim;
public CraftingTreeNode( final ICraftingGrid cc, final CraftingJob job, final IAEItemStack wat, final CraftingTreeProcess par, final int slot, final int depth )
public CraftingTreeNode( final ICraftingGrid cc, final CraftingJob job, final IAEItemStack wat, long amount, final CraftingTreeProcess par, final int slot )
{
this.what = wat;
this.parent = par;
this.slot = slot;
this.world = job.getWorld();
this.job = job;
this.sim = false;
this.canEmit = cc.canEmitFor( this.what );
@@ -81,108 +83,136 @@ public class CraftingTreeNode
for( final ICraftingPatternDetails details : cc.getCraftingFor( this.what, this.parent == null ? null : this.parent.details, slot, this.world ) )// in
// order.
{
if( this.parent == null || this.parent.notRecursive( details ) )
int times = 1;
for( IAEItemStack o : details.getCondensedOutputs() )
{
this.nodes.add( new CraftingTreeProcess( cc, job, details, this, depth + 1 ) );
if( what.equals( o ) )
{
times = (int) ( amount / o.getStackSize() + ( amount % o.getStackSize() != 0 ? 1 : 0 ) );
}
}
if( this.parent == null )
{
this.nodes.add( new CraftingTreeProcess( cc, job, details, times, this ) );
continue;
}
if( details == parent.details )
{
continue;
}
CraftingTreeNode recursive = recursiveNode( this );
if( recursive == null )
{
this.nodes.add( new CraftingTreeProcess( cc, job, details, times, this ) );
}
else
{
reserveForNode();
}
}
}
boolean notRecursive( final ICraftingPatternDetails details )
void reserveForNode()
{
IAEItemStack[] o = details.getCondensedOutputs();
for( final IAEItemStack i : o )
if( this.equals( loopHead ) )
{
if( i.equals( this.what ) )
{
return false;
}
return;
}
o = details.getCondensedInputs();
for( final IAEItemStack i : o )
IAEItemStack available = job.checkAvailable( this.what );
if( available != null && available.getStackSize() >= this.what.getStackSize() )
{
if( i.equals( this.what ) )
{
return false;
}
this.job.reserve( this, this.what.copy() );
}
if( this.parent == null )
else
{
return true;
parent.reserveForNode();
}
return this.parent.notRecursive( details );
}
IAEItemStack request( final MECraftingInventory inv, long l, final IActionSource src ) throws CraftBranchFailure, InterruptedException
{
this.job.handlePausing();
if( this.canEmit )
{
final IAEItemStack wat = this.what.copy();
wat.setStackSize( l );
this.howManyEmitted = wat.getStackSize();
this.bytes += wat.getStackSize();
return wat;
}
final IItemList<IAEItemStack> inventoryList = inv.getItemList();
IAEItemStack reserved = job.getReserved().get( this );
final List<IAEItemStack> thingsUsed = new ArrayList<>();
this.what.setStackSize( l );
IAEItemStack available = inv.extractItems( this.what, Actionable.MODULATE, src );
if( available != null )
if( this.getSlot() >= 0 && this.parent != null && this.parent.details.isCraftable() )
{
if( !this.exhausted )
{
final IAEItemStack is = this.job.checkUse( available );
Collection<IAEItemStack> itemList = new HashSet<>();
if( is != null )
if( this.what.getItem().isDamageable() || Platform.isGTDamageableItem( this.what.getItem() ) )
{
itemList.addAll( inventoryList.findFuzzy( this.what, FuzzyMode.IGNORE_ALL ) );
if( this.parent.details.canSubstitute() )
{
thingsUsed.add( is.copy() );
this.used.add( is );
}
}
this.bytes += available.getStackSize();
l -= available.getStackSize();
if( l == 0 )
{
return available;
}
}
else if( this.getSlot() >= 0 && this.parent != null && this.parent.details.isCraftable() )
{
final Collection<IAEItemStack> itemList;
final IItemList<IAEItemStack> inventoryList = inv.getItemList();
if( this.parent.details.canSubstitute() )
{
final List<IAEItemStack> substitutes = this.parent.details.getSubstituteInputs( this.slot );
itemList = new ArrayList<>( substitutes.size() );
for( IAEItemStack stack : substitutes )
{
itemList.addAll( inventoryList.findFuzzy( stack, FuzzyMode.IGNORE_ALL ) );
for( IAEItemStack is : inventoryList )
{
if( is.fuzzyComparison( this.what, FuzzyMode.IGNORE_ALL ) )
{
itemList.add( is );
}
}
}
}
else
{
itemList = Lists.newArrayList();
final IAEItemStack item = inventoryList.findPrecise( this.what );
if( item != null )
{
itemList.add( item );
}
if( this.parent.details.canSubstitute() )
{
for( IAEItemStack s : parent.details.getSubstituteInputs( this.slot ) )
{
if( s != null )
{
for( IAEItemStack ss : inventoryList.findFuzzy( s, FuzzyMode.IGNORE_ALL ) )
{
if( ss != null )
{
itemList.add( ss );
}
}
}
}
}
}
for( IAEItemStack fuzz : itemList )
{
if( this.parent.details.isValidItemForSlot( this.getSlot(), fuzz.copy().setStackSize( 1 ).createItemStack(), this.world ) )
if( this.parent.details.isValidItemForSlot( this.getSlot(), fuzz.getDefinition(), this.world ) )
{
fuzz = fuzz.copy();
fuzz.setStackSize( l );
available = inv.extractItems( fuzz, Actionable.MODULATE, src );
final IAEItemStack available;
if( reserved != null )
{
available = reserved;
}
else
{
available = inv.extractItems( fuzz, Actionable.MODULATE, src );
}
if( available != null )
{
@@ -195,6 +225,11 @@ public class CraftingTreeNode
thingsUsed.add( is.copy() );
this.used.add( is );
}
else if( reserved != null )
{
thingsUsed.add( reserved.copy() );
this.used.add( reserved );
}
}
this.bytes += available.getStackSize();
@@ -208,16 +243,49 @@ public class CraftingTreeNode
}
}
}
if( this.canEmit )
else
{
final IAEItemStack wat = this.what.copy();
wat.setStackSize( l );
final IAEItemStack available;
this.howManyEmitted = wat.getStackSize();
this.bytes += wat.getStackSize();
if( parent == null && this.what.equals( job.getOutput() ) )
{
available = null;
}
else if( reserved != null )
{
available = reserved;
}
else
{
available = inv.extractItems( this.what, Actionable.MODULATE, src );
}
return wat;
if( available != null )
{
if( !this.exhausted )
{
final IAEItemStack is = this.job.checkUse( available );
if( is != null )
{
thingsUsed.add( is.copy() );
this.used.add( is );
}
else if( reserved != null )
{
thingsUsed.add( reserved.copy() );
this.used.add( reserved );
}
}
this.bytes += available.getStackSize();
l -= available.getStackSize();
if( l == 0 )
{
return available;
}
}
}
this.exhausted = true;
@@ -233,8 +301,7 @@ public class CraftingTreeNode
pro.request( inv, pro.getTimes( l, madeWhat.getStackSize() ), src );
madeWhat.setStackSize( l );
available = inv.extractItems( madeWhat, Actionable.MODULATE, src );
final IAEItemStack available = inv.extractItems( madeWhat, Actionable.MODULATE, src );
if( available != null )
{
@@ -261,10 +328,12 @@ public class CraftingTreeNode
while ( pro.possible && l > 0 )
{
final MECraftingInventory subInv = new MECraftingInventory( inv, true, true, true );
pro.request( subInv, 1, src );
final IAEItemStack madeWhat = pro.getAmountCrafted( this.what );
pro.request( subInv, pro.getTimes( l, madeWhat.getStackSize() ), src );
this.what.setStackSize( l );
available = subInv.extractItems( this.what, Actionable.MODULATE, src );
final IAEItemStack available = subInv.extractItems( this.what, Actionable.MODULATE, src );
if( available != null )
{
@@ -294,10 +363,10 @@ public class CraftingTreeNode
}
}
if( this.sim )
if( job.isSimulation() )
{
this.missing += l;
this.bytes += l;
this.missing += l;
final IAEItemStack rv = this.what.copy();
rv.setStackSize( l );
return rv;
@@ -313,6 +382,26 @@ public class CraftingTreeNode
throw new CraftBranchFailure( this.what, l );
}
CraftingTreeNode recursiveNode( CraftingTreeNode node )
{
if( this.parent == null )
{
return null;
}
if( node != this )
{
if( node.what.equals( this.what ) )
{
if( node.what.getStackSize() == this.what.getStackSize() )
{
loopHead = this;
return node;
}
}
}
return this.parent.notRecursive( node );
}
void dive( final CraftingJob job )
{
if( this.missing > 0 )
@@ -338,7 +427,6 @@ public class CraftingTreeNode
void setSimulate()
{
this.sim = true;
this.missing = 0;
this.bytes = 0;
this.used.resetStatus();
@@ -360,7 +448,21 @@ public class CraftingTreeNode
{
if( src.player().isPresent() )
{
src.player().get().sendStatusMessage( new TextComponentString( "System reported " + i.getStackSize() + " " + i.getDefinition().getItem().getItemStackDisplayName( i.getDefinition() ) + " available but could not extract anything" ), false );
try
{
if( ex == null )
{
NetworkHandler.instance().sendTo( new PacketInformPlayer( i ), (EntityPlayerMP) src.player().get() );
}
else
{
NetworkHandler.instance().sendTo( new PacketInformPlayer( ex, i ), (EntityPlayerMP) src.player().get() );
}
}
catch( IOException e )
{
e.printStackTrace();
}
}
throw new CraftBranchFailure( i, i.getStackSize() );
}
@@ -19,237 +19,205 @@
package appeng.crafting;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.security.IActionSource;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.container.ContainerNull;
import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import com.google.common.collect.ImmutableCollection;
import it.unimi.dsi.fastutil.objects.Object2LongArrayMap;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
public class CraftingTreeProcess
{
private final CraftingTreeNode parent;
final ICraftingPatternDetails details;
private final CraftingTreeNode parent;
private final CraftingJob job;
private final Map<CraftingTreeNode, Long> nodes = new HashMap<>();
private final int depth;
private final Object2LongArrayMap<CraftingTreeNode> nodes = new Object2LongArrayMap<>();
boolean possible = true;
private World world;
private long crafts = 0;
private boolean containerItems;
private boolean limitQty;
private boolean fullSimulation;
private long bytes = 0;
private boolean hasContainerItem = false;
public CraftingTreeProcess( final ICraftingGrid cc, final CraftingJob job, final ICraftingPatternDetails details, final CraftingTreeNode craftingTreeNode, final int depth )
public CraftingTreeProcess( final ICraftingGrid cc, final CraftingJob job, final ICraftingPatternDetails details, int times, final CraftingTreeNode craftingTreeNode )
{
this.parent = craftingTreeNode;
this.details = details;
this.job = job;
this.depth = depth;
final World world = job.getWorld();
World world = job.getWorld();
if( details.isCraftable() )
final IAEItemStack[] list = details.getInputs();
// this is minor different then below, this slot uses the pattern, but kinda fudges it.
for( IAEItemStack part : details.getCondensedInputs() )
{
final IAEItemStack[] list = details.getInputs();
final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
final IAEItemStack[] is = details.getInputs();
for( int x = 0; x < ic.getSizeInventory(); x++ )
if( part == null )
{
ic.setInventorySlotContents( x, is[x] == null ? ItemStack.EMPTY : is[x].createItemStack() );
continue;
}
for( int x = 0; x < ic.getSizeInventory(); x++ )
for( int x = 0; x < list.length; x++ )
{
final ItemStack g = ic.getStackInSlot( x );
if( !g.isEmpty() && g.getCount() > 1 )
final IAEItemStack comparePart = list[x];
if( part.equals( comparePart ) )
{
this.fullSimulation = true;
}
}
for( final IAEItemStack part : details.getCondensedInputs() )
{
final ItemStack g = part.createItemStack();
boolean isAnInput = false;
for( final IAEItemStack a : details.getCondensedOutputs() )
{
if( !g.isEmpty() && a != null && a.equals( g ) )
boolean isPartContainer = false;
if( part.getItem().hasContainerItem( part.getDefinition() ) )
{
isAnInput = true;
part = list[x];
isPartContainer = true;
this.hasContainerItem = true;
}
}
if( isAnInput )
{
this.limitQty = true;
}
long wantedSize = isPartContainer ? part.getStackSize() : part.getStackSize() * times;
if( g.getItem().hasContainerItem( g ) )
{
this.limitQty = this.containerItems = true;
}
}
final boolean complicated = false;
if( this.containerItems || complicated )
{
for( int x = 0; x < list.length; x++ )
{
final IAEItemStack part = list[x];
if( part != null )
if( details.canSubstitute() && cc.getCraftingFor( part, details, x, world ).isEmpty() )
{
this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, x, depth + 1 ), part.getStackSize() );
}
}
}
else
{
// this is minor different then below, this slot uses the pattern, but kinda fudges it.
for( final IAEItemStack part : details.getCondensedInputs() )
{
for( int x = 0; x < list.length; x++ )
{
final IAEItemStack comparePart = list[x];
if( part != null && part.equals( comparePart ) )
for( IAEItemStack subs : details.getSubstituteInputs( x ) )
{
// use the first slot...
this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, x, depth + 1 ), part.getStackSize() );
break;
if( subs.fuzzyComparison( part, FuzzyMode.IGNORE_ALL ) )
{
this.nodes.put( new CraftingTreeNode( cc, job, subs.copy(), wantedSize, this, x ), part.getStackSize() / times );
wantedSize = 0;
break;
}
}
//try to order the crafting of a substitute
ICraftingPatternDetails prioritizedPattern = null;
IAEItemStack prioritizedIAE = null;
for( IAEItemStack subs : details.getSubstituteInputs( x ) )
{
if( subs.equals( part ) )
{
continue;
}
ImmutableCollection<ICraftingPatternDetails> detailCollection = cc.getCraftingFor( subs, details, x, world );
for( ICraftingPatternDetails sp : detailCollection )
{
if( prioritizedPattern == null )
{
prioritizedPattern = sp;
prioritizedIAE = subs;
}
else
{
if( sp.getPriority() > prioritizedPattern.getPriority() )
{
prioritizedPattern = sp;
}
}
}
if( prioritizedIAE != null )
{
this.nodes.put( new CraftingTreeNode( cc, job, prioritizedIAE.copy(), wantedSize, this, x ), part.getStackSize() / times );
wantedSize = 0;
break;
}
}
}
}
}
}
else
{
for( final IAEItemStack part : details.getCondensedInputs() )
{
final ItemStack g = part.createItemStack();
boolean isAnInput = false;
for( final IAEItemStack a : details.getCondensedOutputs() )
{
if( !g.isEmpty() && a != null && a.equals( g ) )
if( wantedSize > 0 )
{
isAnInput = true;
part = part.copy().setStackSize( wantedSize );
// use the first slot...
this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), wantedSize, this, x ), part.getStackSize() / times );
wantedSize = 0;
}
if( !isPartContainer && wantedSize == 0 )
{
break;
}
}
if( isAnInput )
{
this.limitQty = true;
}
}
for( final IAEItemStack part : details.getCondensedInputs() )
{
this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, -1, depth + 1 ), part.getStackSize() );
}
}
}
boolean notRecursive( final ICraftingPatternDetails details )
CraftingTreeNode notRecursive( CraftingTreeNode node )
{
return this.parent == null || this.parent.notRecursive( details );
if( parent == null )
{
return null;
}
return this.parent.recursiveNode( node );
}
long getTimes( final long remaining, final long stackSize )
{
if( this.limitQty || this.fullSimulation )
if( hasContainerItem )
{
return 1;
}
return ( remaining / stackSize ) + ( remaining % stackSize != 0 ? 1 : 0 );
}
void request( final MECraftingInventory inv, final long i, final IActionSource src ) throws CraftBranchFailure, InterruptedException
void request( final MECraftingInventory inv, final long amountOfTimes, final IActionSource src ) throws CraftBranchFailure, InterruptedException
{
this.job.handlePausing();
if( this.fullSimulation )
List<IAEItemStack> containerItems = null;
// request and remove inputs...
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{
final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
final IAEItemStack stack = entry.getKey().request( inv, details.isCraftable() && hasContainerItem ? 1 : entry.getValue() * amountOfTimes, src );
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.entrySet() )
if( stack.equals( job.getOutput() ) )
{
final IAEItemStack item = entry.getKey().getStack( entry.getValue() );
final IAEItemStack stack = entry.getKey().request( inv, item.getStackSize(), src );
ic.setInventorySlotContents( entry.getKey().getSlot(), stack.createItemStack() );
job.getNeededForLoop().add( stack.copy() );
}
for( int x = 0; x < ic.getSizeInventory(); x++ )
if( details.isCraftable() && stack.getItem().hasContainerItem( stack.getDefinition() ) )
{
ItemStack is = ic.getStackInSlot( x );
is = Platform.getContainerItem( is );
final IAEItemStack o = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( is );
final ItemStack is = Platform.getContainerItem( stack.createItemStack() );
final IAEItemStack o = AEItemStack.fromItemStack( is );
if( o != null )
{
this.bytes++;
inv.injectItems( o, Actionable.MODULATE, src );
}
}
}
else
{
// request and remove inputs...
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.entrySet() )
{
final IAEItemStack item = entry.getKey().getStack( entry.getValue() );
final IAEItemStack stack = entry.getKey().request( inv, item.getStackSize() * i, src );
if( this.containerItems )
{
final ItemStack is = Platform.getContainerItem( stack.createItemStack() );
final IAEItemStack o = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( is );
if( o != null )
if( containerItems == null )
{
this.bytes++;
inv.injectItems( o, Actionable.MODULATE, src );
containerItems = new ArrayList<>();
}
this.bytes++;
o.setCachedItemStack( is );
containerItems.add( o );
}
if( containerItems != null )
{
for( IAEItemStack i : containerItems )
{
inv.injectItems( i, Actionable.MODULATE, src );
}
}
}
}
// assume its possible.
// add crafting results..
for( final IAEItemStack out : this.details.getCondensedOutputs() )
{
final IAEItemStack o = out.copy();
o.setStackSize( o.getStackSize() * i );
o.setStackSize( o.getStackSize() * amountOfTimes );
inv.injectItems( o, Actionable.MODULATE, src );
}
this.crafts += i;
this.crafts += amountOfTimes;
}
void dive( final CraftingJob job )
{
job.addTask( this.getAmountCrafted( this.parent.getStack( 1 ) ), this.crafts, this.details, this.depth );
for( final CraftingTreeNode pro : this.nodes.keySet() )
job.addTask( this.getAmountCrafted( this.parent.getStack( 1 ) ), this.crafts );
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{
pro.dive( job );
entry.getKey().dive( job );
}
job.addBytes( this.crafts * 8 + this.bytes );
@@ -286,9 +254,9 @@ public class CraftingTreeProcess
this.crafts = 0;
this.bytes = 0;
for( final CraftingTreeNode pro : this.nodes.keySet() )
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{
pro.setSimulate();
entry.getKey().setSimulate();
}
}
@@ -296,9 +264,9 @@ public class CraftingTreeProcess
{
craftingCPUCluster.addCrafting( this.details, this.crafts );
for( final CraftingTreeNode pro : this.nodes.keySet() )
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{
pro.setJob( storage, craftingCPUCluster, src );
entry.getKey().setJob( storage, craftingCPUCluster, src );
}
}
@@ -311,9 +279,14 @@ public class CraftingTreeProcess
plan.addRequestable( i );
}
for( final CraftingTreeNode pro : this.nodes.keySet() )
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{
pro.getPlan( plan );
entry.getKey().getPlan( plan );
}
}
public void reserveForNode()
{
parent.reserveForNode();
}
}
@@ -28,10 +28,14 @@ import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.me.helpers.PlayerSource;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketInformPlayer;
import appeng.util.inv.ItemListIgnoreCrafting;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.text.TextComponentString;
import java.io.IOException;
public class MECraftingInventory implements IMEInventory<IAEItemStack>
{
@@ -97,8 +101,7 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
this.injectedCache = null;
}
this.localCache = this.target
.getAvailableItems( new ItemListIgnoreCrafting<>( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ) );
this.localCache = this.target.getAvailableItems( new ItemListIgnoreCrafting<>( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ) );
this.par = parent;
}
@@ -311,17 +314,23 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
{
if( src.player().isPresent() )
{
if( result == null )
try
{
src.player().get().sendStatusMessage( new TextComponentString( "System reported " + extra.getStackSize() + " " + extra.getDefinition().getItem().getItemStackDisplayName( extra.getDefinition() ) + " available but could not extract anything" ), false );
if( result == null )
{
NetworkHandler.instance().sendTo( new PacketInformPlayer( extra ), (EntityPlayerMP) src.player().get() );
}
else
{
NetworkHandler.instance().sendTo( new PacketInformPlayer( extra, result ), (EntityPlayerMP) src.player().get() );
}
}
else
catch( IOException e )
{
src.player().get().sendStatusMessage( new TextComponentString( "System reported " + extra.getStackSize() + " " + extra.getDefinition().getItem().getItemStackDisplayName( extra.getDefinition() ) + " available but could only extract " + result.getStackSize() ), false );
e.printStackTrace();
}
}
failed = true;
if( !src.player().isPresent() ) break;
}
}
}
@@ -352,11 +361,6 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
return true;
}
private void addMissing( final IAEItemStack extra )
{
this.missingCache.add( extra );
}
void ignore( final IAEItemStack what )
{
final IAEItemStack list = this.localCache.findPrecise( what );
@@ -365,4 +369,18 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
list.setStackSize( 0 );
}
}
void reserve( final IAEItemStack what )
{
final IAEItemStack list = this.localCache.findPrecise( what );
if( list != null )
{
list.decStackSize( what.getStackSize() );
}
}
private void addMissing( final IAEItemStack extra )
{
this.missingCache.add( extra );
}
}
@@ -68,7 +68,7 @@ public class GuiFluidInterface extends GuiUpgradeable implements IConfigManagerH
for( int i = 0; i < DualityFluidInterface.NUMBER_OF_TANKS; ++i )
{
this.guiSlots.add( new GuiFluidTank( fluidTank, i, DualityFluidInterface.NUMBER_OF_TANKS + i, 36 + 18 * i, 53, 16, 68 ) );
this.guiSlots.add( new GuiFluidTank( fluidTank, i, DualityFluidInterface.NUMBER_OF_TANKS + i, 36 + 18 * i, 57, 16, 64 ) );
this.guiSlots.add( new GuiFluidSlot( configFluids, i, i, 35 + 18 * i, 35 ) );
}
@@ -77,14 +77,14 @@ public class GuiFluidTank extends GuiCustomSlot implements ITooltip
TextureAtlasSprite sprite = mc.getTextureMapBlocks().getAtlasSprite( fluid.getFluid().getStill().toString() );
final int scaledHeight = (int) ( this.height * ( (float) fluid.getStackSize() / this.tank.getTankProperties()[this.slot].getCapacity() ) );
int iconHeightRemainder = scaledHeight % this.getHeight();
int iconHeightRemainder = scaledHeight % 16;
if( iconHeightRemainder > 0 )
{
this.drawTexturedModalRect( this.xPos(), this.yPos() + this.getHeight() - iconHeightRemainder, sprite, this.getWidth(), iconHeightRemainder );
this.drawTexturedModalRect( this.xPos(), this.yPos() + this.getHeight() - iconHeightRemainder, sprite, 16, iconHeightRemainder );
}
for( int i = 0; i < scaledHeight / this.getHeight(); i++ )
for( int i = 0; i < scaledHeight / 16; i++ )
{
this.drawTexturedModalRect( this.xPos(), this.yPos() + this.getHeight() - iconHeightRemainder - ( i + 1 ) * 16, sprite, this.getWidth(), this.getHeight() );
this.drawTexturedModalRect( this.xPos(), this.yPos() + this.getHeight() - iconHeightRemainder - ( i + 1 ) * 16, sprite, 16, 16 );
}
}
}
@@ -113,7 +113,7 @@ public class GuiFluidTank extends GuiCustomSlot implements ITooltip
@Override
public int yPos()
{
return this.y - 1;
return this.y - 4;
}
@Override
@@ -125,7 +125,7 @@ public class GuiFluidTank extends GuiCustomSlot implements ITooltip
@Override
public int getHeight()
{
return this.height + 1;
return this.height + 4;
}
@Override
@@ -414,7 +414,7 @@ public class ContainerFluidTerminal extends AEBaseContainer implements IConfigMa
}
}
if( notInserted == null )
if( notInserted == null || notInserted.getStackSize() == 0 )
{
if( !player.inventory.addItemStackToInventory( fh.getContainer() ) )
{
@@ -19,39 +19,6 @@
package appeng.helpers;
import java.util.*;
import javax.annotation.Nullable;
import appeng.util.inv.BlockingInventoryAdaptor;
import appeng.util.*;
import appeng.util.inv.*;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints;
import de.ellpeck.actuallyadditions.api.tile.IPhantomTile;
import gregtech.api.block.machines.BlockMachine;
import gregtech.api.metatileentity.MetaTileEntity;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Items;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.RangedWrapper;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.Settings;
@@ -75,11 +42,7 @@ import appeng.api.networking.ticking.IGridTickable;
import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest;
import appeng.api.parts.IPart;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.IStorageMonitorable;
import appeng.api.storage.IStorageMonitorableAccessor;
import appeng.api.storage.*;
import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEFluidStack;
@@ -101,23 +64,51 @@ import appeng.parts.automation.StackUpgradeInventory;
import appeng.parts.automation.UpgradeInventory;
import appeng.tile.inventory.AppEngInternalAEInventory;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost;
import appeng.util.InventoryAdaptor;
import appeng.util.Platform;
import appeng.util.inv.*;
import appeng.util.item.AEItemStack;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints;
import de.ellpeck.actuallyadditions.api.tile.IPhantomTile;
import gregtech.api.block.machines.BlockMachine;
import gregtech.api.metatileentity.MetaTileEntity;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Items;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.RangedWrapper;
import javax.annotation.Nullable;
import java.util.*;
import static gregtech.api.block.machines.BlockMachine.getMetaTileEntity;
public class DualityInterface implements IGridTickable, IStorageMonitorable, IInventoryDestination, IAEAppEngInventory, IConfigManagerHost, ICraftingProvider, IUpgradeableHost
{
private int[] failedCraftTriesSlot = {0, 0, 0, 0, 0, 0, 0, 0, 0};
public static final int NUMBER_OF_STORAGE_SLOTS = 9;
public static final int NUMBER_OF_CONFIG_SLOTS = 9;
public static final int NUMBER_OF_PATTERN_SLOTS = 36;
private static final Collection<Block> BAD_BLOCKS = new HashSet<>( 100 );
private final IAEItemStack[] requireWork = {
null, null, null, null, null, null, null, null, null
};
private final IAEItemStack[] requireWork = {null, null, null, null, null, null, null, null, null};
private final MultiCraftingTracker craftingTracker;
private final AENetworkProxy gridProxy;
private final IInterfaceHost iHost;
@@ -130,16 +121,15 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private final MEMonitorPassThrough<IAEItemStack> items = new MEMonitorPassThrough<>( new NullInventory<IAEItemStack>(), AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
private final MEMonitorPassThrough<IAEFluidStack> fluids = new MEMonitorPassThrough<>( new NullInventory<IAEFluidStack>(), AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
private final UpgradeInventory upgrades;
private final Accessor accessor = new Accessor();
private boolean hasConfig = false;
private int priority;
private List<ICraftingPatternDetails> craftingList = null;
private List<ItemStack> waitingToSend = null;
private IMEInventory<IAEItemStack> destination;
private int isWorking = -1;
private final Accessor accessor = new Accessor();
private EnumSet<EnumFacing> visitedFaces = EnumSet.noneOf( EnumFacing.class );
private EnumMap<EnumFacing, List<ItemStack>> waitingToSendFacing = new EnumMap<>( EnumFacing.class );
private BlockingInventoryAdaptor blockingInventoryAdaptor;
private boolean resetConfigCache = true;
private IMEMonitor<IAEItemStack> configCachedHandler;
@@ -163,6 +153,11 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
this.interfaceRequestSource = new InterfaceRequestSource( this.iHost );
}
private static boolean invIsCustomBlocking( BlockingInventoryAdaptor inv )
{
return ( inv.containsBlockingItems() );
}
@Override
public void saveChanges()
{
@@ -284,6 +279,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
final NBTTagCompound waitingListSided = data.getCompoundTag( "sidedWaitList" );
for( EnumFacing s : EnumFacing.values() )
{
if( waitingListSided.hasKey( s.name() ) )
{
NBTTagList w = waitingListSided.getTagList( s.name(), 10 );
@@ -297,6 +293,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
}
}
}
this.craftingTracker.readFromNBT( data );
@@ -415,6 +412,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
// :P
}
}
this.notifyNeighbors();
}
private void updateCraftingList()
@@ -427,6 +425,8 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return;
}
boolean removed = false;
if( this.craftingList != null )
{
final Iterator<ICraftingPatternDetails> i = this.craftingList.iterator();
@@ -446,26 +446,29 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
if( !found )
{
removed = true;
i.remove();
}
}
}
boolean newPattern = false;
for( int x = 0; x < accountedFor.length; x++ )
{
if( !accountedFor[x] )
{
newPattern = true;
this.addToCraftingList( this.patterns.getStackInSlot( x ) );
}
}
try
{
this.gridProxy.getGrid().postEvent( new MENetworkCraftingPatternChange( this, this.gridProxy.getNode() ) );
}
catch( final GridAccessException e )
catch( GridAccessException e )
{
// :P
e.printStackTrace();
}
}
@@ -797,17 +800,18 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return;
}
final InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() );
final Iterator<ItemStack> i = this.waitingToSendFacing.get( s ).iterator();
while ( i.hasNext() )
{
ItemStack whatToSend = i.next();
final InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() );
if( ad != null )
{
final ItemStack result = ad.addItems( whatToSend );
if( !result.isEmpty() )
{
whatToSend.setCount( whatToSend.getCount() - ( whatToSend.getCount() - result.getCount() ) );
whatToSend.setCount( result.getCount() );
}
else
{
@@ -894,9 +898,14 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
else if( itemStack.getStackSize() > 0 )
{
// make sure strange things didn't happen...
ItemStack inputStack = itemStack.createItemStack();
if( !adaptor.simulateAdd( inputStack ).isEmpty() )
ItemStack inputStack = itemStack.getCachedItemStack( itemStack.getStackSize() );
ItemStack remaining = adaptor.simulateAdd( inputStack );
if( !remaining.isEmpty() )
{
itemStack.setCachedItemStack( remaining );
changed = true;
throw new GridAccessException();
}
@@ -904,24 +913,26 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
IAEItemStack storedStack = this.gridProxy.getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).getStorageList().findPrecise( itemStack );
if( storedStack != null )
{
if( storedStack.getStackSize() > 0 )
final IAEItemStack acquired = Platform.poweredExtraction( src, this.destination, itemStack, this.interfaceRequestSource );
if( acquired != null )
{
final IAEItemStack acquired = Platform.poweredExtraction( src, this.destination, itemStack, this.interfaceRequestSource );
if( acquired != null )
changed = true;
inputStack.setCount( Ints.saturatedCast( acquired.getStackSize() ) );
final ItemStack issue = adaptor.addItems( inputStack );
if( !issue.isEmpty() )
{
changed = true;
inputStack.setCount( Ints.saturatedCast( acquired.getStackSize() ) );
final ItemStack issue = adaptor.addItems( inputStack );
if( !issue.isEmpty() )
{
throw new IllegalStateException( "bad attempt at managing inventory. ( addItems )" );
}
throw new IllegalStateException( "bad attempt at managing inventory. ( addItems )" );
}
}
else if( storedStack.isCraftable() )
{
itemStack.setCachedItemStack( inputStack );
changed = this.handleCrafting( x, adaptor, itemStack ) || changed;
}
if( acquired == null )
{
itemStack.setCachedItemStack( inputStack );
}
}
}
// else wtf?
@@ -951,20 +962,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
{
if( this.getInstalledUpgrades( Upgrades.CRAFTING ) > 0 && itemStack != null )
{
if( this.failedCraftTriesSlot[x] <= 0 )
{
boolean crafted = this.craftingTracker.handleCrafting( x, itemStack.getStackSize(), itemStack, d, this.iHost.getTileEntity().getWorld(), this.gridProxy.getGrid(), this.gridProxy.getCrafting(), this.mySource );
if( crafted )
{
this.failedCraftTriesSlot[x] = 0;
}
else
{
this.failedCraftTriesSlot[x] += 2;
}
}
this.failedCraftTriesSlot[x] -= 1;
return this.craftingTracker.handleCrafting( x, itemStack.getStackSize(), itemStack, d, this.iHost.getTileEntity().getWorld(), this.gridProxy.getGrid(), this.gridProxy.getCrafting(), this.mySource );
}
}
catch( final GridAccessException e )
@@ -1107,11 +1105,6 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return ( inv.containsItems() );
}
private static boolean invIsCustomBlocking( BlockingInventoryAdaptor inv )
{
return ( inv.containsBlockingItems() );
}
@Override
public boolean pushPattern( final ICraftingPatternDetails patternDetails, final InventoryCrafting table )
{
@@ -1161,7 +1154,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
}
final InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() );
InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() );
if( ad != null )
{
if( this.isBlocking() )
@@ -1173,7 +1166,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
if( phantomTE.hasBoundPosition() )
{
TileEntity phantom = w.getTileEntity( phantomTE.getBoundPosition() );
if( NonBlockingItems.INSTANCE.getMap().containsKey( phantom.getBlockType().getRegistryName().getResourceDomain() ) )
if( NonBlockingItems.INSTANCE.getMap().containsKey( w.getBlockState( phantomTE.getBoundPosition() ).getBlock().getRegistryName().getResourceDomain() ) )
{
if( isCustomInvBlocking( phantom, s ) )
{
@@ -1183,7 +1176,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
}
}
else if( NonBlockingItems.INSTANCE.getMap().containsKey( te.getBlockType().getRegistryName().getResourceDomain() ) )
else if( NonBlockingItems.INSTANCE.getMap().containsKey( w.getBlockState( tile.getPos().offset( s ) ).getBlock().getRegistryName().getResourceDomain() ) )
{
if( isCustomInvBlocking( te, s ) )
{
@@ -1191,7 +1184,6 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
continue;
}
}
else if( invIsBlocked( ad ) )
{
visitedFaces.remove( s );
@@ -1251,7 +1243,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
if( phantomTE.hasBoundPosition() )
{
TileEntity phantom = w.getTileEntity( phantomTE.getBoundPosition() );
if( NonBlockingItems.INSTANCE.getMap().containsKey( phantom.getBlockType().getRegistryName().getResourceDomain() ) )
if( NonBlockingItems.INSTANCE.getMap().containsKey( w.getBlockState( phantomTE.getBoundPosition() ).getBlock().getRegistryName().getResourceDomain() ) )
{
if( !isCustomInvBlocking( phantom, s ) )
{
@@ -1261,8 +1253,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
}
}
else if( NonBlockingItems.INSTANCE.getMap().containsKey( te.getBlockType().getRegistryName().getResourceDomain() ) )
else if( NonBlockingItems.INSTANCE.getMap().containsKey( w.getBlockState( tile.getPos().offset( s ) ).getBlock().getRegistryName().getResourceDomain() ) )
{
if( !isCustomInvBlocking( te, s ) )
{
@@ -1270,11 +1261,13 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
break;
}
}
else if( !invIsBlocked( ad ) )
else
{
allAreBusy = false;
break;
if( !invIsBlocked( ad ) )
{
allAreBusy = false;
break;
}
}
}
}
@@ -1285,7 +1278,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
boolean isCustomInvBlocking( TileEntity te, EnumFacing s )
{
blockingInventoryAdaptor = BlockingInventoryAdaptor.getAdaptor( te, s.getOpposite() );
BlockingInventoryAdaptor blockingInventoryAdaptor = BlockingInventoryAdaptor.getAdaptor( te, s.getOpposite() );
return invIsCustomBlocking( blockingInventoryAdaptor );
}
@@ -1309,7 +1302,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
continue;
}
if( !ad.simulateAdd( is.copy() ).isEmpty() )
if( !ad.simulateAdd( is ).isEmpty() )
{
return false;
}
@@ -1600,6 +1593,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
private class InterfaceRequestContext implements Comparable<Integer>
{
@@ -1610,6 +1604,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
}
private class InterfaceInventory extends MEMonitorIInventory
{
@@ -1647,6 +1642,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
}
private class Accessor implements IStorageMonitorableAccessor
{
@@ -24,6 +24,7 @@ import java.util.concurrent.Future;
import com.google.common.collect.ImmutableSet;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
@@ -83,57 +84,70 @@ public class MultiCraftingTracker
public boolean handleCrafting( final int x, final long itemToCraft, final IAEItemStack ais, final InventoryAdaptor d, final World w, final IGrid g, final ICraftingGrid cg, final IActionSource mySrc )
{
if( ais != null && d.simulateAdd( ais.createItemStack() ).isEmpty() )
if( ais != null )
{
final Future<ICraftingJob> craftingJob = this.getJob( x );
ItemStack inputStack = ais.getCachedItemStack( ais.getStackSize() );
if( this.getLink( x ) != null )
{
return false;
}
else if( craftingJob != null )
{
ItemStack remaining = d.simulateAdd( inputStack );
try
if( remaining.isEmpty() )
{
ais.setCachedItemStack( inputStack );
final Future<ICraftingJob> craftingJob = this.getJob( x );
if( this.getLink( x ) != null )
{
ICraftingJob job = null;
if( craftingJob.isDone() )
return false;
}
else if( craftingJob != null )
{
try
{
job = craftingJob.get();
}
if( job != null )
{
final ICraftingLink link = cg.submitJob( job, this.owner, null, false, mySrc );
this.setJob( x, null );
if( link != null )
ICraftingJob job = null;
if( craftingJob.isDone() )
{
this.setLink( x, link );
job = craftingJob.get();
}
return true;
if( job != null )
{
final ICraftingLink link = cg.submitJob( job, this.owner, null, false, mySrc );
this.setJob( x, null );
if( link != null )
{
this.setLink( x, link );
return true;
}
}
}
catch( final InterruptedException e )
{
// :P
}
catch( final ExecutionException e )
{
// :P
}
}
catch( final InterruptedException e )
else
{
// :P
}
catch( final ExecutionException e )
{
// :P
if( this.getLink( x ) == null )
{
final IAEItemStack aisC = ais.copy();
aisC.setStackSize( itemToCraft );
this.setJob( x, cg.beginCraftingJob( w, g, mySrc, aisC, null ) );
}
}
}
else
{
if( this.getLink( x ) == null )
{
final IAEItemStack aisC = ais.copy();
aisC.setStackSize( itemToCraft );
this.setJob( x, cg.beginCraftingJob( w, g, mySrc, aisC, null ) );
}
ais.setCachedItemStack( remaining );
}
}
return false;
@@ -1,74 +1,120 @@
package appeng.helpers;
import appeng.api.AEApi;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.core.AEConfig;
import appeng.core.AELog;
import appeng.util.item.AEItemStack;
import appeng.util.Platform;
import gregtech.api.items.metaitem.MetaItem;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.*;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.oredict.OreDictionary;
import java.util.*;
public class NonBlockingItems
{
public static Map<String, IItemList<IAEItemStack>> NON_BLOCKING_MAP = new HashMap<>();
public static Map<String, Object2ObjectOpenHashMap<Item, IntSet>> NON_BLOCKING_MAP = new HashMap<>();
public static NonBlockingItems INSTANCE = new NonBlockingItems();
private NonBlockingItems()
{
String[] strings = AEConfig.instance().getNonBlockingItems();
String modid = "";
String[] modids = new String[0];
if( strings.length > 0 )
{
for( String s : strings )
{
if( s.startsWith( "[" ) && s.endsWith( "]" ) )
{
modid = s.substring( 1, s.length() - 1 );
modids = s.substring( 1, s.length() - 1 ).split( "\\|" );
}
else
{
if( !Loader.isModLoaded( modid ) )
for( String modid : modids )
{
continue;
}
NON_BLOCKING_MAP.putIfAbsent( modid, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() );
String[] ModItemMeta = s.split( ":" );
if( ModItemMeta.length < 2 || ModItemMeta.length > 3 )
{
AELog.error( "Invalid non blocking item entry: " + s );
continue;
}
if( ModItemMeta[0].equals( "gregtech" ) )
{
for( MetaItem<?> metaItem : MetaItem.getMetaItems() )
if( !Loader.isModLoaded( modid ) )
{
MetaItem<?>.MetaValueItem metaItem2 = metaItem.getItem( ModItemMeta[1] );
if( metaItem.getItem( ModItemMeta[1] ) != null )
continue;
}
NON_BLOCKING_MAP.putIfAbsent( modid, new Object2ObjectOpenHashMap<>() );
String[] ModItemMeta = s.split( ":" );
if( ModItemMeta.length < 2 || ModItemMeta.length > 3 )
{
AELog.error( "Invalid non blocking item entry: " + s );
continue;
}
if( ModItemMeta[0].equals( "gregtech" ) && Platform.isModLoaded( "gregtech" ) )
{
boolean found = false;
for( MetaItem<?> metaItem : MetaItem.getMetaItems() )
{
NON_BLOCKING_MAP.get( modid ).add( AEItemStack.fromItemStack( metaItem2.getStackForm() ) );
break;
MetaItem<?>.MetaValueItem metaItem2 = metaItem.getItem( ModItemMeta[1] );
if( metaItem.getItem( ModItemMeta[1] ) != null )
{
found = true;
ItemStack itemStack = metaItem2.getStackForm();
NON_BLOCKING_MAP.get( modid ).putIfAbsent( itemStack.getItem(), new IntOpenHashSet() );
NON_BLOCKING_MAP.get( modid ).computeIfPresent( itemStack.getItem(), ( item, intSet ) ->
{
intSet.add( itemStack.getItemDamage() );
return intSet;
} );
}
else
{
ItemStack itemStack = GameRegistry.makeItemStack( ModItemMeta[0] + ":" + ModItemMeta[1], ModItemMeta.length == 3 ? Integer.parseInt( ModItemMeta[2] ) : 0, 1, null );
if( !itemStack.isEmpty() )
{
NON_BLOCKING_MAP.get( modid ).putIfAbsent( itemStack.getItem(), new IntOpenHashSet() );
NON_BLOCKING_MAP.get( modid ).computeIfPresent( itemStack.getItem(), ( item, intSet ) ->
{
intSet.add( itemStack.getItemDamage() );
return intSet;
} );
}
}
}
if( !found )
{
AELog.error( "Item not found on nonBlocking config: " + s );
}
}
}
else
{
ItemStack itemStack = GameRegistry.makeItemStack( ModItemMeta[0] + ":" + ModItemMeta[1], ModItemMeta.length == 3 ? Integer.parseInt( ModItemMeta[2] ) : 0, 1, null );
if( !itemStack.isEmpty() )
else if( ModItemMeta[0].equals( "ore" ) )
{
NON_BLOCKING_MAP.get( modid ).add( AEItemStack.fromItemStack( itemStack ) );
OreDictionary.getOres( ModItemMeta[1] ).forEach( itemStack ->
{
NON_BLOCKING_MAP.get( modid ).putIfAbsent( itemStack.getItem(), new IntOpenHashSet() );
NON_BLOCKING_MAP.get( modid ).computeIfPresent( itemStack.getItem(), ( item, intSet ) ->
{
intSet.add( itemStack.getItemDamage() );
return intSet;
} );
} );
}
else
{
AELog.error( "Item not found on nonBlocking config: " + s );
ItemStack itemStack = GameRegistry.makeItemStack( ModItemMeta[0] + ":" + ModItemMeta[1], ModItemMeta.length == 3 ? Integer.parseInt( ModItemMeta[2] ) : 0, 1, null );
if( !itemStack.isEmpty() )
{
NON_BLOCKING_MAP.get( modid ).putIfAbsent( itemStack.getItem(), new IntOpenHashSet() );
NON_BLOCKING_MAP.get( modid ).computeIfPresent( itemStack.getItem(), ( item, intSet ) ->
{
intSet.add( itemStack.getItemDamage() );
return intSet;
} );
}
else
{
AELog.error( "Item not found on nonBlocking config: " + s );
}
}
}
}
@@ -76,8 +122,12 @@ public class NonBlockingItems
}
}
public Map<String, IItemList<IAEItemStack>> getMap()
public Map<String, Object2ObjectOpenHashMap<Item, IntSet>> getMap()
{
return NON_BLOCKING_MAP;
}
public void init()
{
}
}
+54 -32
View File
@@ -40,6 +40,7 @@ import appeng.container.ContainerNull;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import net.minecraftforge.common.crafting.IShapedRecipe;
import net.minecraftforge.fml.common.Optional;
public class PatternHelper implements ICraftingPatternDetails, Comparable<PatternHelper>
@@ -247,7 +248,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
final TestStatus result = this.getStatus( slotIndex, i );
switch( result )
switch ( result )
{
case ACCEPT:
return true;
@@ -266,9 +267,11 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
this.testFrame.setInventorySlotContents( slotIndex, i );
// If we cannot substitute, the items must match exactly
if (!canSubstitute && slotIndex < inputs.length) {
if (!inputs[slotIndex].isSameType(i)) {
this.markItemAs(slotIndex, i, TestStatus.DECLINE);
if( ( !( i.getItem().isDamageable() || Platform.isGTDamageableItem( i.getItem() ) ) && !canSubstitute ) && slotIndex < inputs.length )
{
if( !inputs[slotIndex].isSameType( i ) )
{
this.markItemAs( slotIndex, i, TestStatus.DECLINE );
return false;
}
}
@@ -326,23 +329,26 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
}
@Override
public List<IAEItemStack> getSubstituteInputs(int slot) {
if (this.inputs[slot] == null) {
public List<IAEItemStack> getSubstituteInputs( int slot )
{
if( this.inputs[slot] == null )
{
return Collections.emptyList();
}
return this.substituteInputs.computeIfAbsent(slot, value -> {
ItemStack[] matchingStacks = getRecipeIngredient(slot).getMatchingStacks();
List<IAEItemStack> itemList = new ArrayList<>(matchingStacks.length + 1);
for (ItemStack matchingStack : matchingStacks) {
itemList.add(AEItemStack.fromItemStack(matchingStack));
return this.substituteInputs.computeIfAbsent( slot, value -> {
ItemStack[] matchingStacks = getRecipeIngredient( slot ).getMatchingStacks();
List<IAEItemStack> itemList = new ArrayList<>( matchingStacks.length + 1 );
for( ItemStack matchingStack : matchingStacks )
{
itemList.add( AEItemStack.fromItemStack( matchingStack ) );
}
// Ensure that the specific item put in by the user is at the beginning,
// so that it takes precedence over substitutions
itemList.add(0, this.inputs[slot]);
itemList.add( 0, this.inputs[slot] );
return itemList;
});
} );
}
/**
@@ -352,31 +358,40 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
* ingredient list will be condensed to the actual recipe's grid size. In addition, in our 3x3 grid, the user can
* shift the actual recipe input to the right and down.
*/
private Ingredient getRecipeIngredient(int slot) {
private Ingredient getRecipeIngredient( int slot )
{
if (standardRecipe instanceof IShapedRecipe ) {
if( standardRecipe instanceof IShapedRecipe )
{
IShapedRecipe shapedRecipe = (IShapedRecipe) standardRecipe;
return getShapedRecipeIngredient(slot, shapedRecipe.getRecipeWidth());
} else {
return getShapelessRecipeIngredient(slot);
return getShapedRecipeIngredient( slot, shapedRecipe.getRecipeWidth() );
}
else
{
return getShapelessRecipeIngredient( slot );
}
}
private Ingredient getShapedRecipeIngredient(int slot, int recipeWidth) {
private Ingredient getShapedRecipeIngredient( int slot, int recipeWidth )
{
// Compute the offset of the user's input vs. crafting grid origin
// Which is >0 if they have empty rows above or to the left of their input
int topOffset = 0;
if (inputs[0] == null && inputs[1] == null && inputs[2] == null) {
if( inputs[0] == null && inputs[1] == null && inputs[2] == null )
{
topOffset++; // First row is fully empty
if (inputs[3] == null && inputs[4] == null && inputs[5] == null) {
if( inputs[3] == null && inputs[4] == null && inputs[5] == null )
{
topOffset++; // Second row is fully empty
}
}
int leftOffset = 0;
if (inputs[0] == null && inputs[3] == null && inputs[6] == null) {
if( inputs[0] == null && inputs[3] == null && inputs[6] == null )
{
leftOffset++; // First column is fully empty
if (inputs[1] == null && inputs[4] == null && inputs[7] == null) {
if( inputs[1] == null && inputs[4] == null && inputs[7] == null )
{
leftOffset++; // Second column is fully empty
}
}
@@ -390,32 +405,37 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
NonNullList<Ingredient> ingredients = standardRecipe.getIngredients();
if (ingredientIndex < 0 || ingredientIndex > ingredients.size()) {
if( ingredientIndex < 0 || ingredientIndex > ingredients.size() )
{
return Ingredient.EMPTY;
}
return ingredients.get(ingredientIndex);
return ingredients.get( ingredientIndex );
}
private Ingredient getShapelessRecipeIngredient(int slot) {
private Ingredient getShapelessRecipeIngredient( int slot )
{
// We map the list of *filled* sparse inputs to the shapeless (ergo unordered)
// ingredients. While these do not actually correspond to each other,
// since both lists have the same length, the mapping is at least stable.
int ingredientIndex = 0;
for (int i = 0; i < slot; i++) {
if (inputs[i] != null) {
for( int i = 0; i < slot; i++ )
{
if( inputs[i] != null )
{
ingredientIndex++;
}
}
NonNullList<Ingredient> ingredients = standardRecipe.getIngredients();
if (ingredientIndex < ingredients.size()) {
return ingredients.get(ingredientIndex);
if( ingredientIndex < ingredients.size() )
{
return ingredients.get( ingredientIndex );
}
return Ingredient.EMPTY;
}
@Override
public ItemStack getOutput( final InventoryCrafting craftingInv, final World w )
{
@@ -517,7 +537,9 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
private enum TestStatus
{
ACCEPT, DECLINE, TEST
ACCEPT,
DECLINE,
TEST
}
private static final class TestLookup
+7 -10
View File
@@ -190,10 +190,11 @@ public class TickHandler
synchronized ( this.craftingJobs )
{
final Collection<CraftingJob> jobSet = this.craftingJobs.get( wte.world );
if (!jobSet.isEmpty()) {
if( !jobSet.isEmpty() )
{
final int jobSize = jobSet.size();
final int microSecondsPerTick = AEConfig.instance().getCraftingCalculationTimePerTick() * 1000;
final int simTime = Math.max(1, microSecondsPerTick / jobSize);
final int simTime = Math.max( 1, microSecondsPerTick / jobSize );
jobSet.removeIf( cj -> !cj.simulateFor( simTime ) );
}
@@ -206,7 +207,7 @@ public class TickHandler
this.tickColors( this.srvPlayerColors );
// ready tiles.
final HandlerRep repo = this.getRepo();
while( !repo.tiles.isEmpty() )
while ( !repo.tiles.isEmpty() )
{
final AEBaseTile bt = repo.tiles.poll();
if( !bt.isInvalid() )
@@ -238,7 +239,7 @@ public class TickHandler
private void tickColors( final HashMap<Integer, PlayerColor> playerSet )
{
final Iterator<PlayerColor> i = playerSet.values().iterator();
while( i.hasNext() )
while ( i.hasNext() )
{
final PlayerColor pc = i.next();
if( pc.ticksLeft <= 0 )
@@ -259,7 +260,7 @@ public class TickHandler
final Stopwatch sw = Stopwatch.createStarted();
IWorldCallable<?> c = null;
while( ( c = queue.poll() ) != null )
while ( ( c = queue.poll() ) != null )
{
try
{
@@ -275,15 +276,11 @@ public class TickHandler
AELog.debug( e );
}
}
// long time = sw.elapsed( TimeUnit.MILLISECONDS );
// if ( time > 0 )
// AELog.info( "processQueue Time: " + time + "ms" );
}
public void registerCraftingSimulation( final World world, final CraftingJob craftingJob )
{
synchronized( this.craftingJobs )
synchronized ( this.craftingJobs )
{
this.craftingJobs.put( world, craftingJob );
}
+69 -82
View File
@@ -74,96 +74,84 @@ public enum PartType
INVALID_TYPE( -1, "invalid", EnumSet.of( AEFeature.CORE ), EnumSet.noneOf( IntegrationType.class ), null ),
CABLE_GLASS( 0, "cable_glass", EnumSet.of( AEFeature.GLASS_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartCableGlass.class )
{
@Override
public boolean isCable()
{
return true;
}
{
@Override
public boolean isCable()
{
return true;
}
@Override
@SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName )
{
return Arrays.stream( AEColor.values() )
.map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) )
.collect( Collectors.toList() );
}
},
@Override
@SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName )
{
return Arrays.stream( AEColor.values() ).map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ).collect( Collectors.toList() );
}
},
CABLE_COVERED( 20, "cable_covered", EnumSet.of( AEFeature.COVERED_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartCableCovered.class )
{
@Override
public boolean isCable()
{
return true;
}
{
@Override
public boolean isCable()
{
return true;
}
@Override
@SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName )
{
return Arrays.stream( AEColor.values() )
.map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) )
.collect( Collectors.toList() );
}
},
@Override
@SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName )
{
return Arrays.stream( AEColor.values() ).map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ).collect( Collectors.toList() );
}
},
CABLE_SMART( 40, "cable_smart", EnumSet.of( AEFeature.CHANNELS, AEFeature.SMART_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartCableSmart.class )
{
@Override
public boolean isCable()
{
return true;
}
{
@Override
public boolean isCable()
{
return true;
}
@Override
@SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName )
{
return Arrays.stream( AEColor.values() )
.map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) )
.collect( Collectors.toList() );
}
},
@Override
@SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName )
{
return Arrays.stream( AEColor.values() ).map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ).collect( Collectors.toList() );
}
},
CABLE_DENSE_SMART( 60, "cable_dense_smart", EnumSet.of( AEFeature.CHANNELS, AEFeature.DENSE_CABLES ), EnumSet
.noneOf( IntegrationType.class ), PartDenseCableSmart.class )
{
@Override
public boolean isCable()
{
return true;
}
CABLE_DENSE_SMART( 60, "cable_dense_smart", EnumSet.of( AEFeature.CHANNELS, AEFeature.DENSE_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartDenseCableSmart.class )
{
@Override
public boolean isCable()
{
return true;
}
@Override
@SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName )
{
return Arrays.stream( AEColor.values() )
.map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) )
.collect( Collectors.toList() );
}
},
@Override
@SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName )
{
return Arrays.stream( AEColor.values() ).map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ).collect( Collectors.toList() );
}
},
CABLE_DENSE_COVERED( 500, "cable_dense_covered", EnumSet.of( AEFeature.CHANNELS, AEFeature.DENSE_CABLES ), EnumSet
.noneOf( IntegrationType.class ), PartDenseCableCovered.class )
{
@Override
public boolean isCable()
{
return true;
}
CABLE_DENSE_COVERED( 500, "cable_dense_covered", EnumSet.of( AEFeature.CHANNELS, AEFeature.DENSE_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartDenseCableCovered.class )
{
@Override
public boolean isCable()
{
return true;
}
@Override
@SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName )
{
return Arrays.stream( AEColor.values() )
.map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) )
.collect( Collectors.toList() );
}
},
@Override
@SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName )
{
return Arrays.stream( AEColor.values() ).map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ).collect( Collectors.toList() );
}
},
TOGGLE_BUS( 80, "toggle_bus", EnumSet.of( AEFeature.TOGGLE_BUS ), EnumSet.noneOf( IntegrationType.class ), PartToggleBus.class ),
@@ -282,7 +270,7 @@ public enum PartType
}
},
P2P_TUNNEL_GTCEU( 470, "p2p_tunnel_gtceu", EnumSet.of( AEFeature.P2P_TUNNEL, AEFeature.P2P_TUNNEL_GTCEU ), EnumSet.of( IntegrationType.GTCE ), PartP2PGTCEPower.class, GuiText.GTCEUTunnel )
P2P_TUNNEL_GTEU( 470, "p2p_tunnel_gteu", EnumSet.of( AEFeature.P2P_TUNNEL, AEFeature.P2P_TUNNEL_GTEU ), EnumSet.of( IntegrationType.GTCE ), PartP2PGTCEPower.class, GuiText.GTEUTunnel )
{
@Override
String getUnlocalizedName()
@@ -335,8 +323,7 @@ public enum PartType
this.oreName = oreDict;
// The part is enabled if all features + integrations it needs are enabled
this.enabled = features.stream().allMatch( AEConfig.instance()::isFeatureEnabled ) && integrations.stream()
.allMatch( IntegrationRegistry.INSTANCE::isEnabled );
this.enabled = features.stream().allMatch( AEConfig.instance()::isFeatureEnabled ) && integrations.stream().allMatch( IntegrationRegistry.INSTANCE::isEnabled );
if( this.enabled )
{
+1 -7
View File
@@ -19,12 +19,8 @@
package appeng.me;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import appeng.api.AEApi;
import appeng.api.networking.IGrid;
@@ -220,9 +216,7 @@ public class Grid implements IGrid
@Override
public MENetworkEvent postEvent( final MENetworkEvent ev )
{
CraftingGridCache.pauseRebuilds();
final MENetworkEvent ret = this.eventBus.postEvent( this, ev );
CraftingGridCache.unpauseRebuilds();
return ret;
}
+6 -9
View File
@@ -65,7 +65,7 @@ import net.minecraftforge.common.util.Constants;
public class GridNode implements IGridNode, IPathItem
{
private static final MENetworkChannelsChanged EVENT = new MENetworkChannelsChanged();
private static final int[] CHANNEL_COUNT = { 0, 8, 32 };
private static final int[] CHANNEL_COUNT = {0, 8, 32};
private final List<IGridConnection> connections = new ArrayList<>();
private final IGridBlock gridProxy;
@@ -166,8 +166,6 @@ public class GridNode implements IGridNode, IPathItem
{
final Object tracker = new Object();
CraftingGridCache.pauseRebuilds();
Deque<GridNode> nextRun = new ArrayDeque<>();
nextRun.add( this );
@@ -178,9 +176,9 @@ public class GridNode implements IGridNode, IPathItem
final Deque<IGridConnection> nextConn = new ArrayDeque<>();
final IGridConnectionVisitor gcv = (IGridConnectionVisitor) g;
while( !nextRun.isEmpty() )
while ( !nextRun.isEmpty() )
{
while( !nextConn.isEmpty() )
while ( !nextConn.isEmpty() )
{
gcv.visitConnection( nextConn.poll() );
}
@@ -196,7 +194,7 @@ public class GridNode implements IGridNode, IPathItem
}
else
{
while( !nextRun.isEmpty() )
while ( !nextRun.isEmpty() )
{
final Iterable<GridNode> thisRun = nextRun;
nextRun = new ArrayDeque<>();
@@ -207,7 +205,6 @@ public class GridNode implements IGridNode, IPathItem
}
}
}
CraftingGridCache.unpauseRebuilds();
}
@Override
@@ -269,7 +266,7 @@ public class GridNode implements IGridNode, IPathItem
@Override
public void destroy()
{
while( !this.connections.isEmpty() )
while ( !this.connections.isEmpty() )
{
// not part of this network for real anymore.
if( this.connections.size() == 1 )
@@ -378,7 +375,7 @@ public class GridNode implements IGridNode, IPathItem
@Override
public boolean meetsChannelRequirements()
{
return( !this.gridProxy.getFlags().contains( GridFlags.REQUIRE_CHANNEL ) || this.getUsedChannels() > 0 );
return ( !this.gridProxy.getFlags().contains( GridFlags.REQUIRE_CHANNEL ) || this.getUsedChannels() > 0 );
}
@Override
+34 -63
View File
@@ -113,9 +113,9 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
private final GenericInterestManager<CraftingWatcher> interestManager = new GenericInterestManager<>( this.interests );
private IStorageGrid storageGrid;
private IEnergyGrid energyGrid;
int i;
private boolean updateList = false;
private static int pauseRebuilds = 0;
private static Set<CraftingGridCache> rebuildNeeded = new HashSet<>();
private boolean updatePatterns = false;
public CraftingGridCache( final IGrid grid )
{
@@ -140,8 +140,14 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
this.updateCPUClusters();
}
if( updatePatterns )
{
this.recalculateCraftingPatterns();
this.updatePatterns = false;
}
final Iterator<CraftingLinkNexus> craftingLinkIterator = this.craftingLinks.values().iterator();
while( craftingLinkIterator.hasNext() )
while ( craftingLinkIterator.hasNext() )
{
if( craftingLinkIterator.next().isDead( this.grid, this ) )
{
@@ -187,7 +193,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
if( machine instanceof ICraftingProvider )
{
this.craftingProviders.remove( machine );
this.updatePatterns();
this.updatePatterns = true;
}
}
@@ -221,7 +227,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
if( machine instanceof ICraftingProvider )
{
this.craftingProviders.add( (ICraftingProvider) machine );
this.updatePatterns();
this.updatePatterns = true;
}
}
@@ -242,36 +248,15 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
// nothing!
}
public static void pauseRebuilds()
{
pauseRebuilds++;
}
public static void unpauseRebuilds()
{
pauseRebuilds--;
if (pauseRebuilds == 0 && rebuildNeeded.size() > 0)
{
ImmutableSet<CraftingGridCache> needed = ImmutableSet.copyOf(rebuildNeeded);
rebuildNeeded.clear();
for ( CraftingGridCache cache: needed )
{
cache.updatePatterns();
}
}
}
private void updatePatterns()
{
// coalesce change events during a grid traversal to a single rebuild
if (pauseRebuilds != 0)
{
rebuildNeeded.add(this);
return;
}
this.updatePatterns = true;
}
final Object2ObjectMap<IAEItemStack, ImmutableList<ICraftingPatternDetails>> oldItems = new Object2ObjectOpenHashMap<>(this.craftableItems);
final Set<IAEItemStack> oldEmitableItems = new HashSet<>(this.emitableItems);
private void recalculateCraftingPatterns()
{
final Object2ObjectMap<IAEItemStack, ImmutableList<ICraftingPatternDetails>> oldItems = new Object2ObjectOpenHashMap<>( this.craftableItems );
final Set<IAEItemStack> oldEmitableItems = new HashSet<>( this.emitableItems );
// erase list.
this.craftingMethods.clear();
@@ -312,25 +297,29 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
this.craftableItems.put( e.getKey(), ImmutableList.copyOf( e.getValue() ) );
}
Object2ObjectMap<IAEItemStack, ImmutableList<ICraftingPatternDetails>> craftablesChanged = new Object2ObjectArrayMap<>();
List<IAEItemStack> craftablesChanged = new ArrayList<>();
ObjectSet<Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>>> i = oldItems.entrySet();
for ( Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>> ais : i) {
if (!this.craftableItems.containsKey( ais.getKey() )) {
for( Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>> ais : i )
{
if( !this.craftableItems.containsKey( ais.getKey() ) )
{
IAEItemStack changedStack = ais.getKey().copy();
changedStack.reset();
changedStack.setCraftable( false );
craftablesChanged.put( changedStack, ais.getValue() );
craftablesChanged.add( changedStack );
}
}
ObjectSet<Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>>> j = this.craftableItems.entrySet();
for ( Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>> ais : j) {
if (!oldItems.containsKey( ais )){
for( Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>> ais : j )
{
if( !oldItems.containsKey( ais ) )
{
IAEItemStack changedStack = ais.getKey().copy();
changedStack.reset();
changedStack.setCraftable( true );
craftablesChanged.put( changedStack, ais.getValue() );
craftablesChanged.add( changedStack );
}
}
@@ -341,7 +330,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
IAEItemStack changedStack = st.copy();
changedStack.reset();
changedStack.setCraftable( false );
craftablesChanged.put( changedStack, null );
craftablesChanged.add( changedStack );
}
}
@@ -352,12 +341,11 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
IAEItemStack changedStack = st.copy();
changedStack.reset();
changedStack.setCraftable( true );
craftablesChanged.put( changedStack, null );
craftablesChanged.add( changedStack );
}
}
this.storageGrid.postCraftablesChanges( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), craftablesChanged.keySet(),
new BaseActionSource() );
this.storageGrid.postCraftablesChanges( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), craftablesChanged, new BaseActionSource() );
}
private void updateCPUClusters()
@@ -535,22 +523,6 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
if( res == null )
{
if( details != null && details.isCraftable() )
{
for( final IAEItemStack ais : this.craftableItems.keySet() )
{
if( ais.getItem() == whatToCraft.getItem() && ( !ais.getItem().getHasSubtypes() || ais.getItemDamage() == whatToCraft.getItemDamage() ) )
{
// TODO: check if OK
// TODO: this is slightly hacky, but fine as long as we only deal with itemstacks
if( details.isValidItemForSlot( slotIndex, ais.asItemStackRepresentation(), world ) )
{
return this.craftableItems.get( ais );
}
}
}
}
return ImmutableSet.of();
}
@@ -596,8 +568,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
}
}
Collections.sort( validCpusClusters, ( firstCluster, nextCluster ) ->
{
Collections.sort( validCpusClusters, ( firstCluster, nextCluster ) -> {
if( prioritizePower )
{
final int comparison1 = Long.compare( nextCluster.getCoProcessors(), firstCluster.getCoProcessors() );
@@ -676,7 +647,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
public boolean hasCpu( final ICraftingCPU cpu )
{
if (cpu instanceof CraftingCPUCluster)
if( cpu instanceof CraftingCPUCluster )
{
return this.craftingCPUClusters.contains( (CraftingCPUCluster) cpu );
}
@@ -710,7 +681,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
private void findNext()
{
while( this.iterator.hasNext() && this.cpuCluster == null )
while ( this.iterator.hasNext() && this.cpuCluster == null )
{
this.cpuCluster = this.iterator.next();
if( !this.cpuCluster.isActive() || this.cpuCluster.isDestroyed() )
+34 -8
View File
@@ -19,13 +19,12 @@
package appeng.me.cache;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.crafting.MECraftingInventory;
import appeng.helpers.IInterfaceHost;
import appeng.helpers.IPriorityHost;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
@@ -55,6 +54,8 @@ import appeng.me.helpers.GenericInterestManager;
import appeng.me.helpers.MachineSource;
import appeng.me.storage.ItemWatcher;
import appeng.me.storage.NetworkInventoryHandler;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class GridStorageCache implements IStorageGrid
@@ -68,6 +69,8 @@ public class GridStorageCache implements IStorageGrid
private final HashMap<IGridNode, IStackWatcher> watchers = new HashMap<>();
private final Map<IStorageChannel<? extends IAEStack>, NetworkInventoryHandler<?>> storageNetworks;
private final Map<IStorageChannel<? extends IAEStack>, NetworkMonitor<?>> storageMonitors;
private MECraftingInventory localCache = null;
private final Int2ObjectMap<MECraftingInventory> extractableItemPriorityMap = new Int2ObjectOpenHashMap<>();
private int localDepth;
public GridStorageCache( final IGrid g )
@@ -82,6 +85,8 @@ public class GridStorageCache implements IStorageGrid
@Override
public void onUpdateTick()
{
this.localCache = null;
this.extractableItemPriorityMap.clear();
this.storageMonitors.forEach( ( channel, monitor ) -> monitor.onTick() );
}
@@ -169,6 +174,28 @@ public class GridStorageCache implements IStorageGrid
return (IMEMonitor<T>) this.storageMonitors.get( channel );
}
public MECraftingInventory getExtractableList( IActionSource src )
{
if( src instanceof MachineSource )
{
if( src.machine().isPresent() )
{
IActionHost machine = src.machine().get();
if( machine instanceof IInterfaceHost )
{
extractableItemPriorityMap.putIfAbsent( ( (IPriorityHost) machine ).getPriority(), new MECraftingInventory( getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), src, false, false, false ) );
return extractableItemPriorityMap.get( ( (IPriorityHost) machine ).getPriority() );
}
}
}
if( localCache == null )
{
localCache = new MECraftingInventory( getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), src, false, false, false );
}
return localCache;
}
private CellChangeTracker addCellProvider( final ICellProvider cc, final CellChangeTracker tracker )
{
if( this.inactiveCellProviders.contains( cc ) )
@@ -198,8 +225,7 @@ public class GridStorageCache implements IStorageGrid
final IActionSource actionSrc = cc instanceof IActionHost ? new MachineSource( (IActionHost) cc ) : new BaseActionSource();
this.storageMonitors.forEach( ( channel, monitor ) ->
{
this.storageMonitors.forEach( ( channel, monitor ) -> {
for( final IMEInventoryHandler<IAEItemStack> h : cc.getCellArray( channel ) )
{
tracker.postChanges( channel, -1, h, actionSrc );
@@ -19,22 +19,6 @@
package appeng.me.cluster.implementations;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import appeng.api.config.Upgrades;
import appeng.helpers.DualityInterface;
import appeng.helpers.PatternHelper;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.world.World;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode;
@@ -43,14 +27,7 @@ import appeng.api.implementations.ICraftingPatternItem;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.CraftingItemList;
import appeng.api.networking.crafting.ICraftingCPU;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingJob;
import appeng.api.networking.crafting.ICraftingLink;
import appeng.api.networking.crafting.ICraftingMedium;
import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.crafting.ICraftingRequester;
import appeng.api.networking.crafting.*;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.events.MENetworkCraftingCpuChange;
import appeng.api.networking.security.IActionSource;
@@ -63,11 +40,8 @@ import appeng.api.storage.data.IItemList;
import appeng.api.util.WorldCoord;
import appeng.container.ContainerNull;
import appeng.core.AELog;
import appeng.crafting.CraftBranchFailure;
import appeng.crafting.CraftingJob;
import appeng.crafting.CraftingLink;
import appeng.crafting.CraftingWatcher;
import appeng.crafting.MECraftingInventory;
import appeng.crafting.*;
import appeng.helpers.PatternHelper;
import appeng.me.cache.CraftingGridCache;
import appeng.me.cluster.IAECluster;
import appeng.me.helpers.MachineSource;
@@ -75,6 +49,17 @@ import appeng.tile.crafting.TileCraftingMonitorTile;
import appeng.tile.crafting.TileCraftingTile;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.world.World;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
@@ -102,6 +87,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
private IAEItemStack finalOutput;
private boolean waiting = false;
private IItemList<IAEItemStack> waitingFor = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private IItemList<IAEItemStack> neededForLoop = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private long availableStorage = 0;
private MachineSource machineSrc = null;
private int accelerator = 0;
@@ -224,13 +210,10 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
public boolean canAccept( final IAEItemStack input )
{
if( input instanceof IAEItemStack )
if( input != null )
{
final IAEItemStack is = this.waitingFor.findPrecise( input );
if( is != null && is.getStackSize() > 0 )
{
return true;
}
return is != null && is.getStackSize() > 0;
}
return false;
}
@@ -239,7 +222,8 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{
// also stop accepting items when the job is complete, i.e. to prevent re-insertion when pushing out
// items during storeItems
if (input == null || isComplete) {
if( input == null || isComplete )
{
return input;
}
@@ -303,9 +287,28 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
if( this.finalOutput.equals( what ) )
{
IAEItemStack isLoop = neededForLoop.findPrecise( finalOutput );
IAEItemStack leftover = what;
this.finalOutput.decStackSize( what.getStackSize() );
if( isLoop != null && isLoop.getStackSize() > 0 )
{
if( isLoop.getStackSize() >= what.getStackSize() )
{
leftover = this.inventory.injectItems( what.copy(), type, src );
isLoop.decStackSize( what.getStackSize() );
}
else
{
leftover = this.inventory.injectItems( what.copy().setStackSize( what.getStackSize() - isLoop.getStackSize() ), type, src );
isLoop.decStackSize( what.getStackSize() - isLoop.getStackSize() );
}
if( leftover == null )
{
return null;
}
}
this.finalOutput.decStackSize( leftover.getStackSize() );
if( this.myLastLink != null )
{
@@ -335,9 +338,28 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
if( this.finalOutput.equals( insert ) )
{
IAEItemStack isLoop = neededForLoop.findPrecise( finalOutput );
IAEItemStack leftover = input;
this.finalOutput.decStackSize( insert.getStackSize() );
if( isLoop != null && isLoop.getStackSize() > 0 )
{
if( isLoop.getStackSize() >= insert.getStackSize() )
{
leftover = this.inventory.injectItems( insert.copy(), type, src );
isLoop.decStackSize( insert.getStackSize() );
}
else
{
leftover = this.inventory.injectItems( insert.copy().setStackSize( insert.getStackSize() - isLoop.getStackSize() ), type, src );
isLoop.decStackSize( insert.getStackSize() - isLoop.getStackSize() );
}
if( leftover == null )
{
return null;
}
}
this.finalOutput.decStackSize( leftover.getStackSize() );
if( this.myLastLink != null )
{
@@ -375,7 +397,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{
final ImmutableList<IAEItemStack> single = ImmutableList.of( diff.copy() );
while( i.hasNext() )
while ( i.hasNext() )
{
final Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> o = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> receiver = o.getKey();
@@ -495,15 +517,14 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
return null;
}
private boolean canCraft(final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs)
private boolean canCraft( final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs )
{
if( !details.isCraftable() )
{
// Processing patterns are relatively easy
for ( IAEItemStack input : condensedInputs )
for( IAEItemStack input : condensedInputs )
{
final IAEItemStack ais = this.inventory.extractItems( input.copy(), Actionable.SIMULATE,
this.machineSrc );
final IAEItemStack ais = this.inventory.extractItems( input.copy(), Actionable.SIMULATE, this.machineSrc );
if( ais == null || ais.getStackSize() < input.getStackSize() )
{
@@ -516,7 +537,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
// When substitutions are allowed, we have to keep track of which items we've reserved
IAEItemStack[] inputs = details.getInputs();
Map<IAEItemStack, Integer> consumedCount = new HashMap<>();
for ( int i = 0; i < inputs.length; i++ )
for( int i = 0; i < inputs.length; i++ )
{
List<IAEItemStack> substitutes = details.getSubstituteInputs( i );
if( substitutes.isEmpty() )
@@ -525,9 +546,9 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
}
boolean found = false;
for ( IAEItemStack substitute : substitutes )
for( IAEItemStack substitute : substitutes )
{
for ( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( substitute, FuzzyMode.IGNORE_ALL ) )
for( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( substitute, FuzzyMode.IGNORE_ALL ) )
{
int alreadyConsumed = consumedCount.getOrDefault( fuzz, 0 );
if( fuzz.getStackSize() - alreadyConsumed <= 0 )
@@ -537,8 +558,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
fuzz = fuzz.copy();
fuzz.setStackSize( 1 ); // We're iterating over non condensed inputs which means there's 1 of each needed
final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.SIMULATE,
this.machineSrc );
final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.SIMULATE, this.machineSrc );
if( ais != null && ais.getStackSize() > 0 )
{
@@ -565,11 +585,11 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{
// When no substitutions can occur, we can simply check that all items are accounted since
// each type of item should only occur once
for ( IAEItemStack g : condensedInputs )
for( IAEItemStack g : condensedInputs )
{
boolean found = false;
for ( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( g, FuzzyMode.IGNORE_ALL ) )
for( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( g, FuzzyMode.IGNORE_ALL ) )
{
fuzz = fuzz.copy();
fuzz.setStackSize( g.getStackSize() );
@@ -675,8 +695,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{
this.somethingChanged = false;
this.executeCrafting( eg, cc );
}
while( this.somethingChanged && this.remainingOperations > 0 );
} while ( this.somethingChanged && this.remainingOperations > 0 );
}
this.usedOps[2] = this.usedOps[1];
this.usedOps[1] = this.usedOps[0];
@@ -692,7 +711,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{
final Iterator<Entry<ICraftingPatternDetails, TaskProgress>> i = this.tasks.entrySet().iterator();
while( i.hasNext() )
while ( i.hasNext() )
{
final Entry<ICraftingPatternDetails, TaskProgress> e = i.next();
@@ -708,12 +727,12 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{
InventoryCrafting ic = null;
if (!visitedMediums.containsKey( details ) || visitedMediums.get( details ).isEmpty())
if( !visitedMediums.containsKey( details ) || visitedMediums.get( details ).isEmpty() )
{
visitedMediums.put( details, new ArrayDeque<>( cc.getMediums( details ).stream().filter( Objects::nonNull ).collect( Collectors.toList()) ) );
visitedMediums.put( details, new ArrayDeque<>( cc.getMediums( details ).stream().filter( Objects::nonNull ).collect( Collectors.toList() ) ) );
}
while (!visitedMediums.get( details ).isEmpty())
while ( !visitedMediums.get( details ).isEmpty() )
{
ICraftingMedium m = visitedMediums.get( details ).poll();
@@ -773,52 +792,58 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{
itemList.addAll( this.inventory.getItemList().findFuzzy( stack, FuzzyMode.IGNORE_ALL ) );
}
} else {
itemList = new ArrayList<>(1);
}
else
{
itemList = new ArrayList<>( 1 );
final IAEItemStack item = this.inventory.getItemList()
.findPrecise(input[x]);
final IAEItemStack item = this.inventory.getItemList().findPrecise( input[x] );
if (item != null) {
itemList.add(item);
if( item != null )
{
itemList.add( item );
}
}
for (IAEItemStack fuzz : itemList) {
for( IAEItemStack fuzz : itemList )
{
fuzz = fuzz.copy();
fuzz.setStackSize(input[x].getStackSize());
fuzz.setStackSize( input[x].getStackSize() );
if (details.isValidItemForSlot(x, fuzz.createItemStack(),
this.getWorld())) {
final IAEItemStack ais = this.inventory.extractItems(fuzz,
Actionable.MODULATE, this.machineSrc);
final ItemStack is = ais == null ? ItemStack.EMPTY
: ais.createItemStack();
if( details.isValidItemForSlot( x, fuzz.createItemStack(), this.getWorld() ) )
{
final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.MODULATE, this.machineSrc );
final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack();
if (!is.isEmpty()) {
this.postChange(AEItemStack.fromItemStack(is), this.machineSrc);
ic.setInventorySlotContents(x, is);
if( !is.isEmpty() )
{
this.postChange( AEItemStack.fromItemStack( is ), this.machineSrc );
ic.setInventorySlotContents( x, is );
found = true;
break;
}
}
}
} else {
final IAEItemStack ais = this.inventory.extractItems(input[x].copy(),
Actionable.MODULATE, this.machineSrc);
}
else
{
final IAEItemStack ais = this.inventory.extractItems( input[x].copy(), Actionable.MODULATE, this.machineSrc );
final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack();
if (!is.isEmpty()) {
this.postChange(input[x], this.machineSrc);
ic.setInventorySlotContents(x, is);
if (is.getCount() == input[x].getStackSize()) {
if( !is.isEmpty() )
{
this.postChange( input[x], this.machineSrc );
ic.setInventorySlotContents( x, is );
if( is.getCount() == input[x].getStackSize() )
{
found = true;
continue;
}
}
}
if (!found) {
if( !found )
{
break;
}
}
@@ -902,7 +927,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
private void storeItems()
{
Preconditions.checkState(isComplete, "CPU should be complete to prevent re-insertion when dumping items");
Preconditions.checkState( isComplete, "CPU should be complete to prevent re-insertion when dumping items" );
final IGrid g = this.getGrid();
if( g == null )
@@ -962,10 +987,12 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
try
{
this.waitingFor.resetStatus();
this.neededForLoop.resetStatus();
( (CraftingJob) job ).getTree().setJob( ci, this, src );
if( ci.commit( src ) )
{
this.finalOutput = job.getOutput();
this.neededForLoop = ( (CraftingJob) job ).getNeededForLoop();
this.waiting = false;
this.isComplete = false;
this.markDirty();
@@ -1016,8 +1043,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
public boolean isBusy()
{
this.tasks.entrySet().removeIf(
taskProgressEntry -> taskProgressEntry.getValue().value <= 0 );
this.tasks.entrySet().removeIf( taskProgressEntry -> taskProgressEntry.getValue().value <= 0 );
if( !this.waitingFor.isEmpty() || !this.tasks.isEmpty() )
{
@@ -1075,8 +1101,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
final int hash = System.identityHashCode( this );
final int hmm = this.finalOutput == null ? 0 : this.finalOutput.hashCode();
return Long.toString( now, Character.MAX_RADIX ) + '-' + Integer.toString( hash, Character.MAX_RADIX ) + '-' + Integer.toString( hmm,
Character.MAX_RADIX );
return Long.toString( now, Character.MAX_RADIX ) + '-' + Integer.toString( hash, Character.MAX_RADIX ) + '-' + Integer.toString( hmm, Character.MAX_RADIX );
}
private NBTTagCompound generateLinkData( final String craftingID, final boolean standalone, final boolean req )
@@ -1103,7 +1128,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
public void getListOfItem( final IItemList<IAEItemStack> list, final CraftingItemList whichList )
{
switch( whichList )
switch ( whichList )
{
case ACTIVE:
for( final IAEItemStack ais : this.waitingFor )
@@ -1174,7 +1199,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{
IAEItemStack is;
switch( storage2 )
switch ( storage2 )
{
case STORAGE:
is = this.inventory.getItemList().findPrecise( what );
@@ -19,7 +19,6 @@
package appeng.parts.automation;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -72,8 +71,6 @@ import appeng.util.item.AEItemStack;
public class PartExportBus extends PartSharedItemBus implements ICraftingRequester
{
private final int[] failedCraftTriesSlot = {0, 0, 0, 0, 0, 0, 0, 0, 0};
public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "part/export_bus_base" );
@PartModels
@@ -156,22 +153,8 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
if( this.craftOnly() )
{
if( this.failedCraftTriesSlot[x] <= 0 )
{
this.didSomething = this.craftingTracker.handleCrafting( slotToExport, this.itemToSend, ais, destination, this.getTile().getWorld(), this.getProxy().getGrid(), cg, this.mySrc ) || this.didSomething;
this.didSomething = this.craftingTracker.handleCrafting( slotToExport, this.itemToSend, ais, destination, this.getTile().getWorld(), this.getProxy().getGrid(), cg, this.mySrc ) || this.didSomething;
if( this.didSomething )
{
this.failedCraftTriesSlot[x] = 0;
}
else
{
this.failedCraftTriesSlot[x] += 2;
}
}
this.failedCraftTriesSlot[x] -= 1;
continue;
}
final long before = this.itemToSend;
@@ -197,21 +180,7 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
if( this.itemToSend == before && this.isCraftingEnabled() )
{
if( this.failedCraftTriesSlot[x] <= 0 )
{
this.didSomething = this.craftingTracker.handleCrafting( slotToExport, this.itemToSend, ais, destination, this.getTile().getWorld(), this.getProxy().getGrid(), cg, this.mySrc ) || this.didSomething;
if( this.didSomething )
{
this.failedCraftTriesSlot[x] = 0;
}
else
{
this.failedCraftTriesSlot[x] += 2;
}
}
this.failedCraftTriesSlot[x] -= 1;
this.didSomething = this.craftingTracker.handleCrafting( slotToExport, this.itemToSend, ais, destination, this.getTile().getWorld(), this.getProxy().getGrid(), cg, this.mySrc ) || this.didSomething;
}
}
@@ -297,15 +266,18 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
ItemStack remaining;
remaining = mode == Actionable.SIMULATE ? d.simulateAdd( inputStack ) : d.addItems( inputStack );
if( !remaining.isEmpty() )
if( mode == Actionable.SIMULATE )
{
items.setCachedItemStack( remaining );
remaining = d.simulateAdd( inputStack );
items.setCachedItemStack( inputStack );
}
else
{
items.setCachedItemStack( inputStack );
remaining = d.addItems( inputStack );
if( !remaining.isEmpty() )
{
items.setCachedItemStack( remaining );
}
}
if( remaining == inputStack )
@@ -357,10 +329,10 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
if( !remaining.isEmpty() )
{
ais.setCachedItemStack( remaining );
}
else
{
ais.setCachedItemStack( inputStack );
if( remaining == inputStack )
{
return;
}
}
final long canFit = remaining.isEmpty() ? this.itemToSend : this.itemToSend - remaining.getCount();
@@ -19,7 +19,6 @@
package appeng.parts.misc;
import javax.annotation.Nullable;
import appeng.api.AEApi;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
@@ -91,13 +90,16 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
}
// Store the stack in the cache for next time.
if( !remaining.isEmpty() )
if( type == Actionable.SIMULATE )
{
iox.setCachedItemStack( remaining );
iox.setCachedItemStack( inputStack );
}
else
{
iox.setCachedItemStack( inputStack );
if( !remaining.isEmpty() )
{
iox.setCachedItemStack( remaining );
}
}
// At this point, we still have some items left...
@@ -134,7 +136,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
ItemStack gathered = ItemStack.EMPTY;
final boolean simulate = ( mode == Actionable.SIMULATE );
for ( int i = 0; i < this.itemHandler.getSlots(); i++ )
for( int i = 0; i < this.itemHandler.getSlots(); i++ )
{
ItemStack stackInInventorySlot = this.itemHandler.getStackInSlot( i );
@@ -144,6 +146,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
}
ItemStack extracted;
int stackSizeCurrentSlot = stackInInventorySlot.getCount();
int remainingCurrentSlot = Math.min( remainingSize, stackSizeCurrentSlot );
@@ -152,24 +155,36 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
do
{
extracted = this.itemHandler.extractItem( i, remainingCurrentSlot, simulate );
if( !extracted.isEmpty() )
{
// In order to guard against broken IItemHandler implementations, we'll try to guess if the returned
// stack (especially in simulate mode) is the same that was returned by getStackInSlot. This is
// obviously not a precise science, but it would catch the previous Forge bug:
// https://github.com/MinecraftForge/MinecraftForge/pull/6580
if( extracted == stackInInventorySlot )
{
extracted = extracted.copy();
}
if( extracted.getCount() > remainingCurrentSlot )
{
// Something broke. It should never return more than we requested...
// We're going to silently eat the remainder
AELog.warn( "Mod that provided item handler %s is broken. Returned %s items while only requesting %d.",
this.itemHandler.getClass().getName(), extracted.toString(), remainingCurrentSlot );
AELog.warn( "Mod that provided item handler %s is broken. Returned %s items while only requesting %d.", this.itemHandler.getClass().getName(), extracted.toString(), remainingCurrentSlot );
extracted.setCount( remainingCurrentSlot );
}
// Heuristic for simulation: looping in case of simulations is pointless, since the state of the
// underlying inventory does not change after a simulated extraction. To still support inventories
// that report stacks that are larger than maxStackSize, we use this heuristic
if( simulate && extracted.getCount() == extracted.getMaxStackSize() && remainingCurrentSlot > extracted.getMaxStackSize() )
{
extracted.setCount( remainingCurrentSlot );
}
// We're just gonna use the first stack we get our hands on as the template for the rest.
// In case some stupid itemhandler (aka forge) returns an internal state we have to do a second
// expensive copy again.
if( gathered.isEmpty() )
{
gathered = extracted.copy();
gathered = extracted;
}
else
{
@@ -177,11 +192,9 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
}
remainingCurrentSlot -= extracted.getCount();
}
} while ( !extracted.isEmpty() && remainingCurrentSlot > 0 );
} while ( !simulate && !extracted.isEmpty() && remainingCurrentSlot > 0 );
remainingSize -= stackSizeCurrentSlot - remainingCurrentSlot;
// Done?
if( remainingSize <= 0 )
{
break;
@@ -316,17 +329,17 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
currentlyOnStorage.add( is.getAEItemStack() );
}
for ( final IAEItemStack is : currentlyCached )
for( final IAEItemStack is : currentlyCached )
{
is.setStackSize( -is.getStackSize() );
}
for ( final IAEItemStack is : currentlyOnStorage )
for( final IAEItemStack is : currentlyOnStorage )
{
currentlyCached.add( is );
}
for ( final IAEItemStack is : currentlyCached )
for( final IAEItemStack is : currentlyCached )
{
if( is.getStackSize() != 0 )
{
@@ -35,223 +35,225 @@ import java.util.*;
class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor
{
private final Object2ObjectMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new Object2ObjectOpenHashMap<>();
private IActionSource mySource;
private final IItemRepository itemRepository;
private final IGridProxyable proxyable;
private final InventoryCache cache;
private AccessRestriction access;
private final Object2ObjectMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new Object2ObjectOpenHashMap<>();
private IActionSource mySource;
private final IItemRepository itemRepository;
private final IGridProxyable proxyable;
private final InventoryCache cache;
private AccessRestriction access;
ItemRepositoryAdapter( IItemRepository itemRepository, IGridProxyable proxy )
{
this.itemRepository = itemRepository;
this.proxyable = proxy;
this.cache = new InventoryCache( this.itemRepository );
if( this.proxyable instanceof PartStorageBus )
{
PartStorageBus partStorageBus = (PartStorageBus) this.proxyable;
this.access = ( (AccessRestriction) partStorageBus.getConfigManager().getSetting( Settings.ACCESS ) );
}
this.cache.update();
}
ItemRepositoryAdapter( IItemRepository itemRepository, IGridProxyable proxy )
{
this.itemRepository = itemRepository;
this.proxyable = proxy;
this.cache = new InventoryCache( this.itemRepository );
if( this.proxyable instanceof PartStorageBus )
{
PartStorageBus partStorageBus = (PartStorageBus) this.proxyable;
this.access = ( (AccessRestriction) partStorageBus.getConfigManager().getSetting( Settings.ACCESS ) );
}
this.cache.update();
}
@Override
public IAEItemStack injectItems( IAEItemStack iox, Actionable type, IActionSource src )
{
// Try to reuse the cached stack
ItemStack inputStack = iox.getCachedItemStack( iox.getStackSize() );
@Override
public IAEItemStack injectItems( IAEItemStack iox, Actionable type, IActionSource src )
{
// Try to reuse the cached stack
ItemStack inputStack = iox.getCachedItemStack( iox.getStackSize() );
ItemStack remaining;
ItemStack remaining;
remaining = this.itemRepository.insertItem( inputStack, type == Actionable.SIMULATE );
remaining = this.itemRepository.insertItem( inputStack, type == Actionable.SIMULATE );
// Store the stack in the cache for next time.
if( !remaining.isEmpty() )
{
iox.setCachedItemStack( remaining );
}
else
{
iox.setCachedItemStack( inputStack );
}
// Store the stack in the cache for next time.
if( type == Actionable.SIMULATE )
{
iox.setCachedItemStack( inputStack );
}
else
{
if( !remaining.isEmpty() )
{
iox.setCachedItemStack( remaining );
}
}
// At this point, we still have some items left...
if( remaining == inputStack )
{
// The stack remained unmodified, target inventory is full
return iox;
}
// At this point, we still have some items left...
if( remaining == inputStack )
{
// The stack remained unmodified, target inventory is full
return iox;
}
if( type == Actionable.MODULATE )
{
IAEItemStack added = iox.copy().setStackSize( iox.getStackSize() - remaining.getCount() );
this.cache.currentlyCached.add( added );
this.postDifference( Collections.singletonList( added ) );
try
{
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
}
catch( GridAccessException ex )
{
// meh
}
}
if( type == Actionable.MODULATE )
{
IAEItemStack added = iox.copy().setStackSize( iox.getStackSize() - remaining.getCount() );
this.cache.currentlyCached.add( added );
this.postDifference( Collections.singletonList( added ) );
try
{
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
}
catch( GridAccessException ex )
{
// meh
}
}
return AEItemStack.fromItemStack( remaining );
return AEItemStack.fromItemStack( remaining );
}
}
@Override
public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src )
{
int remainingSize = Ints.saturatedCast( request.getStackSize() );
@Override
public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src )
{
int remainingSize = Ints.saturatedCast( request.getStackSize() );
final boolean simulate = ( mode == Actionable.SIMULATE );
final boolean simulate = ( mode == Actionable.SIMULATE );
ItemStack extracted = this.itemRepository.extractItem( request.getDefinition(), remainingSize, simulate );
ItemStack extracted = this.itemRepository.extractItem( request.getDefinition(), remainingSize, simulate );
if( extracted.getCount() > remainingSize )
{
// Something broke. It should never return more than we requested...
// We're going to silently eat the remainder
AELog.warn( "Mod that provided item handler %s is broken. Returned %s items while only requesting %d.",
this.itemRepository.getClass().getName(), extracted.toString(), remainingSize );
extracted.setCount( remainingSize );
}
if( extracted.getCount() > remainingSize )
{
// Something broke. It should never return more than we requested...
// We're going to silently eat the remainder
AELog.warn( "Mod that provided item handler %s is broken. Returned %s items while only requesting %d.", this.itemRepository.getClass().getName(), extracted.toString(), remainingSize );
extracted.setCount( remainingSize );
}
if( !extracted.isEmpty() )
{
IAEItemStack extractedAEItemStack = AEItemStack.fromItemStack( extracted );
if( mode == Actionable.MODULATE )
{
IAEItemStack cachedStack = this.cache.currentlyCached.findPrecise( request );
if (cachedStack != null)
{
cachedStack.decStackSize( extractedAEItemStack.getStackSize() );
this.postDifference( Collections.singletonList( extractedAEItemStack.copy().setStackSize( -extractedAEItemStack.getStackSize() ) ) );
}
try
{
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
}
catch( GridAccessException ex )
{
// meh
}
}
return extractedAEItemStack;
}
return null;
}
if( !extracted.isEmpty() )
{
IAEItemStack extractedAEItemStack = AEItemStack.fromItemStack( extracted );
if( mode == Actionable.MODULATE )
{
IAEItemStack cachedStack = this.cache.currentlyCached.findPrecise( request );
if( cachedStack != null )
{
cachedStack.decStackSize( extractedAEItemStack.getStackSize() );
this.postDifference( Collections.singletonList( extractedAEItemStack.copy().setStackSize( -extractedAEItemStack.getStackSize() ) ) );
}
try
{
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
}
catch( GridAccessException ex )
{
// meh
}
}
return extractedAEItemStack;
}
return null;
}
@Override
public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out )
{
return this.cache.getAvailableItems( out );
}
@Override
public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out )
{
return this.cache.getAvailableItems( out );
}
@Override
public IStorageChannel<IAEItemStack> getChannel()
{
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
}
@Override
public IStorageChannel<IAEItemStack> getChannel()
{
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
}
@Override
public void addListener( IMEMonitorHandlerReceiver<IAEItemStack> l, Object verificationToken )
{
this.listeners.put( l, verificationToken );
}
@Override
public void addListener( IMEMonitorHandlerReceiver<IAEItemStack> l, Object verificationToken )
{
this.listeners.put( l, verificationToken );
}
@Override
public void removeListener( IMEMonitorHandlerReceiver<IAEItemStack> l )
{
this.listeners.remove( l );
}
@Override
public void removeListener( IMEMonitorHandlerReceiver<IAEItemStack> l )
{
this.listeners.remove( l );
}
private void postDifference( Iterable<IAEItemStack> a )
{
final Iterator<Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
while ( i.hasNext() )
{
final Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
if( key.isValid( l.getValue() ) )
{
key.postChange( this, a, this.mySource );
}
else
{
i.remove();
}
}
}
private void postDifference( Iterable<IAEItemStack> a )
{
final Iterator<Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
while ( i.hasNext() )
{
final Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
if( key.isValid( l.getValue() ) )
{
key.postChange( this, a, this.mySource );
}
else
{
i.remove();
}
}
}
@Override
public TickRateModulation onTick()
{
List<IAEItemStack> changes = this.cache.update();
if( !changes.isEmpty() && access.hasPermission( AccessRestriction.READ ) )
{
this.postDifference( changes );
return TickRateModulation.URGENT;
}
else
{
return TickRateModulation.SLOWER;
}
}
@Override
public TickRateModulation onTick()
{
List<IAEItemStack> changes = this.cache.update();
if( !changes.isEmpty() && access.hasPermission( AccessRestriction.READ ) )
{
this.postDifference( changes );
return TickRateModulation.URGENT;
}
else
{
return TickRateModulation.SLOWER;
}
}
@Override
public void setActionSource( final IActionSource mySource )
{
this.mySource = mySource;
}
@Override
public void setActionSource( final IActionSource mySource )
{
this.mySource = mySource;
}
private static class InventoryCache
{
private IItemList<IAEItemStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final IItemRepository iItemRepository;
private static class InventoryCache
{
private IItemList<IAEItemStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final IItemRepository iItemRepository;
public InventoryCache( IItemRepository iItemRepository )
{
this.iItemRepository = iItemRepository;
}
public InventoryCache( IItemRepository iItemRepository )
{
this.iItemRepository = iItemRepository;
}
public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out )
{
currentlyCached.iterator().forEachRemaining( out::add );
return out;
}
public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out )
{
currentlyCached.iterator().forEachRemaining( out::add );
return out;
}
public List<IAEItemStack> update()
{
final List<IAEItemStack> changes = new ArrayList<>();
public List<IAEItemStack> update()
{
final List<IAEItemStack> changes = new ArrayList<>();
IItemList<IAEItemStack> currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
this.iItemRepository.getAllItems().stream().map( s -> AEItemStack.fromItemStack( s.itemPrototype ).setStackSize( s.count ) ).forEach( currentlyOnStorage::add );
IItemList<IAEItemStack> currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
this.iItemRepository.getAllItems().stream().map( s -> AEItemStack.fromItemStack( s.itemPrototype ).setStackSize( s.count ) ).forEach( currentlyOnStorage::add );
for ( final IAEItemStack is : currentlyCached )
{
is.setStackSize( -is.getStackSize() );
}
for( final IAEItemStack is : currentlyCached )
{
is.setStackSize( -is.getStackSize() );
}
for ( final IAEItemStack is : currentlyOnStorage )
{
currentlyCached.add( is );
}
for( final IAEItemStack is : currentlyOnStorage )
{
currentlyCached.add( is );
}
for ( final IAEItemStack is : currentlyCached )
{
if( is.getStackSize() != 0 )
{
changes.add( is );
}
}
for( final IAEItemStack is : currentlyCached )
{
if( is.getStackSize() != 0 )
{
changes.add( is );
}
}
currentlyCached = currentlyOnStorage;
currentlyCached = currentlyOnStorage;
return changes;
}
return changes;
}
}
}
}
File diff suppressed because it is too large Load Diff
@@ -20,289 +20,289 @@ import java.util.Queue;
public class PartP2PGTCEPower extends PartP2PTunnel<PartP2PGTCEPower>
{
private static final P2PModels MODELS = new P2PModels( "part/p2p/p2p_tunnel_gtceu" );
private static final IEnergyContainer NULL_ENERGY_STORAGE = new NullEnergyStorage();
private final IEnergyContainer inputHandler = new InputEnergyStorage();
private final IEnergyContainer outputHandler = new OutputEnergyStorage();
private final Queue<PartP2PGTCEPower> outputs = new ArrayDeque<>();
private static final P2PModels MODELS = new P2PModels( "part/p2p/p2p_tunnel_gteu" );
private static final IEnergyContainer NULL_ENERGY_STORAGE = new NullEnergyStorage();
private final IEnergyContainer inputHandler = new InputEnergyStorage();
private final IEnergyContainer outputHandler = new OutputEnergyStorage();
private final Queue<PartP2PGTCEPower> outputs = new ArrayDeque<>();
public PartP2PGTCEPower( ItemStack is )
{
super( is );
}
public PartP2PGTCEPower( ItemStack is )
{
super( is );
}
@PartModels
public static List<IPartModel> getModels()
{
return MODELS.getModels();
}
@PartModels
public static List<IPartModel> getModels()
{
return MODELS.getModels();
}
@Override
public IPartModel getStaticModels()
{
return MODELS.getModel( this.isPowered(), this.isActive() );
}
@Override
public IPartModel getStaticModels()
{
return MODELS.getModel( this.isPowered(), this.isActive() );
}
@Override
public void onTunnelNetworkChange()
{
this.getHost().notifyNeighbors();
}
@Override
public void onTunnelNetworkChange()
{
this.getHost().notifyNeighbors();
}
private IEnergyContainer getAttachedEnergyStorage()
{
if( this.isActive() )
{
final TileEntity self = this.getTile();
final TileEntity te = self.getWorld().getTileEntity( self.getPos().offset( this.getSide().getFacing() ) );
private IEnergyContainer getAttachedEnergyStorage()
{
if( this.isActive() )
{
final TileEntity self = this.getTile();
final TileEntity te = self.getWorld().getTileEntity( self.getPos().offset( this.getSide().getFacing() ) );
if( te != null && te.hasCapability( GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, this.getSide().getOpposite().getFacing() ) )
{
return te.getCapability( GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, this.getSide().getOpposite().getFacing() );
}
}
return NULL_ENERGY_STORAGE;
}
if( te != null && te.hasCapability( GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, this.getSide().getOpposite().getFacing() ) )
{
return te.getCapability( GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, this.getSide().getOpposite().getFacing() );
}
}
return NULL_ENERGY_STORAGE;
}
@Override
public boolean hasCapability( @Nonnull Capability<?> capability )
{
if( capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER )
{
return true;
}
return super.hasCapability( capability );
}
@Override
public boolean hasCapability( @Nonnull Capability<?> capability )
{
if( capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER )
{
return true;
}
return super.hasCapability( capability );
}
@Nullable
@Override
public <T> T getCapability( @Nonnull Capability<T> capability )
{
if( capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER )
{
if( this.isOutput() )
{
return (T) this.outputHandler;
}
return (T) this.inputHandler;
}
return super.getCapability( capability );
}
@Nullable
@Override
public <T> T getCapability( @Nonnull Capability<T> capability )
{
if( capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER )
{
if( this.isOutput() )
{
return (T) this.outputHandler;
}
return (T) this.inputHandler;
}
return super.getCapability( capability );
}
class InputEnergyStorage implements IEnergyContainer
{
@Override
public long getEnergyCanBeInserted()
{
long canInsert = 0;
if( outputs.isEmpty() )
{
try
{
for( PartP2PGTCEPower o : PartP2PGTCEPower.this.getOutputs() )
outputs.add( o );
}
catch( GridAccessException e )
{
e.printStackTrace();
}
}
class InputEnergyStorage implements IEnergyContainer
{
@Override
public long getEnergyCanBeInserted()
{
long canInsert = 0;
if( outputs.isEmpty() )
{
try
{
for( PartP2PGTCEPower o : PartP2PGTCEPower.this.getOutputs() )
outputs.add( o );
}
catch( GridAccessException e )
{
e.printStackTrace();
}
}
while ( !outputs.isEmpty() )
{
PartP2PGTCEPower target = outputs.poll();
final IEnergyContainer output = target.getAttachedEnergyStorage();
while ( !outputs.isEmpty() )
{
PartP2PGTCEPower target = outputs.poll();
final IEnergyContainer output = target.getAttachedEnergyStorage();
if( output == null || output.getEnergyCanBeInserted() <= 0 )
{
continue;
}
canInsert += output.getEnergyCanBeInserted();
}
return canInsert;
}
if( output == null || output.getEnergyCanBeInserted() <= 0 )
{
continue;
}
canInsert += output.getEnergyCanBeInserted();
}
return canInsert;
}
@Override
public long acceptEnergyFromNetwork( EnumFacing facing, long voltage, long amperage )
{
long amperesUsed = 0L;
@Override
public long acceptEnergyFromNetwork( EnumFacing facing, long voltage, long amperage )
{
long amperesUsed = 0L;
if( outputs.isEmpty() )
{
try
{
for( PartP2PGTCEPower o : PartP2PGTCEPower.this.getOutputs() )
outputs.add( o );
}
catch( GridAccessException e )
{
e.printStackTrace();
}
}
if( outputs.isEmpty() )
{
try
{
for( PartP2PGTCEPower o : PartP2PGTCEPower.this.getOutputs() )
outputs.add( o );
}
catch( GridAccessException e )
{
e.printStackTrace();
}
}
while ( !outputs.isEmpty() )
{
PartP2PGTCEPower target = outputs.poll();
final IEnergyContainer output = target.getAttachedEnergyStorage();
while ( !outputs.isEmpty() )
{
PartP2PGTCEPower target = outputs.poll();
final IEnergyContainer output = target.getAttachedEnergyStorage();
if( output == null || !output.inputsEnergy( facing ) || output.getEnergyCanBeInserted() <= 0 )
{
continue;
}
if( output == null || !output.inputsEnergy( facing ) || output.getEnergyCanBeInserted() <= 0 )
{
continue;
}
if( voltage > 0 )
{
amperesUsed += output.acceptEnergyFromNetwork( facing, voltage, amperage - amperesUsed );
}
if( voltage > 0 )
{
amperesUsed += output.acceptEnergyFromNetwork( facing, voltage, amperage - amperesUsed );
}
if( amperage == amperesUsed )
{
break;
}
}
return amperesUsed;
}
if( amperage == amperesUsed )
{
break;
}
}
return amperesUsed;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return true;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return true;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long getEnergyStored()
{
return 0;
}
@Override
public long getEnergyStored()
{
return 0;
}
@Override
public long getEnergyCapacity()
{
return 0;
}
@Override
public long getEnergyCapacity()
{
return 0;
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputVoltage()
{
return 0;
}
}
@Override
public long getInputVoltage()
{
return 0;
}
}
class OutputEnergyStorage implements IEnergyContainer
{
@Override
public long acceptEnergyFromNetwork( EnumFacing facing, long voltage, long amperage )
{
if( facing == getSide().getFacing() )
{
return 0;
}
final IEnergyContainer output = getAttachedEnergyStorage();
voltage *= 0.95;
if( voltage > 0 )
{
return output.acceptEnergyFromNetwork( facing, voltage, amperage );
}
return 0;
}
class OutputEnergyStorage implements IEnergyContainer
{
@Override
public long acceptEnergyFromNetwork( EnumFacing facing, long voltage, long amperage )
{
if( facing == getSide().getFacing() )
{
return 0;
}
final IEnergyContainer output = getAttachedEnergyStorage();
voltage *= 0.95;
if( voltage > 0 )
{
return output.acceptEnergyFromNetwork( facing, voltage, amperage );
}
return 0;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return false;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return false;
}
@Override
public boolean outputsEnergy( EnumFacing side )
{
return true;
}
@Override
public boolean outputsEnergy( EnumFacing side )
{
return true;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long getEnergyStored()
{
return 0;
}
@Override
public long getEnergyStored()
{
return 0;
}
@Override
public long getEnergyCapacity()
{
return 0;
}
@Override
public long getEnergyCapacity()
{
return 0;
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputVoltage()
{
return 0;
}
}
@Override
public long getInputVoltage()
{
return 0;
}
}
static class NullEnergyStorage implements IEnergyContainer
{
@Override
public long acceptEnergyFromNetwork( EnumFacing enumFacing, long l, long l1 )
{
return 0;
}
static class NullEnergyStorage implements IEnergyContainer
{
@Override
public long acceptEnergyFromNetwork( EnumFacing enumFacing, long l, long l1 )
{
return 0;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return false;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return false;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long getEnergyStored()
{
return 0;
}
@Override
public long getEnergyStored()
{
return 0;
}
@Override
public long getEnergyCapacity()
{
return 0;
}
@Override
public long getEnergyCapacity()
{
return 0;
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputVoltage()
{
return 0;
}
}
@Override
public long getInputVoltage()
{
return 0;
}
}
}
@@ -156,7 +156,7 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
super.writeToStream( data );
data.writeShort( this.getFrequency() );
}
@Override
@MENetworkEventSubscribe
public void chanRender( final MENetworkChannelsChanged c )
@@ -205,10 +205,11 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
{
return false;
}
boolean pasteAsOutput = true;
ItemStack is = player.getHeldItem( hand );
if (is.isEmpty()) {
if( is.isEmpty() )
{
pasteAsOutput = false;
is = player.getHeldItemOffhand();
}
@@ -250,7 +251,7 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
if( newBus instanceof PartP2PTunnel )
{
final PartP2PTunnel newTunnel = (PartP2PTunnel) newBus;
if( pasteAsOutput )
{
newTunnel.setOutput( true );
@@ -282,7 +283,7 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
final IParts parts = AEApi.instance().definitions().parts();
switch( tt )
switch ( tt )
{
case LIGHT:
newType = parts.p2PTunnelLight().maybeStack( 1 ).orElse( ItemStack.EMPTY );
@@ -292,8 +293,8 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
newType = parts.p2PTunnelFE().maybeStack( 1 ).orElse( ItemStack.EMPTY );
break;
case GTCEU_POWER:
newType = parts.p2PTunnelGTCEU().maybeStack( 1 ).orElse( ItemStack.EMPTY );
case GTEU_POWER:
newType = parts.p2PTunnelGTEU().maybeStack( 1 ).orElse( ItemStack.EMPTY );
break;
case FLUID:
@@ -455,8 +456,10 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
final AEColor[] colors = Platform.p2p().toColors( this.getFrequency() );
final int[] colorCode = new int[]{
colors[0].ordinal(), colors[0].ordinal(), colors[1].ordinal(), colors[1].ordinal(),
colors[2].ordinal(), colors[2].ordinal(), colors[3].ordinal(), colors[3].ordinal(),
colors[0].ordinal(), colors[0].ordinal(),
colors[1].ordinal(), colors[1].ordinal(),
colors[2].ordinal(), colors[2].ordinal(),
colors[3].ordinal(), colors[3].ordinal(),
};
data.setIntArray( "colorCode", colorCode );
@@ -20,7 +20,9 @@ package appeng.tile.crafting;
import java.io.IOException;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import appeng.api.networking.security.IActionSource;
import appeng.api.storage.IMEMonitor;
@@ -28,6 +30,7 @@ import appeng.api.storage.IStorageMonitorable;
import appeng.api.storage.IStorageMonitorableAccessor;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.capabilities.Capabilities;
import appeng.helpers.PatternHelper;
import appeng.me.helpers.MachineSource;
import io.netty.buffer.ByteBuf;
@@ -37,6 +40,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.common.FMLCommonHandler;
@@ -93,6 +97,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
private final AppEngInternalInventory patternInv = new AppEngInternalInventory( this, 1, 1 );
private final IItemHandler gridInvExt = new WrapperFilteredItemHandler( this.gridInv, new CraftingGridFilter() );
private final IItemHandler internalInv = new WrapperChainedItemHandler( this.gridInv, this.patternInv );
private final EnumMap<EnumFacing, Object> neighbors = new EnumMap<>( EnumFacing.class );
private final IConfigManager settings;
private final UpgradeInventory upgrades;
private boolean isPowered = false;
@@ -122,6 +127,126 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
return 5;
}
public void updateNeighbors()
{
for( EnumFacing f : EnumFacing.VALUES )
{
TileEntity te = world.getTileEntity( pos.offset( f ) );
Object capability = null;
if( te != null )
{
// Prioritize a handler to directly link to another ME network
IStorageMonitorableAccessor accessor = te.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, f.getOpposite() );
if( accessor != null )
{
IStorageMonitorable inventory = accessor.getInventory( this.mySrc );
if( inventory != null )
{
capability = inventory;
}
}
if( capability == null )
{
capability = InventoryAdaptor.getAdaptor( te, f.getOpposite() );
}
}
if( capability != null )
{
neighbors.put( f, capability );
}
else
{
neighbors.remove( f );
}
}
}
@Override
public void onReady()
{
super.onReady();
updateNeighbors();
}
public void updateNeighbors( IBlockAccess w, BlockPos pos, BlockPos neighbor )
{
EnumFacing updateFromFacing;
if( pos.getX() != neighbor.getX() )
{
if( pos.getX() > neighbor.getX() )
{
updateFromFacing = EnumFacing.WEST;
}
else
{
updateFromFacing = EnumFacing.EAST;
}
}
else if( pos.getY() != neighbor.getY() )
{
if( pos.getY() > neighbor.getY() )
{
updateFromFacing = EnumFacing.DOWN;
}
else
{
updateFromFacing = EnumFacing.UP;
}
}
else if( pos.getZ() != neighbor.getZ() )
{
if( pos.getZ() > neighbor.getZ() )
{
updateFromFacing = EnumFacing.NORTH;
}
else
{
updateFromFacing = EnumFacing.SOUTH;
}
}
else
{
return;
}
if( pos.offset( updateFromFacing ).equals( neighbor ) )
{
TileEntity te = w.getTileEntity( neighbor );
Object capability = null;
if( te != null )
{
// Prioritize a handler to directly link to another ME network
IStorageMonitorableAccessor accessor = te.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, updateFromFacing.getOpposite() );
if( accessor != null )
{
IStorageMonitorable inventory = accessor.getInventory( this.mySrc );
if( inventory != null )
{
capability = inventory;
}
}
if( capability == null )
{
capability = InventoryAdaptor.getAdaptor( te, updateFromFacing.getOpposite() );
}
}
if( capability != null )
{
neighbors.put( updateFromFacing, capability );
}
else
{
neighbors.remove( updateFromFacing );
}
}
}
@Override
public boolean pushPattern( final ICraftingPatternDetails patternDetails, final InventoryCrafting table, final EnumFacing where )
{
@@ -151,7 +276,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
private void updateSleepiness()
{
final boolean wasEnabled = this.isAwake;
this.isAwake = this.myPlan != null && this.hasMats() || this.canPush();
this.isAwake = this.canPush() || this.myPlan != null && this.hasMats();
if( wasEnabled != this.isAwake )
{
try
@@ -187,9 +312,13 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
for( int x = 0; x < this.craftingInv.getSizeInventory(); x++ )
{
this.craftingInv.setInventorySlotContents( x, this.gridInv.getStackInSlot( x ) );
if( !myPlan.isValidItemForSlot( x, craftingInv.getStackInSlot( x ), world ) )
{
return false;
}
}
return !this.myPlan.getOutput( this.craftingInv, this.getWorld() ).isEmpty();
return this.myPlan.getOutputs().length > 0;
}
@Override
@@ -433,7 +562,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
this.reboot = false;
int speed = 10;
switch( this.upgrades.getInstalledUpgrades( Upgrades.SPEED ) )
switch ( this.upgrades.getInstalledUpgrades( Upgrades.SPEED ) )
{
case 0:
this.progress += this.userPower( ticksSinceLastCall, speed = 10, 1.0 );
@@ -527,10 +656,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
{
try
{
return (int) ( this.getProxy()
.getEnergy()
.extractAEPower( ticksPassed * bonusValue * acceleratorTax, Actionable.MODULATE,
PowerMultiplier.CONFIG ) / acceleratorTax );
return (int) ( this.getProxy().getEnergy().extractAEPower( ticksPassed * bonusValue * acceleratorTax, Actionable.MODULATE, PowerMultiplier.CONFIG ) / acceleratorTax );
}
catch( final GridAccessException e )
{
@@ -542,9 +668,13 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
{
if( this.pushDirection == AEPartLocation.INTERNAL )
{
for( final EnumFacing d : EnumFacing.VALUES )
for( final Map.Entry<EnumFacing, Object> d : neighbors.entrySet() )
{
output = this.pushTo( output, d );
output = this.pushTo( output, d.getKey() );
if( output.isEmpty() )
{
break;
}
}
}
else
@@ -568,55 +698,42 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
return output;
}
final TileEntity te = this.getWorld().getTileEntity( this.pos.offset( d ) );
if( te == null )
Object capability = neighbors.get( d );
if( capability instanceof IStorageMonitorable )
{
return output;
}
// Prioritize a handler to directly link to another ME network
IStorageMonitorableAccessor accessor = te.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, d.getOpposite() );
if( accessor != null )
{
IStorageMonitorable inventory = accessor.getInventory( this.mySrc );
if( inventory != null )
// Prioritize a handler to directly link to another ME network
IStorageMonitorable inventory = (IStorageMonitorable) capability;
IAEItemStack toInsert = AEItemStack.fromItemStack( output );
IMEMonitor<IAEItemStack> inv = inventory.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
IAEItemStack remainder = inv.injectItems( toInsert, Actionable.SIMULATE, this.mySrc );
if( remainder == null )
{
IAEItemStack toInsert = AEItemStack.fromItemStack( output );
IMEMonitor<IAEItemStack> inv = inventory.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
IAEItemStack remainder = inv.injectItems( toInsert, Actionable.SIMULATE, this.mySrc );
if( remainder == null )
inv.injectItems( toInsert, Actionable.MODULATE, this.mySrc );
return ItemStack.EMPTY;
}
else
{
if( remainder.getStackSize() == toInsert.getStackSize() )
{
inv.injectItems( toInsert, Actionable.MODULATE, this.mySrc );
return ItemStack.EMPTY;
}
else
{
if( remainder.getStackSize() == toInsert.getStackSize() )
{
return output.copy();
}
inv.injectItems( toInsert.setStackSize( toInsert.getStackSize() - remainder.getStackSize() ), Actionable.MODULATE, this.mySrc );
return remainder.createItemStack();
return output;
}
inv.injectItems( toInsert.setStackSize( toInsert.getStackSize() - remainder.getStackSize() ), Actionable.MODULATE, this.mySrc );
this.saveChanges();
return remainder.createItemStack();
}
}
final InventoryAdaptor adaptor = InventoryAdaptor.getAdaptor( te, d.getOpposite() );
if( adaptor == null )
else if( capability instanceof InventoryAdaptor )
{
return output;
}
InventoryAdaptor adaptor = (InventoryAdaptor) capability;
final int size = output.getCount();
output = adaptor.addItems( output.copy() );
final int newSize = output.isEmpty() ? 0 : output.getCount();
final int size = output.getCount();
output = adaptor.addItems( output );
final int newSize = output.isEmpty() ? 0 : output.getCount();
if( size != newSize )
{
this.saveChanges();
if( size != newSize )
{
this.saveChanges();
}
}
return output;
@@ -77,6 +77,10 @@ public class AppEngInternalInventory extends ItemStackHandler implements Iterabl
@Override
public void setStackInSlot( int slot, @Nonnull ItemStack stack )
{
if( stack == this.getStackInSlot( slot ) )
{
return;
}
this.previousStack = this.getStackInSlot( slot ).copy();
super.setStackInSlot( slot, stack );
}
@@ -8,82 +8,82 @@ import net.minecraft.util.EnumFacing;
public class GTCEEnergyAdapter implements IEnergyContainer
{
private final IExternalPowerSink sink;
private final IExternalPowerSink sink;
double EUBuffer;
double EUBuffer;
GTCEEnergyAdapter( IExternalPowerSink sink )
{
this.sink = sink;
}
GTCEEnergyAdapter( IExternalPowerSink sink )
{
this.sink = sink;
}
@Override
public long acceptEnergyFromNetwork( EnumFacing enumFacing, long voltage, long amperage )
{
final double power = voltage * amperage;
final double oldBuffer = EUBuffer;
@Override
public long acceptEnergyFromNetwork( EnumFacing enumFacing, long voltage, long amperage )
{
final double power = voltage * amperage;
final double oldBuffer = EUBuffer;
EUBuffer = this.sink.injectExternalPower( PowerUnits.GTCEU, power + EUBuffer, Actionable.MODULATE );
EUBuffer = this.sink.injectExternalPower( PowerUnits.GTEU, power + EUBuffer, Actionable.MODULATE );
// if the overflow went down, all inputs were consumed
if ( EUBuffer <= oldBuffer )
{
return amperage;
}
// if overflow is greater than the inputs, nothing was consumed
if ( EUBuffer >= power )
{
EUBuffer -= power;
return 0;
}
// determine how many amps are being used
final double usedEU = power + oldBuffer - EUBuffer;
final long ampsUsed = (long) Math.ceil( usedEU / ( (double) voltage ) );
// adjust the overflow
EUBuffer += usedEU % voltage;
// if the overflow went down, all inputs were consumed
if( EUBuffer <= oldBuffer )
{
return amperage;
}
// if overflow is greater than the inputs, nothing was consumed
if( EUBuffer >= power )
{
EUBuffer -= power;
return 0;
}
// determine how many amps are being used
final double usedEU = power + oldBuffer - EUBuffer;
final long ampsUsed = (long) Math.ceil( usedEU / ( (double) voltage ) );
// adjust the overflow
EUBuffer += usedEU % voltage;
return ampsUsed;
}
return ampsUsed;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return true;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return true;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long getEnergyStored()
{
return (long) Math.floor( PowerUnits.AE.convertTo( PowerUnits.GTCEU, this.sink.getAECurrentPower() ) );
}
@Override
public long getEnergyStored()
{
return (long) Math.floor( PowerUnits.AE.convertTo( PowerUnits.GTEU, this.sink.getAECurrentPower() ) );
}
@Override
public long getEnergyCapacity()
{
return (long) Math.floor( PowerUnits.AE.convertTo( PowerUnits.GTCEU, this.sink.getAEMaxPower() ) );
}
@Override
public long getEnergyCapacity()
{
return (long) Math.floor( PowerUnits.AE.convertTo( PowerUnits.GTEU, this.sink.getAEMaxPower() ) );
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputVoltage()
{
return 0;
}
@Override
public long getInputVoltage()
{
return 0;
}
@Override
public long getEnergyCanBeInserted()
{
return this.getEnergyCapacity() - this.getEnergyStored();
}
@Override
public long getEnergyCanBeInserted()
{
return this.getEnergyCapacity() - this.getEnergyStored();
}
}
@@ -128,7 +128,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
public TileChest()
{
this.setInternalMaxPower( PowerMultiplier.CONFIG.multiply( 40 ) );
this.setInternalMaxPower( PowerMultiplier.CONFIG.multiply( 128 ) );
this.getProxy().setFlags( GridFlags.REQUIRE_CHANNEL );
this.config.registerSetting( Settings.SORT_BY, SortOrder.NAME );
this.config.registerSetting( Settings.VIEW_MODE, ViewItems.ALL );
@@ -541,7 +541,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
if( this.cellHandler != null && this.cellHandler.getChannel() == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{
final IAEItemStack returns = Platform.poweredInsert( this, this.cellHandler,
AEItemStack.fromItemStack( this.inputInventory.getStackInSlot( 0 ) ), this.mySrc );
AEItemStack.fromItemStack( this.inputInventory.getStackInSlot( 0 ) ), this.mySrc );
if( returns == null )
{
@@ -698,7 +698,8 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
{
TileChest.this.getProxy().getStorage().postAlterationOfStoredItems( this.chan, change, TileChest.this.mySrc );
}
} catch ( final GridAccessException e )
}
catch( final GridAccessException e )
{
// :(
}
@@ -738,11 +739,11 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
return input;
}
T injected = super.injectItems( input, mode, src );
if (mode == Actionable.MODULATE && ( injected == null || injected.getStackSize() != input.getStackSize() ))
if( mode == Actionable.MODULATE && ( injected == null || injected.getStackSize() != input.getStackSize() ) )
{
if( TileChest.this.getProxy().isActive() && this.getInternalHandler().getCellInv() != null )
if( TileChest.this.isPowered() && this.getInternalHandler().getCellInv() != null )
{
TileChest.this.cellHandler.postChangesToListeners(Collections.singletonList( input.copy().setStackSize( input.getStackSize() - ( injected == null ? 0 : injected.getStackSize() ) ) ), TileChest.this.mySrc );
TileChest.this.cellHandler.postChangesToListeners( Collections.singletonList( input.copy().setStackSize( input.getStackSize() - ( injected == null ? 0 : injected.getStackSize() ) ) ), TileChest.this.mySrc );
}
}
return injected;
@@ -792,9 +793,9 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
T extracted = super.extractItems( request, mode, src );
if( mode == Actionable.MODULATE && extracted != null )
{
if( TileChest.this.getProxy().isActive() && this.getInternalHandler().getCellInv() != null )
if( TileChest.this.isPowered() && this.getInternalHandler().getCellInv() != null )
{
TileChest.this.cellHandler.postChangesToListeners(Collections.singletonList( request.copy().setStackSize( -extracted.getStackSize() ) ), TileChest.this.mySrc );
TileChest.this.cellHandler.postChangesToListeners( Collections.singletonList( request.copy().setStackSize( -extracted.getStackSize() ) ), TileChest.this.mySrc );
}
}
return extracted;
@@ -848,7 +849,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
private class FluidHandler implements IFluidHandler
{
private final IFluidTankProperties[] TANK_PROPS = new IFluidTankProperties[] { new FluidTankProperties( null, Fluid.BUCKET_VOLUME ) };
private final IFluidTankProperties[] TANK_PROPS = new IFluidTankProperties[]{new FluidTankProperties( null, Fluid.BUCKET_VOLUME )};
@Override
public int fill( final FluidStack resource, final boolean doFill )
@@ -858,7 +859,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
.getChannel() == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) )
{
final IAEFluidStack results = Platform.poweredInsert( TileChest.this, TileChest.this.cellHandler, AEFluidStack.fromFluidStack( resource ),
TileChest.this.mySrc, doFill ? Actionable.MODULATE : Actionable.SIMULATE );
TileChest.this.mySrc, doFill ? Actionable.MODULATE : Actionable.SIMULATE );
if( results == null )
{
+60 -51
View File
@@ -36,6 +36,9 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import gregtech.api.items.IToolItem;
import ic2.api.item.IC2Items;
import ic2.api.item.ICustomDamageItem;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
@@ -73,6 +76,7 @@ import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.Optional;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.oredict.OreDictionary;
@@ -134,6 +138,8 @@ import appeng.util.prioritylist.IPartitionList;
* @version rv2
* @since rv0
*/
@Optional.Interface( iface = "gregtech.api.items.IToolItem", modid = "gregtech" )
@Optional.Interface( iface = "ic2.api.item.ICustomDamageItem", modid = "IC2" )
public class Platform
{
@@ -176,9 +182,8 @@ public class Platform
/**
* This displays the value for encoded longs ( double *100 )
*
* @param n to be formatted long value
* @param n to be formatted long value
* @param isRate if true it adds a /t to the formatted string
*
* @return formatted long value
*/
public static String formatPowerLong( final long n, final boolean isRate )
@@ -188,12 +193,14 @@ public class Platform
final PowerUnits displayUnits = AEConfig.instance().selectedPowerUnit();
p = PowerUnits.AE.convertTo( displayUnits, p );
final String[] preFixes = { "k", "M", "G", "T", "P", "T", "P", "E", "Z", "Y" };
final String[] preFixes = {
"k", "M", "G", "T", "P", "T", "P", "E", "Z", "Y"
};
String unitName = displayUnits.name();
String level = "";
int offset = 0;
while( p > 1000 && offset < preFixes.length )
while ( p > 1000 && offset < preFixes.length )
{
p /= 1000;
level = preFixes[offset];
@@ -210,7 +217,7 @@ public class Platform
final int west_y = forward.zOffset * up.xOffset - forward.xOffset * up.zOffset;
final int west_z = forward.xOffset * up.yOffset - forward.yOffset * up.xOffset;
switch( west_x + west_y * 2 + west_z * 3 )
switch ( west_x + west_y * 2 + west_z * 3 )
{
case 1:
return AEPartLocation.EAST;
@@ -237,7 +244,7 @@ public class Platform
final int west_y = forward.getFrontOffsetZ() * up.getFrontOffsetX() - forward.getFrontOffsetX() * up.getFrontOffsetZ();
final int west_z = forward.getFrontOffsetX() * up.getFrontOffsetY() - forward.getFrontOffsetY() * up.getFrontOffsetX();
switch( west_x + west_y * 2 + west_z * 3 )
switch ( west_x + west_y * 2 + west_z * 3 )
{
case 1:
return EnumFacing.EAST;
@@ -271,8 +278,7 @@ public class Platform
{
ce = nextEnum( ce );
}
}
while( !validOptions.contains( ce ) || isNotValidSetting( ce ) );
} while ( !validOptions.contains( ce ) || isNotValidSetting( ce ) );
return ce;
}
@@ -446,7 +452,7 @@ public class Platform
{
if( upAndDown )
{
switch( dir )
switch ( dir )
{
case NORTH:
return AEPartLocation.SOUTH;
@@ -466,7 +472,7 @@ public class Platform
}
else
{
switch( dir )
switch ( dir )
{
case UP:
return AEPartLocation.DOWN;
@@ -519,8 +525,7 @@ public class Platform
final double offset_x = ( getRandomInt() % 32 - 16 ) / 82;
final double offset_y = ( getRandomInt() % 32 - 16 ) / 82;
final double offset_z = ( getRandomInt() % 32 - 16 ) / 82;
final EntityItem ei = new EntityItem( w, 0.5 + offset_x + pos.getX(), 0.5 + offset_y + pos.getY(), 0.2 + offset_z + pos.getZ(), i
.copy() );
final EntityItem ei = new EntityItem( w, 0.5 + offset_x + pos.getX(), 0.5 + offset_y + pos.getY(), 0.2 + offset_z + pos.getZ(), i.copy() );
w.spawnEntity( ei );
}
}
@@ -592,8 +597,7 @@ public class Platform
try
{
ITooltipFlag.TooltipFlags tooltipFlag = Minecraft
.getMinecraft().gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL;
ITooltipFlag.TooltipFlags tooltipFlag = Minecraft.getMinecraft().gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL;
return itemStack.getTooltip( Minecraft.getMinecraft().player, tooltipFlag );
}
catch( final Exception errB )
@@ -764,7 +768,7 @@ public class Platform
public static int MC2MEColor( final int color )
{
switch( color )
switch ( color )
{
case 4: // "blue"
return 0;
@@ -842,10 +846,10 @@ public class Platform
return forward;
}
switch( forward )
switch ( forward )
{
case DOWN:
switch( axis )
switch ( axis )
{
case DOWN:
return forward;
@@ -864,7 +868,7 @@ public class Platform
}
break;
case UP:
switch( axis )
switch ( axis )
{
case NORTH:
return AEPartLocation.WEST;
@@ -879,7 +883,7 @@ public class Platform
}
break;
case NORTH:
switch( axis )
switch ( axis )
{
case UP:
return AEPartLocation.WEST;
@@ -894,7 +898,7 @@ public class Platform
}
break;
case SOUTH:
switch( axis )
switch ( axis )
{
case UP:
return AEPartLocation.EAST;
@@ -909,7 +913,7 @@ public class Platform
}
break;
case EAST:
switch( axis )
switch ( axis )
{
case UP:
return AEPartLocation.NORTH;
@@ -923,7 +927,7 @@ public class Platform
break;
}
case WEST:
switch( axis )
switch ( axis )
{
case UP:
return AEPartLocation.SOUTH;
@@ -944,10 +948,10 @@ public class Platform
public static EnumFacing rotateAround( final EnumFacing forward, final EnumFacing axis )
{
switch( forward )
switch ( forward )
{
case DOWN:
switch( axis )
switch ( axis )
{
case DOWN:
return forward;
@@ -966,7 +970,7 @@ public class Platform
}
break;
case UP:
switch( axis )
switch ( axis )
{
case NORTH:
return EnumFacing.WEST;
@@ -981,7 +985,7 @@ public class Platform
}
break;
case NORTH:
switch( axis )
switch ( axis )
{
case UP:
return EnumFacing.WEST;
@@ -996,7 +1000,7 @@ public class Platform
}
break;
case SOUTH:
switch( axis )
switch ( axis )
{
case UP:
return EnumFacing.EAST;
@@ -1011,7 +1015,7 @@ public class Platform
}
break;
case EAST:
switch( axis )
switch ( axis )
{
case UP:
return EnumFacing.NORTH;
@@ -1025,7 +1029,7 @@ public class Platform
break;
}
case WEST:
switch( axis )
switch ( axis )
{
case UP:
return EnumFacing.SOUTH;
@@ -1101,9 +1105,7 @@ public class Platform
final Vec3d vec31 = vec3.addVector( f7 * d3, f6 * d3, f8 * d3 );
final AxisAlignedBB bb = new AxisAlignedBB( Math.min( vec3.x, vec31.x ), Math.min( vec3.y, vec31.y ), Math.min( vec3.z,
vec31.z ), Math.max( vec3.x, vec31.x ), Math.max( vec3.y, vec31.y ), Math.max( vec3.z, vec31.z ) ).grow(
16, 16, 16 );
final AxisAlignedBB bb = new AxisAlignedBB( Math.min( vec3.x, vec31.x ), Math.min( vec3.y, vec31.y ), Math.min( vec3.z, vec31.z ), Math.max( vec3.x, vec31.x ), Math.max( vec3.y, vec31.y ), Math.max( vec3.z, vec31.z ) ).grow( 16, 16, 16 );
Entity entity = null;
double closest = 9999999.0D;
@@ -1249,15 +1251,15 @@ public class Platform
final T leftover = input.copy();
final T split = input.copy();
leftover.decStackSize(itemToAdd);
split.setStackSize(itemToAdd);
leftover.add(cell.injectItems(split, Actionable.MODULATE, src));
leftover.decStackSize( itemToAdd );
split.setStackSize( itemToAdd );
leftover.add( cell.injectItems( split, Actionable.MODULATE, src ) );
src.player().ifPresent( player ->
{
final long diff = original - leftover.getStackSize();
Stats.ItemsInserted.addToPlayer( player, (int) diff );
} );
{
final long diff = original - leftover.getStackSize();
Stats.ItemsInserted.addToPlayer( player, (int) diff );
} );
return leftover;
}
@@ -1265,10 +1267,10 @@ public class Platform
final T ret = cell.injectItems( input, Actionable.MODULATE, src );
src.player().ifPresent( player ->
{
final long diff = ret == null ? input.getStackSize() : input.getStackSize() - ret.getStackSize();
Stats.ItemsInserted.addToPlayer( player, (int) diff );
} );
{
final long diff = ret == null ? input.getStackSize() : input.getStackSize() - ret.getStackSize();
Stats.ItemsInserted.addToPlayer( player, (int) diff );
} );
return ret;
}
@@ -1282,7 +1284,7 @@ public class Platform
return input;
}
@SuppressWarnings( { "rawtypes", "unchecked" } )
@SuppressWarnings( {"rawtypes", "unchecked"} )
public static void postChanges( final IStorageGrid gs, final ItemStack removed, final ItemStack added, final IActionSource src )
{
for( final IStorageChannel<?> chan : AEApi.instance().storage().storageChannels() )
@@ -1361,8 +1363,7 @@ public class Platform
final String locationA = a.getGridBlock().isWorldAccessible() ? a.getGridBlock().getLocation().toString() : "notInWorld";
final String locationB = b.getGridBlock().isWorldAccessible() ? b.getGridBlock().getLocation().toString() : "notInWorld";
AELog.info( "Audit: Node A [isSecure=%b, key=%d, playerID=%d, location={%s}] vs Node B[isSecure=%b, key=%d, playerID=%d, location={%s}]",
a_isSecure, a.getLastSecurityKey(), a.getPlayerID(), locationA, b_isSecure, b.getLastSecurityKey(), b.getPlayerID(), locationB );
AELog.info( "Audit: Node A [isSecure=%b, key=%d, playerID=%d, location={%s}] vs Node B[isSecure=%b, key=%d, playerID=%d, location={%s}]", a_isSecure, a.getLastSecurityKey(), a.getPlayerID(), locationA, b_isSecure, b.getLastSecurityKey(), b.getPlayerID(), locationB );
}
// can't do that son...
@@ -1423,7 +1424,7 @@ public class Platform
float yaw = 0.0f;
// player.yOffset = 1.8f;
switch( side )
switch ( side )
{
case DOWN:
pitch = 90.0f;
@@ -1513,16 +1514,14 @@ public class Platform
}
}
final boolean checkFuzzy = ae_req.getOre().isPresent() || providedTemplate.getItemDamage() == OreDictionary.WILDCARD_VALUE || providedTemplate
.hasTagCompound() || providedTemplate.isItemStackDamageable();
final boolean checkFuzzy = ae_req.getOre().isPresent() || providedTemplate.getItemDamage() == OreDictionary.WILDCARD_VALUE || providedTemplate.hasTagCompound() || providedTemplate.isItemStackDamageable();
if( items != null && checkFuzzy )
{
for( final IAEItemStack x : items )
{
final ItemStack sh = x.getDefinition();
if( ( Platform.itemComparisons().isEqualItemType( providedTemplate, sh ) || ae_req.sameOre( x ) ) && !ItemStack.areItemsEqual( sh,
output ) )
if( ( Platform.itemComparisons().isEqualItemType( providedTemplate, sh ) || ae_req.sameOre( x ) ) && !ItemStack.areItemsEqual( sh, output ) )
{ // Platform.isSameItemType( sh, providedTemplate )
final ItemStack cp = sh.copy();
cp.setCount( 1 );
@@ -1681,4 +1680,14 @@ public class Platform
return isPurified;
}
public static boolean isGTDamageableItem( Item item )
{
return ( isModLoaded( "gregtech" ) && item instanceof IToolItem );
}
public static boolean isIC2DamageableItem( Item item )
{
return ( isModLoaded( "IC2" ) && item instanceof ICustomDamageItem );
}
}
@@ -223,26 +223,28 @@ public class AdaptorItemHandler extends InventoryAdaptor
return this.addItems( toBeSimulated, true );
}
protected ItemStack addItems( final ItemStack itemsToAdd, final boolean simulate )
protected ItemStack addItems( ItemStack itemsToAdd, final boolean simulate )
{
if( itemsToAdd.isEmpty() )
{
return ItemStack.EMPTY;
}
ItemStack left = itemsToAdd.copy();
for( int slot = 0; slot < this.itemHandler.getSlots(); slot++ )
{
left = this.itemHandler.insertItem( slot, left, simulate );
if( !simulate )
{
itemsToAdd = itemsToAdd.copy();
}
itemsToAdd = this.itemHandler.insertItem( slot, itemsToAdd, simulate );
if( left.isEmpty() )
if( itemsToAdd.isEmpty() )
{
return ItemStack.EMPTY;
}
}
return left;
return itemsToAdd;
}
@Override
@@ -163,23 +163,26 @@ public class AdaptorItemRepository extends InventoryAdaptor
return this.addItems( toBeAdded, false );
}
protected ItemStack addItems( final ItemStack itemsToAdd, final boolean simulate )
protected ItemStack addItems( ItemStack itemsToAdd, final boolean simulate )
{
if( itemsToAdd.isEmpty() )
{
return ItemStack.EMPTY;
}
ItemStack left = itemsToAdd.copy();
if( !simulate )
{
itemsToAdd = itemsToAdd.copy();
}
left = this.itemRepository.insertItem( left, simulate );
itemsToAdd = this.itemRepository.insertItem( itemsToAdd, simulate );
if( left.isEmpty() )
if( itemsToAdd.isEmpty() )
{
return ItemStack.EMPTY;
}
return left;
return itemsToAdd;
}
@Override
@@ -1,18 +1,12 @@
package appeng.util.inv;
import appeng.api.config.FuzzyMode;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.helpers.NonBlockingItems;
import appeng.util.item.AEItemStack;
import appeng.util.item.ItemList;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
@@ -29,9 +23,12 @@ public class BlockingItemHandler extends BlockingInventoryAdaptor
boolean isBlockableItem( ItemStack stack )
{
IItemList<IAEItemStack> itemList = NonBlockingItems.INSTANCE.getMap().get( domain );
Collection<IAEItemStack> item = itemList.findFuzzy( AEItemStack.fromItemStack( stack ), FuzzyMode.IGNORE_ALL );
return item.isEmpty();
Object2ObjectOpenHashMap<Item, IntSet> map = NonBlockingItems.INSTANCE.getMap().get( domain );
if( map.get( stack.getItem() ) != null )
{
return !map.get( stack.getItem() ).contains( stack.getItemDamage() );
}
return true;
}
@Override
@@ -41,11 +38,10 @@ public class BlockingItemHandler extends BlockingInventoryAdaptor
for( int slot = 0; slot < slots; slot++ )
{
ItemStack is = this.itemHandler.getStackInSlot( slot );
if( is.isEmpty() || !isBlockableItem( is ) )
if( !is.isEmpty() && isBlockableItem( is ) )
{
continue;
return true;
}
return true;
}
return false;
}
+321 -262
View File
@@ -26,6 +26,8 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.primitives.Ints;
import gregtech.api.items.IToolItem;
import ic2.api.item.ICustomDamageItem;
import io.netty.buffer.ByteBuf;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@@ -42,320 +44,377 @@ import appeng.api.storage.data.IAEItemStack;
import appeng.core.Api;
import appeng.util.Platform;
public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemStack {
private static final String NBT_STACKSIZE = "Cnt";
private static final String NBT_REQUESTABLE = "Req";
private static final String NBT_CRAFTABLE = "Craft";
private final AESharedItemStack sharedStack;
private Optional<OreReference> oreReference;
public class AEItemStack extends AEStack<IAEItemStack> implements IAEItemStack
{
private static final String NBT_STACKSIZE = "Cnt";
private static final String NBT_REQUESTABLE = "Req";
private static final String NBT_CRAFTABLE = "Craft";
@SideOnly(Side.CLIENT)
private String displayName;
@SideOnly( Side.CLIENT )
private List<String> tooltip;
private ItemStack cachedItemStack;
private final AESharedItemStack sharedStack;
private Optional<OreReference> oreReference;
private AEItemStack(final AEItemStack is) {
this.setStackSize(is.getStackSize());
this.setCraftable(is.isCraftable());
this.setCountRequestable(is.getCountRequestable());
this.sharedStack = is.sharedStack;
this.oreReference = is.oreReference;
}
@SideOnly( Side.CLIENT )
private String displayName;
@SideOnly( Side.CLIENT )
private List<String> tooltip;
private ItemStack cachedItemStack;
private AEItemStack(final AESharedItemStack is, long size) {
this.sharedStack = is;
this.setStackSize(size);
this.setCraftable(false);
this.setCountRequestable(0);
this.oreReference = OreHelper.INSTANCE.getOre( is.getDefinition() );
}
private AEItemStack( final AEItemStack is )
{
this.setStackSize( is.getStackSize() );
this.setCraftable( is.isCraftable() );
this.setCountRequestable( is.getCountRequestable() );
this.sharedStack = is.sharedStack;
this.oreReference = is.oreReference;
this.cachedItemStack = is.cachedItemStack;
}
@Nullable
public static AEItemStack fromItemStack(@Nonnull final ItemStack stack) {
if (stack.isEmpty()) {
return null;
}
private AEItemStack( final AESharedItemStack is, long size )
{
this.sharedStack = is;
this.setStackSize( size );
this.setCraftable( false );
this.setCountRequestable( 0 );
this.oreReference = OreHelper.INSTANCE.getOre( is.getDefinition() );
}
return new AEItemStack(AEItemStackRegistry.getRegisteredStack(stack), stack.getCount());
}
@Nullable
public static AEItemStack fromItemStack( @Nonnull final ItemStack stack )
{
if( stack.isEmpty() )
{
return null;
}
public static IAEItemStack fromNBT( final NBTTagCompound i )
{
if( i == null )
{
return null;
}
return new AEItemStack( AEItemStackRegistry.getRegisteredStack( stack ), stack.getCount() );
}
final ItemStack itemstack = new ItemStack( i );
if( itemstack.isEmpty() )
{
return null;
}
public static IAEItemStack fromNBT( final NBTTagCompound i )
{
if( i == null )
{
return null;
}
final AEItemStack item = AEItemStack.fromItemStack( itemstack );
final ItemStack itemstack = new ItemStack( i );
if( itemstack.isEmpty() )
{
return null;
}
item.setStackSize(i.getLong(NBT_STACKSIZE));
item.setCountRequestable(i.getLong(NBT_REQUESTABLE));
item.setCraftable(i.getBoolean(NBT_CRAFTABLE));
return item;
}
final AEItemStack item = AEItemStack.fromItemStack( itemstack );
@Override
public void writeToNBT(final NBTTagCompound i) {
this.getDefinition().writeToNBT( i );
item.setStackSize( i.getLong( NBT_STACKSIZE ) );
item.setCountRequestable( i.getLong( NBT_REQUESTABLE ) );
item.setCraftable( i.getBoolean( NBT_CRAFTABLE ) );
return item;
}
i.setLong(NBT_STACKSIZE, this.getStackSize());
i.setLong(NBT_REQUESTABLE, this.getCountRequestable());
i.setBoolean(NBT_CRAFTABLE, this.isCraftable());
}
@Override
public void writeToNBT( final NBTTagCompound i )
{
this.getDefinition().writeToNBT( i );
public static AEItemStack fromPacket( final ByteBuf data )
{
final byte mask = data.readByte();
final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 );
final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 );
final boolean isCraftable = ( mask & 0x40 ) > 0;
i.setLong( NBT_STACKSIZE, this.getStackSize() );
i.setLong( NBT_REQUESTABLE, this.getCountRequestable() );
i.setBoolean( NBT_CRAFTABLE, this.isCraftable() );
}
final ItemStack itemstack = new ItemStack( ByteBufUtils.readTag( data ) );
final long stackSize = getPacketValue( stackType, data );
final long countRequestable = getPacketValue( countReqType, data );
public static AEItemStack fromPacket( final ByteBuf data )
{
final byte mask = data.readByte();
final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 );
final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 );
final boolean isCraftable = ( mask & 0x40 ) > 0;
if( itemstack.isEmpty() )
{
return null;
}
final ItemStack itemstack = new ItemStack( ByteBufUtils.readTag( data ) );
final long stackSize = getPacketValue( stackType, data );
final long countRequestable = getPacketValue( countReqType, data );
final AEItemStack item = new AEItemStack( AEItemStackRegistry.getRegisteredStack( itemstack ), stackSize );
item.setCountRequestable( countRequestable );
item.setCraftable( isCraftable );
return item;
}
if( itemstack.isEmpty() )
{
return null;
}
@Override
public void writeToPacket( final ByteBuf i )
{
final byte mask = (byte) ( ( this.getType( this.getStackSize() ) << 2 ) | ( this
.getType( this.getCountRequestable() ) << 4 ) | ( (byte) ( this.isCraftable() ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 );
final AEItemStack item = new AEItemStack( AEItemStackRegistry.getRegisteredStack( itemstack ), stackSize );
item.setCountRequestable( countRequestable );
item.setCraftable( isCraftable );
return item;
}
i.writeByte( mask );
ByteBufUtils.writeTag( i, this.getDefinition().serializeNBT() );
this.putPacketValue( i, this.getStackSize() );
this.putPacketValue( i, this.getCountRequestable() );
}
@Override
public void writeToPacket( final ByteBuf i )
{
final byte mask = (byte) ( ( this.getType( this.getStackSize() ) << 2 ) | ( this.getType( this.getCountRequestable() ) << 4 ) | ( (byte) ( this.isCraftable() ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 );
@Override
public void add(final IAEItemStack option) {
if (option == null) {
return;
}
i.writeByte( mask );
ByteBufUtils.writeTag( i, this.getDefinition().serializeNBT() );
this.putPacketValue( i, this.getStackSize() );
this.putPacketValue( i, this.getCountRequestable() );
}
this.incStackSize(option.getStackSize());
this.setCountRequestable(this.getCountRequestable() + option.getCountRequestable());
this.setCraftable(this.isCraftable() || option.isCraftable());
}
@Override
public void add( final IAEItemStack option )
{
if( option == null )
{
return;
}
@Override
public boolean fuzzyComparison(final IAEItemStack other, final FuzzyMode mode) {
final ItemStack itemStack = this.getDefinition();
final ItemStack otherStack = other.getDefinition();
this.incStackSize( option.getStackSize() );
this.setCountRequestable( this.getCountRequestable() + option.getCountRequestable() );
this.setCraftable( this.isCraftable() || option.isCraftable() );
}
return this.fuzzyItemStackComparison(itemStack, otherStack, mode);
}
@Override
public boolean fuzzyComparison( final IAEItemStack other, final FuzzyMode mode )
{
final ItemStack itemStack = this.getDefinition();
final ItemStack otherStack = other.getDefinition();
@Override
public IAEItemStack copy() {
return new AEItemStack(this);
}
return this.fuzzyItemStackComparison( itemStack, otherStack, mode );
}
@Override
public boolean isItem()
{
return true;
}
@Override
public IAEItemStack copy()
{
return new AEItemStack( this );
}
@Override
public boolean isFluid()
{
return false;
}
@Override
public boolean isItem()
{
return true;
}
@Override
public IStorageChannel<IAEItemStack> getChannel() {
return Api.INSTANCE.storage().getStorageChannel(IItemStorageChannel.class);
}
@Override
public boolean isFluid()
{
return false;
}
@Override
public ItemStack createItemStack() {
return ItemHandlerHelper.copyStackWithSize(this.getDefinition(),
(int) Math.min(Integer.MAX_VALUE, this.getStackSize()));
}
@Override
public IStorageChannel<IAEItemStack> getChannel()
{
return Api.INSTANCE.storage().getStorageChannel( IItemStorageChannel.class );
}
@Override
public Item getItem() {
return this.getDefinition().getItem();
}
@Override
public ItemStack createItemStack()
{
return ItemHandlerHelper.copyStackWithSize( this.getDefinition(), (int) Math.min( Integer.MAX_VALUE, this.getStackSize() ) );
}
@Override
public int getItemDamage() {
return this.sharedStack.getItemDamage();
}
@Override
public Item getItem()
{
return this.getDefinition().getItem();
}
@Override
public boolean sameOre( final IAEItemStack is )
{
return OreHelper.INSTANCE.sameOre( this, is );
}
@Override
public int getItemDamage()
{
return this.sharedStack.getItemDamage();
}
@Override
public boolean isSameType(final IAEItemStack otherStack) {
if (otherStack == null) {
return false;
}
@Override
public boolean sameOre( final IAEItemStack is )
{
return OreHelper.INSTANCE.sameOre( this, is );
}
return Objects.equals(this.sharedStack, ((AEItemStack) otherStack).sharedStack);
}
@Override
public boolean isSameType( final IAEItemStack otherStack )
{
if( otherStack == null )
{
return false;
}
@Override
public boolean isSameType(final ItemStack otherStack) {
if (otherStack.isEmpty()) {
return false;
}
int oldSize = otherStack.getCount();
return Objects.equals( this.sharedStack, ( (AEItemStack) otherStack ).sharedStack );
}
otherStack.setCount(1);
boolean ret = ItemStack.areItemStacksEqual(this.getDefinition(), otherStack);
otherStack.setCount(oldSize);
@Override
public boolean isSameType( final ItemStack otherStack )
{
if( otherStack.isEmpty() )
{
return false;
}
int oldSize = otherStack.getCount();
return ret;
}
otherStack.setCount( 1 );
boolean ret = ItemStack.areItemStacksEqual( this.getDefinition(), otherStack );
otherStack.setCount( oldSize );
@Override
public int hashCode() {
return this.sharedStack.hashCode();
}
return ret;
}
@Override
public boolean equals( final Object ia )
{
if( ia instanceof AEItemStack )
{
return this.isSameType( (AEItemStack) ia );
}
else if( ia instanceof ItemStack )
{
// this actually breaks the equals contract (being equals to unrelated classes)
return equals( (ItemStack) ia );
}
return false;
}
@Override
public int hashCode()
{
return this.sharedStack.hashCode();
}
@Override
public boolean equals( final ItemStack is )
{
return this.isSameType( is );
}
@Override
public boolean equals( final Object ia )
{
if( ia instanceof AEItemStack )
{
return this.isSameType( (AEItemStack) ia );
}
else if( ia instanceof ItemStack )
{
// this actually breaks the equals contract (being equals to unrelated classes)
return equals( (ItemStack) ia );
}
return false;
}
@Override
public ItemStack getCachedItemStack( long stackSize )
{
@Nullable ItemStack currentCached = this.cachedItemStack;
cachedItemStack = ItemStack.EMPTY;
@Override
public boolean equals( final ItemStack is )
{
return this.isSameType( is );
}
ItemStack itemStack;
@Override
public ItemStack getCachedItemStack( long stackSize )
{
if( this.cachedItemStack != null )
{
if( Platform.itemComparisons().isSameItem( this.getDefinition(), this.cachedItemStack ) )
{
ItemStack currentCached = this.cachedItemStack;
this.cachedItemStack = null;
currentCached.setCount( Ints.saturatedCast( stackSize ) );
return currentCached;
}
}
return ItemHandlerHelper.copyStackWithSize( this.getDefinition(), Ints.saturatedCast( stackSize ) );
}
if( currentCached != null )
{
// Cache is suitable, just update the count
itemStack = currentCached;
currentCached.setCount( Ints.saturatedCast( stackSize ) );
}
else
{
// We need a new stack :-(
itemStack = this.createItemStack();
}
return itemStack;
}
@Override
public void setCachedItemStack( ItemStack itemStack )
{
this.cachedItemStack = itemStack;
}
@Override
public void setCachedItemStack( ItemStack itemStack )
{
this.cachedItemStack = itemStack;
}
@Override
public String toString()
{
return this.getStackSize() + "x" + this.getDefinition().getItem().getRegistryName();
}
@Override
public String toString()
{
return this.getStackSize() + "x" + this.getDefinition().getItem().getRegistryName();
}
@SideOnly( Side.CLIENT )
public List<String> getToolTip()
{
if( this.tooltip == null )
{
this.tooltip = Platform.getTooltip( this.asItemStackRepresentation() );
}
return this.tooltip;
}
@SideOnly( Side.CLIENT )
public List<String> getToolTip()
{
if( this.tooltip == null )
{
this.tooltip = Platform.getTooltip( this.asItemStackRepresentation() );
}
return this.tooltip;
}
@SideOnly( Side.CLIENT )
public String getDisplayName()
{
if( this.displayName == null )
{
this.displayName = Platform.getItemDisplayName( this.asItemStackRepresentation() );
}
return this.displayName;
}
@SideOnly( Side.CLIENT )
public String getDisplayName()
{
if( this.displayName == null )
{
this.displayName = Platform.getItemDisplayName( this.asItemStackRepresentation() );
}
return this.displayName;
}
@SideOnly( Side.CLIENT )
public String getModID()
{
return this.getDefinition().getItem().getRegistryName().getResourceDomain();
}
@SideOnly( Side.CLIENT )
public String getModID()
{
return this.getDefinition().getItem().getRegistryName().getResourceDomain();
}
public Optional<OreReference> getOre()
{
return this.oreReference;
}
public Optional<OreReference> getOre()
{
return this.oreReference;
}
@Override
public boolean hasTagCompound()
{
return this.getDefinition().hasTagCompound();
}
@Override
public boolean hasTagCompound()
{
return this.getDefinition().hasTagCompound();
}
@Override
public ItemStack asItemStackRepresentation()
{
return this.getDefinition().copy();
}
@Override
public ItemStack asItemStackRepresentation() {
return this.getDefinition().copy();
}
@Override
public ItemStack getDefinition()
{
return this.sharedStack.getDefinition();
}
@Override
public ItemStack getDefinition() {
return this.sharedStack.getDefinition();
}
AESharedItemStack getSharedStack()
{
return this.sharedStack;
}
AESharedItemStack getSharedStack() {
return this.sharedStack;
}
private boolean fuzzyItemStackComparison( ItemStack a, ItemStack b, FuzzyMode mode )
{
if( a.getItem() == b.getItem() && ( a.getItem().isDamageable() || Platform.isGTDamageableItem( a.getItem() ) ) )
{
if( mode == FuzzyMode.IGNORE_ALL )
{
if( a.getItem().isDamageable() )
{
return true;
}
else if( Platform.isGTDamageableItem( a.getItem() ) )
{
return a.getItemDamage() == b.getItemDamage();
}
}
else if( mode == FuzzyMode.PERCENT_99 )
{
if( Platform.isIC2DamageableItem( a.getItem() ) )
{
return ( (ICustomDamageItem) a.getItem() ).getCustomDamage( a ) > 1 == ( (ICustomDamageItem) b.getItem() ).getCustomDamage( b ) > 1;
}
else if( a.getItem().isDamageable() )
{
return a.getItemDamage() > 1 == b.getItemDamage() > 1;
}
else if( Platform.isGTDamageableItem( a.getItem() ) )
{
return ( (IToolItem) a.getItem() ).getItemDamage( a ) > 1 == ( (IToolItem) b.getItem() ).getItemDamage( b ) > 1;
}
}
else
{
float percentDamageOfA = 0;
float percentDamageOfB = 0;
if( Platform.isIC2DamageableItem( a.getItem() ) )
{
percentDamageOfA = (float) ( (ICustomDamageItem) a.getItem() ).getCustomDamage( a ) / ( (ICustomDamageItem) a.getItem() ).getMaxCustomDamage( a );
percentDamageOfB = (float) ( (ICustomDamageItem) b.getItem() ).getCustomDamage( b ) / ( (ICustomDamageItem) b.getItem() ).getMaxCustomDamage( b );
}
else if( a.getItem().isDamageable() )
{
percentDamageOfA = (float) a.getItemDamage() / a.getMaxDamage();
percentDamageOfB = (float) b.getItemDamage() / b.getMaxDamage();
}
else if( Platform.isGTDamageableItem( a.getItem() ) )
{
percentDamageOfA = (float) ( (IToolItem) a.getItem() ).getItemDamage( a ) / ( (IToolItem) a.getItem() ).getMaxItemDamage( a );
percentDamageOfB = (float) ( (IToolItem) b.getItem() ).getItemDamage( b ) / ( (IToolItem) b.getItem() ).getMaxItemDamage( b );
}
private boolean fuzzyItemStackComparison(ItemStack a, ItemStack b, FuzzyMode mode) {
if (a.getItem() == b.getItem() && a.getItem().isDamageable()) {
if (mode == FuzzyMode.IGNORE_ALL) {
return true;
} else if (mode == FuzzyMode.PERCENT_99) {
return a.getItemDamage() > 1 == b.getItemDamage() > 1;
} else {
final float percentDamageOfA = (float) a.getItemDamage() / a.getMaxDamage();
final float percentDamageOfB = (float) b.getItemDamage() / b.getMaxDamage();
return percentDamageOfA > mode.breakPoint == percentDamageOfB > mode.breakPoint;
}
}
return percentDamageOfA > mode.breakPoint == percentDamageOfB > mode.breakPoint;
}
}
return false;
}
return false;
}
}
@@ -25,7 +25,8 @@ import java.util.Map;
import appeng.util.Platform;
import com.google.common.base.Preconditions;
import gregtech.common.items.MetaTool;
import gregtech.api.items.IToolItem;
import ic2.api.item.ICustomDamageItem;
import net.minecraft.item.ItemStack;
import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap;
@@ -34,159 +35,210 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
import appeng.api.config.FuzzyMode;
import appeng.api.storage.data.IAEItemStack;
/**
* This variant list is optimized for damageable items, and supports selecting durability ranges with
* {@link #findFuzzy(IAEItemStack, FuzzyMode)}.
*/
class FuzzyItemVariantList extends ItemVariantList {
class FuzzyItemVariantList extends ItemVariantList
{
static final SharedStackComparator COMPARATOR = new SharedStackComparator();
static final SharedStackComparator COMPARATOR = new SharedStackComparator();
// NOTE: We only use Object as they key here so we can pass our special DamageBounds to the subMap method.
// We NEVER put any keys in this map that are not AESharedItemStacks.
private final Object2ObjectSortedMap<Object, IAEItemStack> records = new Object2ObjectAVLTreeMap<>(COMPARATOR);
// NOTE: We only use Object as they key here so we can pass our special DamageBounds to the subMap method.
// We NEVER put any keys in this map that are not AESharedItemStacks.
private final Object2ObjectSortedMap<Object, IAEItemStack> records = new Object2ObjectAVLTreeMap<>( COMPARATOR );
@Override
public Collection<IAEItemStack> findFuzzy(final IAEItemStack filter, final FuzzyMode fuzzy) {
ItemStack itemStack = filter.getDefinition();
@Override
public Collection<IAEItemStack> findFuzzy( final IAEItemStack filter, final FuzzyMode fuzzy )
{
ItemStack itemStack = filter.getDefinition();
ItemDamageBound lowerBound = makeLowerBound(itemStack, fuzzy);
ItemDamageBound upperBound = makeUpperBound(itemStack, fuzzy);
Preconditions.checkState(lowerBound.itemDamage > upperBound.itemDamage);
ItemDamageBound lowerBound = makeLowerBound( itemStack, fuzzy );
ItemDamageBound upperBound = makeUpperBound( itemStack, fuzzy );
Preconditions.checkState( lowerBound.itemDamage > upperBound.itemDamage );
return this.records.subMap(lowerBound, upperBound).values();
}
return this.records.subMap( lowerBound, upperBound ).values();
}
@SuppressWarnings("unchecked")
@Override
Map<AESharedItemStack, IAEItemStack> getRecords() {
// We ensure on our end that we NEVER use anything but AESharedItemStack as the key in this map
return (Map<AESharedItemStack, IAEItemStack>) (Object) this.records;
}
@SuppressWarnings( "unchecked" )
@Override
Map<AESharedItemStack, IAEItemStack> getRecords()
{
// We ensure on our end that we NEVER use anything but AESharedItemStack as the key in this map
return (Map<AESharedItemStack, IAEItemStack>) (Object) this.records;
}
static class ItemDamageBound {
final int itemDamage;
static class ItemDamageBound
{
final int itemDamage;
public ItemDamageBound(int itemDamage) {
this.itemDamage = itemDamage;
}
}
public ItemDamageBound( int itemDamage )
{
this.itemDamage = itemDamage;
}
}
/**
* This comparator creates a strict and total ordering over all {@link AESharedItemStack} of the same item. To
* support selecting ranges of durability, it is defined for type {@link Object} and also accepts
* {@link ItemDamageBound} as an argument to compare against.
*/
static class SharedStackComparator implements Comparator<Object> {
@Override
public int compare(Object a, Object b) {
// Either argument can either be a damage bound or a shared item stack
// Since we never put damage bounds into the map as keys, only one
// of the two arguments can possibly be a bound
ItemDamageBound boundA = null;
AESharedItemStack stackA = null;
int itemDamageA;
if (a instanceof ItemDamageBound) {
boundA = (ItemDamageBound) a;
itemDamageA = boundA.itemDamage;
} else {
stackA = (AESharedItemStack) a;
itemDamageA = stackA.getItemDamage();
}
ItemDamageBound boundB = null;
AESharedItemStack stackB = null;
int itemDamageB;
if (b instanceof ItemDamageBound) {
boundB = (ItemDamageBound) b;
itemDamageB = boundB.itemDamage;
} else {
stackB = (AESharedItemStack) b;
itemDamageB = stackB.getItemDamage();
}
/**
* This comparator creates a strict and total ordering over all {@link AESharedItemStack} of the same item. To
* support selecting ranges of durability, it is defined for type {@link Object} and also accepts
* {@link ItemDamageBound} as an argument to compare against.
*/
static class SharedStackComparator implements Comparator<Object>
{
@Override
public int compare( Object a, Object b )
{
// Either argument can either be a damage bound or a shared item stack
// Since we never put damage bounds into the map as keys, only one
// of the two arguments can possibly be a bound
ItemDamageBound boundA = null;
AESharedItemStack stackA = null;
int itemDamageA;
if( a instanceof ItemDamageBound )
{
boundA = (ItemDamageBound) a;
itemDamageA = boundA.itemDamage;
}
else
{
stackA = (AESharedItemStack) a;
itemDamageA = stackA.getItemDamage();
}
ItemDamageBound boundB = null;
AESharedItemStack stackB = null;
int itemDamageB;
if( b instanceof ItemDamageBound )
{
boundB = (ItemDamageBound) b;
itemDamageB = boundB.itemDamage;
}
else
{
stackB = (AESharedItemStack) b;
itemDamageB = stackB.getItemDamage();
}
// When either argument is a damage bound, we just compare the damage values because it is used
// only to get a certain damage range out of the map.
if (boundA != null || boundB != null) {
return Integer.compare(itemDamageB, itemDamageA);
}
// When either argument is a damage bound, we just compare the damage values because it is used
// only to get a certain damage range out of the map.
if( boundA != null || boundB != null )
{
return Integer.compare( itemDamageB, itemDamageA );
}
ItemStack itemStackA = stackA.getDefinition();
ItemStack itemStackB = stackB.getDefinition();
Preconditions.checkState(itemStackA.getCount() == 1, "ItemStack#getCount() has to be 1");
Preconditions.checkArgument(itemStackB.getCount() == 1, "ItemStack#getCount() has to be 1");
ItemStack itemStackA = stackA.getDefinition();
ItemStack itemStackB = stackB.getDefinition();
Preconditions.checkState( itemStackA.getCount() == 1, "ItemStack#getCount() has to be 1" );
Preconditions.checkArgument( itemStackB.getCount() == 1, "ItemStack#getCount() has to be 1" );
if (itemStackA == itemStackB) {
return 0;
}
if( itemStackA == itemStackB )
{
return 0;
}
// Damaged items are sorted before undamaged items
final int damageValue = Integer.compare(itemDamageB, itemDamageA);
if (damageValue != 0) {
return damageValue;
}
// Damaged items are sorted before undamaged items
final int damageValue = Integer.compare( itemDamageB, itemDamageA );
if( damageValue != 0 )
{
return damageValue;
}
// As a final tie breaker, order by the object identity of the item stack
// While this will order seemingly at random, we only need the order of
// damage values to be predictable, while still having to satisfy the
// complete order requirements of the sorted map
return Long.compare(System.identityHashCode(itemStackA), System.identityHashCode(itemStackB));
}
}
// As a final tie breaker, order by the object identity of the item stack
// While this will order seemingly at random, we only need the order of
// damage values to be predictable, while still having to satisfy the
// complete order requirements of the sorted map
return Long.compare( System.identityHashCode( itemStackA ), System.identityHashCode( itemStackB ) );
}
}
/**
* Minecraft reverses the damage values. So anything with a damage of 0 is undamaged and increases the more damaged
* the item is.
* <p>
* Further the used subMap follows [MAX_DAMAGE, MIN_DAMAGE), so to include undamaged items, we have to start with a
* lower damage value than 0, while it is fine to use {@link ItemStack#getMaxDamage()} for the upper bound.
*/
private static final int MIN_DAMAGE_VALUE = -1;
/**
* Minecraft reverses the damage values. So anything with a damage of 0 is undamaged and increases the more damaged
* the item is.
* <p>
* Further the used subMap follows [MAX_DAMAGE, MIN_DAMAGE), so to include undamaged items, we have to start with a
* lower damage value than 0, while it is fine to use {@link ItemStack#getMaxDamage()} for the upper bound.
*/
private static final int MIN_DAMAGE_VALUE = -1;
/*
* Keep in mind that the stack order is from most damaged to least damaged, so this lower bound will actually be a
* higher number than the upper bound.
*/
static ItemDamageBound makeLowerBound(final ItemStack stack, final FuzzyMode fuzzy)
{
Preconditions.checkState( stack.getItem().isDamageable() , "Item#isDamageable() has to be true" );
/*
* Keep in mind that the stack order is from most damaged to least damaged, so this lower bound will actually be a
* higher number than the upper bound.
*/
static ItemDamageBound makeLowerBound( final ItemStack stack, final FuzzyMode fuzzy )
{
Preconditions.checkState( stack.getItem().isDamageable() || ( Platform.isGTDamageableItem( stack.getItem() ) ), "Item#isDamageable() has to be true" );
int damage;
if( fuzzy == FuzzyMode.IGNORE_ALL )
{
if( stack.getMaxDamage() == 0 )
{
damage = stack.getItemDamage();
}
else
{
damage = stack.getMaxDamage();
}
}
else
{
final int breakpoint = fuzzy.calculateBreakPoint( stack.getMaxDamage() );
damage = stack.getItemDamage() <= breakpoint ? breakpoint : stack.getMaxDamage();
}
int damage;
int maxDamage;
if( Platform.isIC2DamageableItem( stack.getItem() ) )
{
maxDamage = ( (ICustomDamageItem) stack.getItem() ).getMaxCustomDamage( stack );
damage = ( (ICustomDamageItem) stack.getItem() ).getCustomDamage( stack );
}
else if( Platform.isGTDamageableItem( stack.getItem() ) )
{
maxDamage = ( (IToolItem) stack.getItem() ).getMaxItemDamage( stack );
damage = ( (IToolItem) stack.getItem() ).getItemDamage( stack );
}
else
{
maxDamage = stack.getMaxDamage();
damage = stack.getItemDamage();
}
return new ItemDamageBound( damage );
}
if( fuzzy == FuzzyMode.IGNORE_ALL )
{
if( maxDamage != 0 )
{
damage = maxDamage;
}
}
else
{
final int breakpoint = fuzzy.calculateBreakPoint( maxDamage );
damage = damage <= breakpoint ? breakpoint : maxDamage;
}
/*
* Keep in mind that the stack order is from most damaged to least damaged, so this upper bound will actually be a
* lower number than the lower bound. It also is exclusive.
*/
static ItemDamageBound makeUpperBound(final ItemStack stack, final FuzzyMode fuzzy) {
Preconditions.checkState(stack.getItem().isDamageable() , "Item#isDamageable() has to be true");
return new ItemDamageBound( damage );
}
int damage;
if (fuzzy == FuzzyMode.IGNORE_ALL) {
damage = MIN_DAMAGE_VALUE;
} else {
final int breakpoint = fuzzy.calculateBreakPoint(stack.getMaxDamage());
damage = stack.getItemDamage() <= breakpoint ? MIN_DAMAGE_VALUE : breakpoint;
}
/*
* Keep in mind that the stack order is from most damaged to least damaged, so this upper bound will actually be a
* lower number than the lower bound. It also is exclusive.
*/
static ItemDamageBound makeUpperBound( final ItemStack stack, final FuzzyMode fuzzy )
{
Preconditions.checkState( stack.getItem().isDamageable() || ( Platform.isGTDamageableItem( stack.getItem() ) ), "Item#isDamageable() has to be true" );
return new ItemDamageBound(damage);
}
int damage;
if( fuzzy == FuzzyMode.IGNORE_ALL )
{
damage = MIN_DAMAGE_VALUE;
}
else
{
int maxDamage;
if( Platform.isIC2DamageableItem( stack.getItem() ) )
{
maxDamage = ( (ICustomDamageItem) stack.getItem() ).getMaxCustomDamage( stack );
damage = ( (ICustomDamageItem) stack.getItem() ).getCustomDamage( stack );
}
else if( Platform.isGTDamageableItem( stack.getItem() ) )
{
maxDamage = ( (IToolItem) stack.getItem() ).getMaxItemDamage( stack );
damage = ( (IToolItem) stack.getItem() ).getItemDamage( stack );
}
else
{
maxDamage = stack.getMaxDamage();
damage = stack.getItemDamage();
}
final int breakpoint = fuzzy.calculateBreakPoint( maxDamage );
damage = damage <= breakpoint ? MIN_DAMAGE_VALUE : breakpoint;
}
return new ItemDamageBound( damage );
}
}
+177 -141
View File
@@ -26,7 +26,6 @@ import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicInteger;
import appeng.util.Platform;
import gregtech.common.items.MetaTool;
import net.minecraft.item.Item;
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
@@ -36,180 +35,217 @@ import appeng.api.config.FuzzyMode;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
public final class ItemList implements IItemList<IAEItemStack> {
private final Reference2ObjectMap<Item, ItemVariantList> records = new Reference2ObjectOpenHashMap<>();
/**
* We increment this version field everytime an attempt to mutate this item list (or potentially one of its
* sub-lists) is made. Iterators will copy the version when they are created and compare it against the current
* version whenever they advance to trigger a {@link ConcurrentModificationException}.
*/
private final AtomicInteger version = new AtomicInteger(0);
public final class ItemList implements IItemList<IAEItemStack>
{
@Override
public IAEItemStack findPrecise(final IAEItemStack itemStack) {
if (itemStack == null) {
return null;
}
private final Reference2ObjectMap<Item, ItemVariantList> records = new Reference2ObjectOpenHashMap<>();
/**
* We increment this version field everytime an attempt to mutate this item list (or potentially one of its
* sub-lists) is made. Iterators will copy the version when they are created and compare it against the current
* version whenever they advance to trigger a {@link ConcurrentModificationException}.
*/
private final AtomicInteger version = new AtomicInteger( 0 );
ItemVariantList record = this.records.get(itemStack.getItem());
return record != null ? record.findPrecise(itemStack) : null;
}
@Override
public IAEItemStack findPrecise( final IAEItemStack itemStack )
{
if( itemStack == null )
{
return null;
}
@Override
public Collection<IAEItemStack> findFuzzy(final IAEItemStack filter, final FuzzyMode fuzzy) {
if (filter == null) {
return Collections.emptyList();
}
ItemVariantList record = this.records.get( itemStack.getItem() );
return record != null ? record.findPrecise( itemStack ) : null;
}
ItemVariantList record = this.records.get(filter.getItem());
return record != null ? record.findFuzzy(filter, fuzzy) : Collections.emptyList();
}
@Override
public Collection<IAEItemStack> findFuzzy( final IAEItemStack filter, final FuzzyMode fuzzy )
{
if( filter == null )
{
return Collections.emptyList();
}
@Override
public boolean isEmpty() {
return !this.iterator().hasNext();
}
ItemVariantList record = this.records.get( filter.getItem() );
return record != null ? record.findFuzzy( filter, fuzzy ) : Collections.emptyList();
}
@Override
public void add(final IAEItemStack itemStack) {
version.incrementAndGet();
@Override
public boolean isEmpty()
{
return !this.iterator().hasNext();
}
if (itemStack == null) {
return;
}
@Override
public void add( final IAEItemStack itemStack )
{
version.incrementAndGet();
this.getOrCreateRecord(itemStack.getItem()).add(itemStack);
}
if( itemStack == null )
{
return;
}
@Override
public void addStorage(final IAEItemStack itemStack) {
version.incrementAndGet();
this.getOrCreateRecord( itemStack.getItem() ).add( itemStack );
}
if (itemStack == null) {
return;
}
@Override
public void addStorage( final IAEItemStack itemStack )
{
version.incrementAndGet();
this.getOrCreateRecord(itemStack.getItem()).addStorage(itemStack);
}
if( itemStack == null )
{
return;
}
@Override
public void addCrafting(final IAEItemStack itemStack) {
version.incrementAndGet();
this.getOrCreateRecord( itemStack.getItem() ).addStorage( itemStack );
}
if (itemStack == null) {
return;
}
@Override
public void addCrafting( final IAEItemStack itemStack )
{
version.incrementAndGet();
this.getOrCreateRecord(itemStack.getItem()).addCrafting(itemStack);
}
if( itemStack == null )
{
return;
}
@Override
public void addRequestable(final IAEItemStack itemStack) {
version.incrementAndGet();
this.getOrCreateRecord( itemStack.getItem() ).addCrafting( itemStack );
}
if (itemStack == null) {
return;
}
@Override
public void addRequestable( final IAEItemStack itemStack )
{
version.incrementAndGet();
this.getOrCreateRecord(itemStack.getItem()).addRequestable(itemStack);
}
if( itemStack == null )
{
return;
}
@Override
public IAEItemStack getFirstItem() {
for (final IAEItemStack stackType : this) {
return stackType;
}
this.getOrCreateRecord( itemStack.getItem() ).addRequestable( itemStack );
}
return null;
}
@Override
public IAEItemStack getFirstItem()
{
for( final IAEItemStack stackType : this )
{
return stackType;
}
@Override
public int size() {
int size = 0;
for (ItemVariantList entry : records.values()) {
size += entry.size();
}
return null;
}
return size;
}
@Override
public int size()
{
int size = 0;
for( ItemVariantList entry : records.values() )
{
size += entry.size();
}
@Override
public Iterator<IAEItemStack> iterator() {
return new ChainedIterator(this.records.values().iterator(), version);
}
return size;
}
@Override
public void resetStatus() {
for (final IAEItemStack i : this) {
i.reset();
}
}
@Override
public Iterator<IAEItemStack> iterator()
{
return new ChainedIterator( this.records.values().iterator(), version );
}
private ItemVariantList getOrCreateRecord(Item item) {
return this.records.computeIfAbsent(item, this::makeRecordMap);
}
@Override
public void resetStatus()
{
for( final IAEItemStack i : this )
{
i.reset();
}
}
private ItemVariantList makeRecordMap(Item item) {
if (item.isDamageable() ) {
return new FuzzyItemVariantList();
} else {
return new NormalItemVariantList();
}
}
private ItemVariantList getOrCreateRecord( Item item )
{
return this.records.computeIfAbsent( item, this::makeRecordMap );
}
/**
* Iterates over multiple item lists as if they were one list.
*/
private static class ChainedIterator implements Iterator<IAEItemStack> {
private ItemVariantList makeRecordMap( Item item )
{
if( item.isDamageable() || Platform.isGTDamageableItem( item ) )
{
return new FuzzyItemVariantList();
}
else
{
return new NormalItemVariantList();
}
}
private final AtomicInteger parentVersion;
private final int version;
private final Iterator<ItemVariantList> parent;
private Iterator<IAEItemStack> next;
/**
* Iterates over multiple item lists as if they were one list.
*/
private static class ChainedIterator implements Iterator<IAEItemStack>
{
public ChainedIterator(Iterator<ItemVariantList> iterator, AtomicInteger parentVersion) {
this.parent = iterator;
this.parentVersion = parentVersion;
this.version = parentVersion.get();
this.ensureItems();
}
private final AtomicInteger parentVersion;
private final int version;
private final Iterator<ItemVariantList> parent;
private Iterator<IAEItemStack> next;
@Override
public boolean hasNext() {
return next != null && next.hasNext();
}
public ChainedIterator( Iterator<ItemVariantList> iterator, AtomicInteger parentVersion )
{
this.parent = iterator;
this.parentVersion = parentVersion;
this.version = parentVersion.get();
this.ensureItems();
}
@Override
public IAEItemStack next() {
if (this.next == null) {
throw new NoSuchElementException();
}
if (this.version != this.parentVersion.get()) {
throw new ConcurrentModificationException();
}
@Override
public boolean hasNext()
{
return next != null && next.hasNext();
}
IAEItemStack result = this.next.next();
this.ensureItems();
return result;
}
@Override
public IAEItemStack next()
{
if( this.next == null )
{
throw new NoSuchElementException();
}
if( this.version != this.parentVersion.get() )
{
throw new ConcurrentModificationException();
}
private void ensureItems() {
if (hasNext()) {
return; // Still items left in the current one
}
IAEItemStack result = this.next.next();
this.ensureItems();
return result;
}
// Find the next iterator willing to return some items...
while (this.parent.hasNext()) {
this.next = this.parent.next().iterator();
private void ensureItems()
{
if( hasNext() )
{
return; // Still items left in the current one
}
if (this.next.hasNext()) {
return; // Found one!
}
}
// Find the next iterator willing to return some items...
while ( this.parent.hasNext() )
{
this.next = this.parent.next().iterator();
// No more items
this.next = null;
}
}
if( this.next.hasNext() )
{
return; // Found one!
}
}
// No more items
this.next = null;
}
}
}
@@ -102,7 +102,7 @@ gui.appliedenergistics2.FluidTunnel=Fluid
gui.appliedenergistics2.RedstoneTunnel=Redstone
gui.appliedenergistics2.EUTunnel=EU
gui.appliedenergistics2.FETunnel=FE
gui.appliedenergistics2.GTCEUTunnel=GTCEU
gui.appliedenergistics2.GTEUTunnel=GTEU
gui.appliedenergistics2.LightTunnel=Light
gui.appliedenergistics2.OCTunnel=OpenComputers
gui.appliedenergistics2.PressureTunnel=Pressure
@@ -376,7 +376,7 @@ gui.tooltips.appliedenergistics2.HighlightInterface=Highlight interface
gui.appliedenergistics2.units.appliedenergstics=AE
gui.appliedenergistics2.units.ic2=Energy Units
gui.appliedenergistics2.units.rf=Redstone Flux
gui.appliedenergistics2.units.gtceu=GTCEU
gui.appliedenergistics2.units.gteu=GTEU
// Colors
gui.appliedenergistics2.White=White
@@ -1,6 +0,0 @@
{
"parent": "appliedenergistics2:item/part/p2p_tunnel",
"textures": {
"type": "appliedenergistics2:parts/p2p/power_gtceu"
}
}
@@ -0,0 +1,6 @@
{
"parent": "appliedenergistics2:item/part/p2p_tunnel",
"textures": {
"type": "appliedenergistics2:parts/p2p/power_gteu"
}
}
@@ -1,6 +0,0 @@
{
"parent": "appliedenergistics2:part/p2p/p2p_tunnel_base",
"textures": {
"type": "appliedenergistics2:parts/p2p/power_gtceu"
}
}
@@ -0,0 +1,6 @@
{
"parent": "appliedenergistics2:part/p2p/p2p_tunnel_base",
"textures": {
"type": "appliedenergistics2:parts/p2p/power_gteu"
}
}