Compare commits

...

39 Commits

Author SHA1 Message Date
PrototypeTrousers 517bd77df7 yet another try at energy issues
fix requesters not being added to the energy grid


partially revert the energy 'fixes'


potential desync on item count


energy and items change
2021-09-17 00:09:49 -03:00
PrototypeTrousers 19f928a9a5 fluid pass 2021-09-13 04:22:52 -03:00
PrototypeTrousers 73251a0fe5 more item count changes.... 2021-09-13 02:10:28 -03:00
PrototypeTrousers 9335daff7d Revert "fixes item showing incorrect amounts"
This reverts commit 618e9390c6.
2021-09-11 22:48:45 -03:00
PrototypeTrousers cc5377d53b fluid storage bus handler cache tweaks and simplify energy cache 2021-09-06 23:51:32 -03:00
Salomão 059f20d801 yet another try at fixing power issues 2021-09-05 20:28:37 -03:00
Salomão d229570495 try to fix energy issues again
fix issue with voiding p2p parts when shift-right clicking with a memory card
2021-09-04 18:59:46 -03:00
PrototypeTrousers c284748b6c fix p2p not updating properly on memory card loading 2021-09-02 20:42:02 -03:00
PrototypeTrousers 880a9c8821 another case of wrong item count caused by weak reset logic overriding
a full reset needed
2021-09-01 16:11:45 -03:00
PrototypeTrousers c68c02ef3b more cases of wrong item counting fixed 2021-08-26 22:03:23 -03:00
PrototypeTrousers 89c4d2736c borrowed some fancy, colored, fluid rendering from gregicality
thank you @Yefancy
2021-08-23 22:35:26 -03:00
PrototypeTrousers 01778794e5 try to fix #51 2021-08-22 23:59:02 -03:00
PrototypeTrousers 8f2a06e457 fix #49. you can now actually clear storage and conversion monitors 2021-08-20 23:26:33 -03:00
PrototypeTrousers 2d71b75019 actually fix it 2021-08-17 07:46:47 -03:00
PrototypeTrousers 9f09cd04d4 enforce cache reset of storage bus attached to interfaces were configs
changed
2021-08-16 21:55:35 -03:00
PrototypeTrousers b041fae0d5 fix storage/monitors wrong item count and interactions 2021-08-16 19:26:25 -03:00
Salomão c466a0e00e fix items in level emitters with crafting cards not showing up 2021-08-14 09:44:47 -03:00
PrototypeTrousers 618e9390c6 fixes item showing incorrect amounts 2021-08-13 00:17:53 -03:00
PrototypeTrousers 9a71bfb0f0 hash drawers handler by the amount of slots 2021-08-10 09:06:18 -03:00
PrototypeTrousers 9680123906 fix JEI targeting disabled slots as valid 2021-08-06 06:25:12 -03:00
PrototypeTrousers 87730894e9 Update CHANGES.md 2021-08-05 21:36:49 -03:00
PrototypeTrousers 71c944daea fix fluid storagebus NPE crash 2021-08-04 20:49:38 -03:00
PrototypeTrousers e96b4a698a fluid containers can now be drained/filled from fluid interfaces 2021-08-04 19:38:00 -03:00
PrototypeTrousers 1d5465a4b8 partially revert fda8c8 2021-08-04 09:28:47 -03:00
PrototypeTrousers 09cbfe96d6 fix NPE when configuring storage busses 2021-08-01 17:36:23 -03:00
PrototypeTrousers cbdad7c58e hopefully fix storage busses for good
1
2021-07-31 23:05:59 -03:00
PrototypeTrousers 6be96956a9 small optimization to import/export busses 2021-07-30 23:26:42 -03:00
PrototypeTrousers e376e002e9 actually fix #43 ? .... 2021-07-30 07:51:57 -03:00
PrototypeTrousers 0b9df31d4e fix broken recipes resulting in item dupes 2021-07-28 19:46:42 -03:00
PrototypeTrousers cef6dbf0d7 fix copy-paste error in the fluid storage bus constructor 2021-07-27 19:32:59 -03:00
Salomão e4af7b1947 fix adapters insert-only mode still reporting items 2021-07-27 12:51:24 -03:00
Salomão 6eadb8f861 fix IO-Port transfer stopping too soon 2021-07-27 11:10:45 -03:00
PrototypeTrousers b6b6a83563 do the same for fluid storage bus 2021-07-26 20:34:15 -03:00
PrototypeTrousers 32ab4c6af4 Merge remote-tracking branch 'PrototypeTrousers/AE2-Omnifactory' into AE2-Omnifactory 2021-07-26 18:25:24 -03:00
PrototypeTrousers fda8c87410 attempts to fix #42 and #43 2021-07-26 18:25:08 -03:00
PrototypeTrousers 389e060707 Merge pull request #41 from BalaM314/patch-1
Fix #27
2021-07-23 10:40:01 -03:00
BalaM314 0942a90ef4 Fix #27
Not sure exactly what method is causing a crash, but added a catch to just say it is located in another dimension
2021-07-23 15:11:07 +05:30
PrototypeTrousers 8cef06512a restore breaking API change 2021-07-22 21:50:56 -03:00
PrototypeTrousers 8e4658be20 fix power not going to sub-networks
renamed variables
2021-07-18 17:52:01 -03:00
42 changed files with 926 additions and 605 deletions
+13 -2
View File
@@ -15,6 +15,10 @@ Fixes:
- Exclusive Blocking mode for GTCE ( shapes, molds and configured circuits do not block GTCE machines ) - Exclusive Blocking mode for GTCE ( shapes, molds and configured circuits do not block GTCE machines )
- Blocking modes default to block on any item in the iventory the entity exposes - Blocking modes default to block on any item in the iventory the entity exposes
- Fuzzy includes items that report that they're damageable, but report a maxDamage of 0 ( auto-crafting of basic capacitors -> resonant capacitors is now possible ) <- Broken item implementation. - Fuzzy includes items that report that they're damageable, but report a maxDamage of 0 ( auto-crafting of basic capacitors -> resonant capacitors is now possible ) <- Broken item implementation.
- Fix CME exceptions on the energy grid
- Fix AE going offline even with enough power by extracting from the local buffer always last
- Fix IO-Port copying craftable flag into items
- Fix NBT of old items not clearing on drives that reached 64 types once
Performance: Performance:
@@ -24,6 +28,9 @@ Performance:
- Count items set in interfaces before queuing crafting for them needlessly - Count items set in interfaces before queuing crafting for them needlessly
- Backported b7ca98d ( Avoid copying items on simulated item extraction ) - Backported b7ca98d ( Avoid copying items on simulated item extraction )
- Cache some level emitters functions - Cache some level emitters functions
- Reduced import bus insert simulation to 1 before real insertion (if possible)
- Backported itemlist re-implementation along with pattern changes to avoid CraftingManager fallback issues
- Instead of recalculating all the content of the network on every change, track the changes properly and apply them to the cached list of items
QOL: QOL:
@@ -31,7 +38,7 @@ QOL:
- Added bar on the interface terminal that search by inputs ( The one on the LEFT, also searchs by interface name ) - Added bar on the interface terminal that search by inputs ( The one on the LEFT, also searchs by interface name )
- Shortcut to molecular assemblers with free slots on the terminal interface by @Theisyat - Shortcut to molecular assemblers with free slots on the terminal interface by @Theisyat
- Toggle button on interface terminal to hide full interfaces - Toggle button on interface terminal to hide full interfaces
- JEI "U""R" and "A" (Usages/Recipes/Bookmark) now work on the Crafting Status GUI. ( the one that shows the total items to craft, and whats missing) - JEI "U", "R" and "A" (Usages/Recipes/Bookmark) now work on the Crafting Status GUI. ( the one that shows the total items to craft, and whats missing)
- Patterns can now be made with items currently showing on JEI. ( This is overriden by Just Enough Energistics. ) - Patterns can now be made with items currently showing on JEI. ( This is overriden by Just Enough Energistics. )
- Added multiplier buttons to processing pattern gui - Added multiplier buttons to processing pattern gui
- Switched crafting terminal JEI search to fuzzy mode. If the recipe uses a damageable item, AE will try to grab it ( damaged tools ) - Switched crafting terminal JEI search to fuzzy mode. If the recipe uses a damageable item, AE will try to grab it ( damaged tools )
@@ -39,7 +46,11 @@ QOL:
- Encoded patterns can be draggred on the interface terminal. - Encoded patterns can be draggred on the interface terminal.
- Storage Monitor and Conversion Monitor now also ccepts fluids - Storage Monitor and Conversion Monitor now also ccepts fluids
- Draggable JEI ghost items (also works on bookmarked items. SHIFT + Click will move the hovered item into the first free target slot) - Draggable JEI ghost items (also works on bookmarked items. SHIFT + Click will move the hovered item into the first free target slot)
-JEI auto switches between crafting and processing patterns - JEI auto switches between crafting and processing patterns
- GTCE Blocking mode work through phantom itemfaces
- Shift-clicking blank patterns into the pattern terminal will try to fill the blank pattern slots first
- Mismached simulated/real item count ( most often due to compacting drawers ) will now tell the player wich item cause the failure when trying to start a craft
- Added 'pattern expansion' cards that adds an extra row of patterns to interfaces. up to 3 card on an interface. (each card will increase the interface idle power draw by 4 times)
HOTKEYS: HOTKEYS:
+1 -1
View File
@@ -3,7 +3,7 @@ aechannel=stable
aebuild=7 aebuild=7
aegroup=appeng aegroup=appeng
aebasename=appliedenergistics2 aebasename=appliedenergistics2
trousers=omni-fixes-v45 trousers=omni-fixes-v46aa
######################################################### #########################################################
# Versions # # Versions #
@@ -47,5 +47,5 @@ public interface IStackWatcherHost
* @param diffStack new stack * @param diffStack new stack
* @param chan storage channel * @param chan storage channel
*/ */
void onStackChange( IAEStack<?> diffStack, IStorageChannel<?> chan ); void onStackChange( IItemList<?> o, IAEStack<?> fullStack, IAEStack<?> diffStack, IActionSource src, IStorageChannel<?> chan );
} }
@@ -51,6 +51,7 @@ public interface IStorageGrid extends IGridCache, IStorageMonitorable
* @param input injected items * @param input injected items
*/ */
void postAlterationOfStoredItems( IStorageChannel<?> chan, Iterable<? extends IAEStack<?>> input, IActionSource src ); void postAlterationOfStoredItems( IStorageChannel<?> chan, Iterable<? extends IAEStack<?>> input, IActionSource src );
void postCraftablesChanges( IStorageChannel<?> chan, Iterable<? extends IAEStack<?>> input, IActionSource src);
/** /**
* Used to add a cell provider to the storage system * Used to add a cell provider to the storage system
@@ -237,7 +237,11 @@ public class GuiInterfaceTerminal extends AEBaseGui
int interfaceDim = dimHashMap.get( guiButtonHashMap.get( this.selectedButton ) ); int interfaceDim = dimHashMap.get( guiButtonHashMap.get( this.selectedButton ) );
if( playerDim != interfaceDim ) if( playerDim != interfaceDim )
{ {
mc.player.sendStatusMessage( new TextComponentString( "Interface located at dimension: " + interfaceDim + " [" + DimensionManager.getWorld( interfaceDim ).provider.getDimensionType().getName() + "] and cant be highlighted" ), false ); try {
mc.player.sendStatusMessage( new TextComponentString( "Interface located at dimension: " + interfaceDim + " [" + DimensionManager.getWorld( interfaceDim ).provider.getDimensionType().getName() + "] and cant be highlighted" ), false );
} catch(Exception e){
mc.player.sendStatusMessage( new TextComponentString( "Interface is located in another dimension and cannot be highlighted" ), false );
}
} }
else else
{ {
@@ -270,12 +270,15 @@ public class GuiUpgradeable extends AEBaseGui implements IJEIGhostIngredients
@Override @Override
public Rectangle getArea() public Rectangle getArea()
{ {
if( slot instanceof SlotFake ) if( slot instanceof SlotFake && ( (SlotFake) slot ).isSlotEnabled() )
{
return new Rectangle( getGuiLeft() + ( (SlotFake) slot ).xPos, getGuiTop() + ( (SlotFake) slot ).yPos, 16, 16 ); return new Rectangle( getGuiLeft() + ( (SlotFake) slot ).xPos, getGuiTop() + ( (SlotFake) slot ).yPos, 16, 16 );
else }
else if( slot instanceof GuiFluidSlot && ( (GuiFluidSlot) slot ).isSlotEnabled() )
{ {
return new Rectangle( getGuiLeft() + ( (GuiFluidSlot) slot ).xPos(), getGuiTop() + ( (GuiFluidSlot) slot ).yPos(), 16, 16 ); return new Rectangle( getGuiLeft() + ( (GuiFluidSlot) slot ).xPos(), getGuiTop() + ( (GuiFluidSlot) slot ).yPos(), 16, 16 );
} }
return new Rectangle();
} }
@Override @Override
@@ -284,7 +287,7 @@ public class GuiUpgradeable extends AEBaseGui implements IJEIGhostIngredients
PacketInventoryAction p = null; PacketInventoryAction p = null;
try try
{ {
if( slot instanceof SlotFake ) if( slot instanceof SlotFake && ( (SlotFake) slot ).isSlotEnabled() )
{ {
if( finalItemStack.isEmpty() && finalFluidStack != null ) if( finalItemStack.isEmpty() && finalFluidStack != null )
{ {
@@ -10,9 +10,9 @@ import net.minecraft.item.ItemStack;
public abstract class GuiCustomSlot extends Gui implements ITooltip public abstract class GuiCustomSlot extends Gui implements ITooltip
{ {
private final int x; protected final int x;
private final int y; protected final int y;
private final int id; protected final int id;
public GuiCustomSlot( final int id, final int x, final int y ) public GuiCustomSlot( final int id, final int x, final int y )
{ {
@@ -22,9 +22,10 @@ package appeng.client.render;
import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEFluidStack;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.RenderItem; import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
@@ -32,6 +33,7 @@ import appeng.api.storage.data.IAEItemStack;
import appeng.util.IWideReadableNumberConverter; import appeng.util.IWideReadableNumberConverter;
import appeng.util.ReadableNumberConverter; import appeng.util.ReadableNumberConverter;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import org.lwjgl.opengl.GL11;
/** /**
@@ -121,6 +123,49 @@ public class TesrRenderHelper
} }
} }
public static void renderFluid2d( FluidStack fluidStack, float scale )
{
if( fluidStack != null )
{
GlStateManager.pushMatrix();
int color = fluidStack.getFluid().getColor( fluidStack );
float r = ( color >> 16 & 255 ) / 255.0f;
float g = ( color >> 8 & 255 ) / 255.0f;
float b = ( color & 255 ) / 255.0f;
TextureAtlasSprite sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite( fluidStack.getFluid().getStill( fluidStack ).toString() );
GlStateManager.enableBlend();
GlStateManager.blendFunc( GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA );
GlStateManager.disableAlpha();
GlStateManager.disableLighting();
Minecraft.getMinecraft().getTextureManager().bindTexture( TextureMap.LOCATION_BLOCKS_TEXTURE );
Tessellator tess = Tessellator.getInstance();
BufferBuilder buf = tess.getBuffer();
float width = 0.4f;
float height = 0.4f;
float alpha = 1.0f;
float z = 0.0001f;
float x = -0.20f;
float y = -0.25f;
buf.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR );
double uMin = sprite.getInterpolatedU( 16D - width * 16D ), uMax = sprite.getInterpolatedU( width * 16D );
double vMin = sprite.getMinV(), vMax = sprite.getInterpolatedV( height * 16D );
buf.pos( x, y, z ).tex( uMin, vMin ).color( r, g, b, alpha ).endVertex();
buf.pos( x, y + height, z ).tex( uMin, vMax ).color( r, g, b, alpha ).endVertex();
buf.pos( x + width, y + height, z ).tex( uMax, vMax ).color( r, g, b, alpha ).endVertex();
buf.pos( x + width, y, z ).tex( uMax, vMin ).color( r, g, b, alpha ).endVertex();
tess.draw();
GlStateManager.enableLighting();
GlStateManager.enableAlpha();
GlStateManager.disableBlend();
GlStateManager.color( 1F, 1F, 1F, 1F );
GlStateManager.popMatrix();
}
}
/** /**
* Render an item in 2D and the given text below it. * Render an item in 2D and the given text below it.
* *
@@ -147,9 +192,9 @@ public class TesrRenderHelper
public static void renderFluid2dWithAmount( IAEFluidStack fluidStack, float scale, float spacing ) public static void renderFluid2dWithAmount( IAEFluidStack fluidStack, float scale, float spacing )
{ {
final ItemStack renderStack = fluidStack.asItemStackRepresentation(); final FluidStack renderStack = fluidStack.getFluidStack();
TesrRenderHelper.renderItem2d( renderStack, scale ); TesrRenderHelper.renderFluid2d( renderStack, scale );
final long stackSize = fluidStack.getStackSize() / 1000; final long stackSize = fluidStack.getStackSize() / 1000;
final String renderedStackSize = NUMBER_CONVERTER.toWideReadableForm( stackSize ) + "B"; final String renderedStackSize = NUMBER_CONVERTER.toWideReadableForm( stackSize ) + "B";
@@ -245,7 +245,10 @@ public class PacketJEIRecipe extends AppEngPacket
if( out != null ) if( out != null )
{ {
out.setStackSize( recipe[x][y].getCount() ); if (!cct.useRealItems())
{
out.setStackSize( recipe[x][y].getCount() );
}
currentItem = out.createItemStack(); currentItem = out.createItemStack();
} }
} }
@@ -19,6 +19,7 @@
package appeng.core.sync.packets; package appeng.core.sync.packets;
import appeng.fluids.container.ContainerFluidInterface;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
@@ -90,5 +91,9 @@ public class PacketTargetFluidStack extends AppEngPacket
{ {
( (ContainerFluidTerminal) player.openContainer ).setTargetStack( this.stack ); ( (ContainerFluidTerminal) player.openContainer ).setTargetStack( this.stack );
} }
else if( player.openContainer instanceof ContainerFluidInterface )
{
( (ContainerFluidInterface) player.openContainer ).setTargetStack( this.stack );
}
} }
} }
@@ -305,7 +305,7 @@ public class CraftingTreeProcess
void getPlan( final IItemList<IAEItemStack> plan ) void getPlan( final IItemList<IAEItemStack> plan )
{ {
for( IAEItemStack i : this.details.getCondensedOutputs() ) for( IAEItemStack i : this.details.getOutputs() )
{ {
i = i.copy(); i = i.copy();
i.setCountRequestable( i.getStackSize() * this.crafts ); i.setCountRequestable( i.getStackSize() * this.crafts );
@@ -21,6 +21,9 @@ package appeng.fluids.client.gui;
import java.io.IOException; import java.io.IOException;
import appeng.api.util.IConfigManager;
import appeng.client.gui.widgets.GuiCustomSlot;
import appeng.util.IConfigManagerHost;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
@@ -38,11 +41,12 @@ import appeng.fluids.helper.IFluidInterfaceHost;
import appeng.fluids.util.IAEFluidTank; import appeng.fluids.util.IAEFluidTank;
public class GuiFluidInterface extends GuiUpgradeable public class GuiFluidInterface extends GuiUpgradeable implements IConfigManagerHost
{ {
public final static int ID_BUTTON_TANK = 222; public final static int ID_BUTTON_TANK = 222;
private final IFluidInterfaceHost host; private final IFluidInterfaceHost host;
private final ContainerFluidInterface container;
private GuiTabButton priority; private GuiTabButton priority;
public GuiFluidInterface( final InventoryPlayer ip, final IFluidInterfaceHost te ) public GuiFluidInterface( final InventoryPlayer ip, final IFluidInterfaceHost te )
@@ -50,6 +54,8 @@ public class GuiFluidInterface extends GuiUpgradeable
super( new ContainerFluidInterface( ip, te ) ); super( new ContainerFluidInterface( ip, te ) );
this.ySize = 231; this.ySize = 231;
this.host = te; this.host = te;
( this.container = (ContainerFluidInterface) this.inventorySlots ).setGui( this );
} }
@Override @Override
@@ -62,9 +68,7 @@ public class GuiFluidInterface extends GuiUpgradeable
for( int i = 0; i < DualityFluidInterface.NUMBER_OF_TANKS; ++i ) for( int i = 0; i < DualityFluidInterface.NUMBER_OF_TANKS; ++i )
{ {
final GuiFluidTank guiTank = new GuiFluidTank( fluidTank, i, DualityFluidInterface.NUMBER_OF_TANKS + i, this.getGuiLeft() + 35 + 18 * i, this this.guiSlots.add( new GuiFluidTank( fluidTank, i, DualityFluidInterface.NUMBER_OF_TANKS + i, 36 + 18 * i, 53, 16, 68 ) );
.getGuiTop() + 53, 16, 68 );
this.buttonList.add( guiTank );
this.guiSlots.add( new GuiFluidSlot( configFluids, i, i, 35 + 18 * i, 35 ) ); this.guiSlots.add( new GuiFluidSlot( configFluids, i, i, 35 + 18 * i, 35 ) );
} }
@@ -104,9 +108,33 @@ public class GuiFluidInterface extends GuiUpgradeable
} }
} }
@Override
protected void mouseClicked( int xCoord, int yCoord, int btn ) throws IOException
{
for( GuiCustomSlot slot : this.guiSlots )
{
if( slot instanceof GuiFluidTank )
{
if( this.isPointInRegion( slot.xPos(), slot.yPos(), slot.getWidth(), slot.getHeight(), xCoord, yCoord ) && slot.canClick( this.mc.player ) )
{
this.container.setTargetStack( ( (GuiFluidTank) slot ).getFluidStack() );
slot.slotClicked( this.mc.player.inventory.getItemStack(), btn );
return;
}
}
}
super.mouseClicked( xCoord, yCoord, btn );
}
@Override @Override
protected boolean drawUpgrades() protected boolean drawUpgrades()
{ {
return false; return false;
} }
@Override
public void updateSetting( IConfigManager manager, Enum settingName, Enum newValue )
{
}
} }
@@ -19,42 +19,50 @@
package appeng.fluids.client.gui.widgets; package appeng.fluids.client.gui.widgets;
import appeng.client.gui.widgets.GuiCustomSlot;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketInventoryAction;
import appeng.helpers.InventoryAction;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.fml.relauncher.SideOnly;
import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEFluidStack;
import appeng.api.util.AEColor;
import appeng.client.gui.widgets.ITooltip; import appeng.client.gui.widgets.ITooltip;
import appeng.fluids.util.IAEFluidTank; import appeng.fluids.util.IAEFluidTank;
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
public class GuiFluidTank extends GuiButton implements ITooltip public class GuiFluidTank extends GuiCustomSlot implements ITooltip
{ {
private final IAEFluidTank tank; private final IAEFluidTank tank;
private final int slot; private final int slot;
private final int width;
private final int height;
public GuiFluidTank( IAEFluidTank tank, int slot, int id, int x, int y, int w, int h ) public GuiFluidTank( IAEFluidTank tank, int slot, int id, int x, int y, int w, int h )
{ {
super( id, x, y, w, h, "" ); super( id, x, y );
this.tank = tank; this.tank = tank;
this.slot = slot; this.slot = slot;
this.width = w;
this.height = h;
} }
@Override @Override
public void drawButton( final Minecraft mc, final int mouseX, final int mouseY, final float partialTicks ) public void drawContent( Minecraft mc, int mouseX, int mouseY, float partialTicks )
{ {
if( this.visible ) final IAEFluidStack fs = this.getFluidStack();
if( fs != null )
{ {
GlStateManager.disableBlend(); GlStateManager.disableBlend();
GlStateManager.disableLighting(); GlStateManager.disableLighting();
drawRect( this.x, this.y, this.x + this.width, this.y + this.height, AEColor.GRAY.blackVariant | 0xFF000000 ); //drawRect( this.x, this.y, this.x + this.width, this.y + this.height, AEColor.GRAY.blackVariant | 0xFF000000 );
final IAEFluidStack fluid = this.tank.getFluidInSlot( this.slot ); final IAEFluidStack fluid = this.tank.getFluidInSlot( this.slot );
if( fluid != null && fluid.getStackSize() > 0 ) if( fluid != null && fluid.getStackSize() > 0 )
@@ -69,17 +77,16 @@ public class GuiFluidTank extends GuiButton implements ITooltip
TextureAtlasSprite sprite = mc.getTextureMapBlocks().getAtlasSprite( fluid.getFluid().getStill().toString() ); TextureAtlasSprite sprite = mc.getTextureMapBlocks().getAtlasSprite( fluid.getFluid().getStill().toString() );
final int scaledHeight = (int) ( this.height * ( (float) fluid.getStackSize() / this.tank.getTankProperties()[this.slot].getCapacity() ) ); final int scaledHeight = (int) ( this.height * ( (float) fluid.getStackSize() / this.tank.getTankProperties()[this.slot].getCapacity() ) );
int iconHeightRemainder = scaledHeight % 16; int iconHeightRemainder = scaledHeight % this.getHeight();
if( iconHeightRemainder > 0 ) if( iconHeightRemainder > 0 )
{ {
this.drawTexturedModalRect( this.x, this.y + this.height - iconHeightRemainder, sprite, 16, iconHeightRemainder ); this.drawTexturedModalRect( this.xPos(), this.yPos() + this.getHeight() - iconHeightRemainder, sprite, this.getWidth(), iconHeightRemainder );
} }
for( int i = 0; i < scaledHeight / 16; i++ ) for( int i = 0; i < scaledHeight / this.getHeight(); i++ )
{ {
this.drawTexturedModalRect( this.x, this.y + this.height - iconHeightRemainder - ( i + 1 ) * 16, sprite, 16, 16 ); this.drawTexturedModalRect( this.xPos(), this.yPos() + this.getHeight() - iconHeightRemainder - ( i + 1 ) * 16, sprite, this.getWidth(), this.getHeight() );
} }
} }
} }
} }
@@ -100,25 +107,25 @@ public class GuiFluidTank extends GuiButton implements ITooltip
@Override @Override
public int xPos() public int xPos()
{ {
return this.x - 2; return this.x - 1;
} }
@Override @Override
public int yPos() public int yPos()
{ {
return this.y - 2; return this.y - 1;
} }
@Override @Override
public int getWidth() public int getWidth()
{ {
return this.width + 4; return this.width;
} }
@Override @Override
public int getHeight() public int getHeight()
{ {
return this.height + 4; return this.height + 1;
} }
@Override @Override
@@ -127,4 +134,24 @@ public class GuiFluidTank extends GuiButton implements ITooltip
return true; return true;
} }
public IAEFluidStack getFluidStack()
{
return this.tank.getFluidInSlot( this.slot );
}
@Override
public void slotClicked( ItemStack clickStack, final int mouseButton )
{
if( getFluidStack() != null )
{
NetworkHandler.instance().sendToServer( new PacketInventoryAction( InventoryAction.FILL_ITEM, slot, 0 ) );
}
else
{
NetworkHandler.instance().sendToServer( new PacketInventoryAction( InventoryAction.EMPTY_ITEM, slot, 0 ) );
}
}
} }
@@ -19,9 +19,17 @@
package appeng.fluids.container; package appeng.fluids.container;
import javax.annotation.Nonnull;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketTargetFluidStack;
import appeng.fluids.util.AEFluidStack;
import appeng.helpers.InventoryAction;
import appeng.util.IConfigManagerHost;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.IContainerListener; import net.minecraft.inventory.IContainerListener;
@@ -33,12 +41,19 @@ import appeng.fluids.helper.FluidSyncHelper;
import appeng.fluids.helper.IFluidInterfaceHost; import appeng.fluids.helper.IFluidInterfaceHost;
import appeng.fluids.util.IAEFluidTank; import appeng.fluids.util.IAEFluidTank;
import appeng.util.Platform; import appeng.util.Platform;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
public class ContainerFluidInterface extends ContainerFluidConfigurable public class ContainerFluidInterface extends ContainerFluidConfigurable implements IConfigManagerHost
{ {
private final DualityFluidInterface myDuality; private final DualityFluidInterface myDuality;
private final FluidSyncHelper tankSync; private final FluidSyncHelper tankSync;
private IConfigManagerHost gui;
// Holds the fluid the client wishes to extract, or null for insert
private IAEFluidStack clientRequestedTargetFluid = null;
public ContainerFluidInterface( final InventoryPlayer ip, final IFluidInterfaceHost te ) public ContainerFluidInterface( final InventoryPlayer ip, final IFluidInterfaceHost te )
{ {
@@ -60,6 +75,15 @@ public class ContainerFluidInterface extends ContainerFluidConfigurable
return this.myDuality.getConfig(); return this.myDuality.getConfig();
} }
@Override
public void updateSetting( IConfigManager manager, Enum settingName, Enum newValue )
{
if( this.getGui() != null )
{
this.getGui().updateSetting( manager, settingName, newValue );
}
}
@Override @Override
public void detectAndSendChanges() public void detectAndSendChanges()
{ {
@@ -97,6 +121,126 @@ public class ContainerFluidInterface extends ContainerFluidConfigurable
this.tankSync.readPacket( fluids ); this.tankSync.readPacket( fluids );
} }
private IConfigManagerHost getGui()
{
return this.gui;
}
public void setGui( @Nonnull final IConfigManagerHost gui )
{
this.gui = gui;
}
public void doAction( EntityPlayerMP player, InventoryAction action, int slot, long id )
{
if( action != InventoryAction.FILL_ITEM && action != InventoryAction.EMPTY_ITEM )
{
super.doAction( player, action, slot, id );
return;
}
final ItemStack held = player.inventory.getItemStack();
ItemStack heldCopy = held.copy();
heldCopy.setCount( 1 );
IFluidHandlerItem fh = FluidUtil.getFluidHandler( heldCopy );
if( fh == null )
{
// only fluid handlers items
return;
}
if( action == InventoryAction.FILL_ITEM && this.clientRequestedTargetFluid != null )
{
final IAEFluidStack stack = this.clientRequestedTargetFluid.copy();
// Check how much we can store in the item
stack.setStackSize( Integer.MAX_VALUE );
int amountAllowed = fh.fill( stack.getFluidStack(), false );
int heldAmount = held.getCount();
for( int i = 0; i < heldAmount; i++ )
{
ItemStack copiedFluidContainer = held.copy();
copiedFluidContainer.setCount( 1 );
fh = FluidUtil.getFluidHandler( copiedFluidContainer );
FluidStack extractableFluid = this.myDuality.getTanks().drain( stack.setStackSize( amountAllowed ).getFluidStack(), false );
if( extractableFluid == null || extractableFluid.amount == 0 )
{
break;
}
int fillableAmount = fh.fill( extractableFluid, false );
if( fillableAmount > 0 )
{
FluidStack extractedFluid = this.myDuality.getTanks().drain( extractableFluid, true );
fh.fill( extractedFluid, true );
}
if( held.getCount() == 1 )
{
player.inventory.setItemStack( fh.getContainer() );
}
else
{
player.inventory.getItemStack().shrink( 1 );
if( !player.inventory.addItemStackToInventory( fh.getContainer() ) )
{
player.dropItem( fh.getContainer(), false );
}
}
}
}
else if( action == InventoryAction.EMPTY_ITEM )
{
int heldAmount = held.getCount();
for( int i = 0; i < heldAmount; i++ )
{
ItemStack copiedFluidContainer = held.copy();
copiedFluidContainer.setCount( 1 );
fh = FluidUtil.getFluidHandler( copiedFluidContainer );
FluidStack drainable = fh.drain( this.myDuality.getTanks().getTankProperties()[slot].getCapacity(), false );
if( drainable != null )
{
fh.drain( drainable, true );
this.myDuality.getTanks().fill( drainable, true );
}
if( held.getCount() == 1 )
{
player.inventory.setItemStack( fh.getContainer() );
}
else
{
player.inventory.getItemStack().shrink( 1 );
if( !player.inventory.addItemStackToInventory( fh.getContainer() ) )
{
player.dropItem( fh.getContainer(), false );
}
}
}
}
this.updateHeld( player );
}
public void setTargetStack( final IAEFluidStack stack )
{
if( Platform.isClient() )
{
if( stack == null && this.clientRequestedTargetFluid == null )
{
return;
}
if( stack != null && this.clientRequestedTargetFluid != null && stack.getFluidStack().isFluidEqual( this.clientRequestedTargetFluid.getFluidStack() ) )
{
return;
}
NetworkHandler.instance().sendToServer( new PacketTargetFluidStack( (AEFluidStack) stack ) );
}
this.clientRequestedTargetFluid = stack == null ? null : stack.copy();
}
@Override @Override
protected boolean supportCapacity() protected boolean supportCapacity()
{ {
@@ -91,12 +91,10 @@ public class DualityFluidInterface implements IGridTickable, IStorageMonitorable
private int isWorking = -1; private int isWorking = -1;
private int priority; private int priority;
private final MEMonitorPassThrough<IAEItemStack> items = new MEMonitorPassThrough<>( new NullInventory<IAEItemStack>(), AEApi.instance() private final MEMonitorPassThrough<IAEItemStack> items = new MEMonitorPassThrough<>( new NullInventory<IAEItemStack>(), AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
.storage() private final MEMonitorPassThrough<IAEFluidStack> fluids = new MEMonitorPassThrough<>( new NullInventory<IAEFluidStack>(), AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
.getStorageChannel( IItemStorageChannel.class ) ); private boolean resetConfigCache;
private final MEMonitorPassThrough<IAEFluidStack> fluids = new MEMonitorPassThrough<>( new NullInventory<IAEFluidStack>(), AEApi.instance() private IMEMonitor<IAEFluidStack> configCachedHandler;
.storage()
.getStorageChannel( IFluidStorageChannel.class ) );
public DualityFluidInterface( final AENetworkProxy networkProxy, final IFluidInterfaceHost ih ) public DualityFluidInterface( final AENetworkProxy networkProxy, final IFluidInterfaceHost ih )
{ {
@@ -146,7 +144,12 @@ public class DualityFluidInterface implements IGridTickable, IStorageMonitorable
{ {
if( this.hasConfig() ) if( this.hasConfig() )
{ {
return (IMEMonitor<T>) new InterfaceInventory( this ); if( resetConfigCache )
{
resetConfigCache = false;
configCachedHandler = new InterfaceInventory( this );
}
return (IMEMonitor<T>) configCachedHandler;
} }
return (IMEMonitor<T>) this.fluids; return (IMEMonitor<T>) this.fluids;
@@ -450,7 +453,12 @@ public class DualityFluidInterface implements IGridTickable, IStorageMonitorable
if( inventory == this.config ) if( inventory == this.config )
{ {
boolean cfg = hasConfig();
this.readConfig(); this.readConfig();
if( cfg != hasConfig )
{
resetConfigCache = true;
}
} }
else if( inventory == this.tanks ) else if( inventory == this.tanks )
{ {
@@ -555,7 +563,6 @@ public class DualityFluidInterface implements IGridTickable, IStorageMonitorable
InterfaceInventory( final DualityFluidInterface tileInterface ) InterfaceInventory( final DualityFluidInterface tileInterface )
{ {
super( tileInterface.tanks ); super( tileInterface.tanks );
this.setActionSource( new MachineSource( tileInterface.iHost ) );
} }
@Override @Override
@@ -19,16 +19,15 @@
package appeng.fluids.parts; package appeng.fluids.parts;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Settings; import appeng.api.config.Settings;
import appeng.api.config.StorageFilter; import appeng.api.config.StorageFilter;
import appeng.api.storage.data.IAEItemStack;
import appeng.me.GridAccessException; import appeng.me.GridAccessException;
import appeng.parts.misc.PartStorageBus; import appeng.util.inv.ItemSlot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fluids.capability.IFluidTankProperties;
@@ -64,17 +63,20 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
private final IGridProxyable proxyable; private final IGridProxyable proxyable;
private final FluidHandlerAdapter.InventoryCache cache; private final FluidHandlerAdapter.InventoryCache cache;
private StorageFilter mode; private StorageFilter mode;
private AccessRestriction access;
FluidHandlerAdapter( IFluidHandler fluidHandler, IGridProxyable proxy ) FluidHandlerAdapter( IFluidHandler fluidHandler, IGridProxyable proxy )
{ {
this.fluidHandler = fluidHandler; this.fluidHandler = fluidHandler;
this.proxyable = proxy; this.proxyable = proxy;
if( this.proxyable instanceof PartStorageBus ) if( this.proxyable instanceof PartFluidStorageBus )
{ {
PartStorageBus partStorageBus = (PartStorageBus) this.proxyable; PartFluidStorageBus partFluidStorageBus = (PartFluidStorageBus) this.proxyable;
this.mode = ( (StorageFilter) partStorageBus.getConfigManager().getSetting( Settings.STORAGE_FILTER ) ); this.mode = ( (StorageFilter) partFluidStorageBus.getConfigManager().getSetting( Settings.STORAGE_FILTER ) );
this.access = ( (AccessRestriction) partFluidStorageBus.getConfigManager().getSetting( Settings.ACCESS ) );
} }
this.cache = new FluidHandlerAdapter.InventoryCache( this.fluidHandler, this.mode); this.cache = new FluidHandlerAdapter.InventoryCache( this.fluidHandler, this.mode );
this.cache.update();
} }
@Override @Override
@@ -93,11 +95,14 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
{ {
IAEFluidStack added = input.copy().setStackSize( input.getStackSize() - remaining );
this.cache.currentlyCached.add( added );
this.postDifference( Collections.singletonList( added ) );
try try
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
} }
catch( GridAccessException ignore ) catch( GridAccessException ex )
{ {
// meh // meh
} }
@@ -125,11 +130,17 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
IAEFluidStack gatheredAEFluidstack = AEFluidStack.fromFluidStack( gathered ); IAEFluidStack gatheredAEFluidstack = AEFluidStack.fromFluidStack( gathered );
if( mode == Actionable.MODULATE ) if( mode == Actionable.MODULATE )
{ {
IAEFluidStack cachedStack = this.cache.currentlyCached.findPrecise( request );
if( cachedStack != null )
{
cachedStack.decStackSize( gatheredAEFluidstack.getStackSize() );
this.postDifference( Collections.singletonList( gatheredAEFluidstack.copy().setStackSize( -gatheredAEFluidstack.getStackSize() ) ) );
}
try try
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
} }
catch( GridAccessException ignore ) catch( GridAccessException ex )
{ {
// meh // meh
} }
@@ -141,7 +152,7 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
public TickRateModulation onTick() public TickRateModulation onTick()
{ {
List<IAEFluidStack> changes = this.cache.update(); List<IAEFluidStack> changes = this.cache.update();
if( !changes.isEmpty() ) if( !changes.isEmpty() && access.hasPermission( AccessRestriction.READ ) )
{ {
this.postDifference( changes ); this.postDifference( changes );
return TickRateModulation.URGENT; return TickRateModulation.URGENT;
@@ -221,18 +232,11 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
for( IFluidTankProperties tankProperty : tankProperties ) for( IFluidTankProperties tankProperty : tankProperties )
{ {
FluidStack newFS = tankProperty.getContents(); if( this.mode == StorageFilter.EXTRACTABLE_ONLY && this.fluidHandler.drain( 1, false ) == null )
if( this.mode == StorageFilter.EXTRACTABLE_ONLY && newFS != null )
{ {
if( this.fluidHandler.drain( 1, false ) == null ) continue;
{
newFS = null;
}
}
if( newFS != null )
{
currentlyOnStorage.add( AEFluidStack.fromFluidStack( newFS ) );
} }
currentlyOnStorage.add( AEFluidStack.fromFluidStack( tankProperty.getContents() ) );
} }
for ( final IAEFluidStack is : currentlyCached ) for ( final IAEFluidStack is : currentlyCached )
@@ -5,6 +5,7 @@ package appeng.fluids.parts;
import java.util.Random; import java.util.Random;
import appeng.api.networking.events.MENetworkChannelChanged; import appeng.api.networking.events.MENetworkChannelChanged;
import appeng.api.storage.data.IItemList;
import appeng.fluids.helper.IConfigurableFluidInventory; import appeng.fluids.helper.IConfigurableFluidInventory;
import appeng.me.cache.NetworkMonitor; import appeng.me.cache.NetworkMonitor;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@@ -113,7 +114,7 @@ public class PartFluidLevelEmitter extends PartUpgradeable implements IStackWatc
} }
@Override @Override
public void onStackChange( IAEStack<?> diffStack, IStorageChannel<?> chan ) public void onStackChange( IItemList<?> o, IAEStack<?> fullStack, IAEStack<?> diffStack, IActionSource src, IStorageChannel<?> chan )
{ {
if( chan == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) && diffStack.equals( this.config.getFluidInSlot( 0 ) ) ) if( chan == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) && diffStack.equals( this.config.getFluidInSlot( 0 ) ) )
{ {
@@ -26,6 +26,7 @@ import java.util.Objects;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import appeng.fluids.helper.IConfigurableFluidInventory; import appeng.fluids.helper.IConfigurableFluidInventory;
import appeng.util.ConfigManager;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
@@ -167,11 +168,28 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni
final boolean fullReset = this.resetCacheLogic == 2; final boolean fullReset = this.resetCacheLogic == 2;
this.resetCacheLogic = 0; this.resetCacheLogic = 0;
final IMEInventory<IAEFluidStack> in = this.getInternalHandler(); final MEInventoryHandler<IAEFluidStack> in = this.getInternalHandler();
IItemList<IAEFluidStack> before = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); IItemList<IAEFluidStack> before = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList();
boolean denyRead = false;
if( in != null ) if( in != null )
{ {
before = in.getAvailableItems( before ); if( accessChanged )
{
AccessRestriction currentAccess = (AccessRestriction) ( (ConfigManager) this.getConfigManager() ).getSetting( Settings.ACCESS );
AccessRestriction oldAccess = (AccessRestriction) ( (ConfigManager) this.getConfigManager() ).getOldSetting( Settings.ACCESS );
if( oldAccess.hasPermission( AccessRestriction.READ ) && !currentAccess.hasPermission( AccessRestriction.READ ) )
{
denyRead = true;
}
in.setBaseAccess( oldAccess );
before = in.getAvailableItems( before );
in.setBaseAccess( currentAccess );
accessChanged = false;
}
else
{
before = in.getAvailableItems( before );
}
} }
this.cached = false; this.cached = false;
@@ -180,15 +198,17 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni
this.handlerHash = 0; this.handlerHash = 0;
} }
final IMEInventory<IAEFluidStack> out = this.getInternalHandler(); final MEInventoryHandler<IAEFluidStack> out = this.getInternalHandler();
if( in != out ) if( in != out || denyRead )
{ {
IItemList<IAEFluidStack> after = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); IItemList<IAEFluidStack> after = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList();
if( out != null )
if( out != null && !denyRead )
{ {
after = out.getAvailableItems( after ); after = out.getAvailableItems( after );
} }
Platform.postListChanges( before, after, this, this.source ); Platform.postListChanges( before, after, this, this.source );
} }
} }
@@ -207,7 +227,7 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni
{ {
this.resetCacheLogic = 2; this.resetCacheLogic = 2;
} }
else else if( this.resetCacheLogic < 2 )
{ {
this.resetCacheLogic = 1; this.resetCacheLogic = 1;
} }
@@ -264,13 +284,22 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni
@Override @Override
public void postChange( final IBaseMonitor<IAEFluidStack> monitor, final Iterable<IAEFluidStack> change, final IActionSource source ) public void postChange( final IBaseMonitor<IAEFluidStack> monitor, final Iterable<IAEFluidStack> change, final IActionSource source )
{ {
if( this.source.machine().map( machine -> machine == this ).orElse( false ) && monitor != null )
{
AccessRestriction currentAccess = (AccessRestriction) ( (ConfigManager) this.getConfigManager() ).getSetting( Settings.ACCESS );
if( !currentAccess.hasPermission( AccessRestriction.READ ) )
{
return;
}
}
try try
{ {
if( this.getProxy().isActive() ) if( this.getProxy().isActive() )
{ {
this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ), change, this.source ); this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ), change, this.source );
} }
} catch ( final GridAccessException e ) }
catch( final GridAccessException e )
{ {
// :( // :(
} }
@@ -297,6 +326,10 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni
this.handlerHash = newHandlerHash; this.handlerHash = newHandlerHash;
this.handler = null; this.handler = null;
if( this.monitor != null )
{
( (IBaseMonitor<IAEFluidStack>) monitor ).removeListener( this );
}
this.monitor = null; this.monitor = null;
if( target != null ) if( target != null )
{ {
@@ -305,6 +338,7 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni
{ {
this.monitor = (ITickingMonitor) inv; this.monitor = (ITickingMonitor) inv;
this.monitor.setActionSource( new MachineSource( this ) ); this.monitor.setActionSource( new MachineSource( this ) );
this.monitor.setMode( (StorageFilter) this.getConfigManager().getSetting( Settings.STORAGE_FILTER ) );
} }
if( inv != null ) if( inv != null )
@@ -23,7 +23,6 @@ import java.util.*;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import appeng.api.definitions.IItemDefinition;
import appeng.integration.modules.gregtech.GTCEInventoryAdaptor; import appeng.integration.modules.gregtech.GTCEInventoryAdaptor;
import appeng.util.*; import appeng.util.*;
import appeng.util.inv.*; import appeng.util.inv.*;
@@ -35,7 +34,6 @@ import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.MetaTileEntityHolder;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.init.Items; import net.minecraft.init.Items;
import net.minecraft.inventory.InventoryCrafting; import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item; import net.minecraft.item.Item;
@@ -142,15 +140,17 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private int isWorking = -1; private int isWorking = -1;
private final Accessor accessor = new Accessor(); private final Accessor accessor = new Accessor();
private EnumSet<EnumFacing> visitedFaces = EnumSet.noneOf( EnumFacing.class ); private EnumSet<EnumFacing> visitedFaces = EnumSet.noneOf( EnumFacing.class );
private EnumMap<EnumFacing,List<ItemStack>> waitingToSendFacing = new EnumMap<>(EnumFacing.class); private EnumMap<EnumFacing, List<ItemStack>> waitingToSendFacing = new EnumMap<>( EnumFacing.class );
private GTCEInventoryAdaptor GTad; private GTCEInventoryAdaptor GTad;
private boolean resetConfigCache = true;
private IMEMonitor<IAEItemStack> configCachedHandler;
public DualityInterface( final AENetworkProxy networkProxy, final IInterfaceHost ih ) public DualityInterface( final AENetworkProxy networkProxy, final IInterfaceHost ih )
{ {
this.gridProxy = networkProxy; this.gridProxy = networkProxy;
this.gridProxy.setFlags( GridFlags.REQUIRE_CHANNEL ); this.gridProxy.setFlags( GridFlags.REQUIRE_CHANNEL );
this.upgrades = new StackUpgradeInventory( this.gridProxy.getMachineRepresentation(), this, 4); this.upgrades = new StackUpgradeInventory( this.gridProxy.getMachineRepresentation(), this, 4 );
this.cm.registerSetting( Settings.BLOCK, YesNo.NO ); this.cm.registerSetting( Settings.BLOCK, YesNo.NO );
this.cm.registerSetting( Settings.INTERFACE_TERMINAL, YesNo.YES ); this.cm.registerSetting( Settings.INTERFACE_TERMINAL, YesNo.YES );
@@ -178,9 +178,14 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
{ {
return; return;
} }
if( inv == this.config ) if( inv == this.config && ( !removed.isEmpty() || !added.isEmpty() ) )
{ {
boolean cfg = hasConfig();
this.readConfig(); this.readConfig();
if( cfg != hasConfig )
{
resetConfigCache = true;
}
} }
else if( inv == this.patterns && ( !removed.isEmpty() || !added.isEmpty() ) ) else if( inv == this.patterns && ( !removed.isEmpty() || !added.isEmpty() ) )
{ {
@@ -975,7 +980,12 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
{ {
if( this.hasConfig() ) if( this.hasConfig() )
{ {
return (IMEMonitor<T>) new InterfaceInventory( this ); if( resetConfigCache )
{
resetConfigCache = false;
configCachedHandler = new InterfaceInventory( this );
}
return (IMEMonitor<T>) configCachedHandler;
} }
return (IMEMonitor<T>) this.items; return (IMEMonitor<T>) this.items;
@@ -1583,7 +1593,6 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
public InterfaceInventory( final DualityInterface tileInterface ) public InterfaceInventory( final DualityInterface tileInterface )
{ {
super( new AdaptorItemHandler( tileInterface.storage ) ); super( new AdaptorItemHandler( tileInterface.storage ) );
this.setActionSource( new MachineSource( DualityInterface.this.iHost ) );
} }
@Override @Override
@@ -147,7 +147,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
} }
} }
} }
final int outputLength = this.isCrafting ? CRAFTING_OUTPUT_LIMIT : PROCESSING_OUTPUT_LIMIT; final int outputLength = out.size();
this.inputs = in.toArray(new IAEItemStack[ALL_INPUT_LIMIT]); this.inputs = in.toArray(new IAEItemStack[ALL_INPUT_LIMIT]);
this.outputs = out.toArray(new IAEItemStack[outputLength]); this.outputs = out.toArray(new IAEItemStack[outputLength]);
@@ -225,7 +225,7 @@ public class ItemEncodedPattern extends AEBaseItem implements ICraftingPatternIt
final ICraftingPatternDetails details = this.getPatternForItem( item, w ); final ICraftingPatternDetails details = this.getPatternForItem( item, w );
out = details != null ? details.getCondensedOutputs()[0].createItemStack() : ItemStack.EMPTY; out = details != null ? details.getOutputs()[0].createItemStack() : ItemStack.EMPTY;
SIMPLE_CACHE.put( item, out ); SIMPLE_CACHE.put( item, out );
return out; return out;
+49 -12
View File
@@ -30,7 +30,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@@ -42,10 +41,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.*;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import net.minecraft.world.World; import net.minecraft.world.World;
import appeng.api.AEApi; import appeng.api.AEApi;
@@ -274,17 +270,14 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
return; return;
} }
final Object2ObjectMap<IAEItemStack, ImmutableList<ICraftingPatternDetails>> oldItems = this.craftableItems; final Object2ObjectMap<IAEItemStack, ImmutableList<ICraftingPatternDetails>> oldItems = new Object2ObjectOpenHashMap<>(this.craftableItems);
final Set<IAEItemStack> oldEmitableItems = new HashSet<>(this.emitableItems);
// erase list. // erase list.
this.craftingMethods.clear(); this.craftingMethods.clear();
this.craftableItems.clear(); this.craftableItems.clear();
this.emitableItems.clear(); this.emitableItems.clear();
// update the stuff that was in the list...
this.storageGrid.postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), oldItems.keySet(),
new BaseActionSource() );
// re-create list.. // re-create list..
for( final ICraftingProvider provider : this.craftingProviders ) for( final ICraftingProvider provider : this.craftingProviders )
{ {
@@ -296,7 +289,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
// new craftables! // new craftables!
for( final ICraftingPatternDetails details : this.craftingMethods.keySet() ) for( final ICraftingPatternDetails details : this.craftingMethods.keySet() )
{ {
for( IAEItemStack out : details.getCondensedOutputs() ) for( IAEItemStack out : details.getOutputs() )
{ {
out = out.copy(); out = out.copy();
out.reset(); out.reset();
@@ -319,7 +312,51 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
this.craftableItems.put( e.getKey(), ImmutableList.copyOf( e.getValue() ) ); this.craftableItems.put( e.getKey(), ImmutableList.copyOf( e.getValue() ) );
} }
this.storageGrid.postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), this.craftableItems.keySet(), Object2ObjectMap<IAEItemStack, ImmutableList<ICraftingPatternDetails>> craftablesChanged = new Object2ObjectArrayMap<>();
ObjectSet<Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>>> i = oldItems.entrySet();
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() );
}
}
ObjectSet<Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>>> j = this.craftableItems.entrySet();
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() );
}
}
for( final IAEItemStack st : oldEmitableItems )
{
if( !emitableItems.contains( st ) )
{
IAEItemStack changedStack = st.copy();
changedStack.reset();
changedStack.setCraftable( false );
craftablesChanged.put( changedStack, null );
}
}
for( final IAEItemStack st : this.emitableItems )
{
if( !oldEmitableItems.contains( st ) )
{
IAEItemStack changedStack = st.copy();
changedStack.reset();
changedStack.setCraftable( true );
craftablesChanged.put( changedStack, null );
}
}
this.storageGrid.postCraftablesChanges( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), craftablesChanged.keySet(),
new BaseActionSource() ); new BaseActionSource() );
} }
+60 -90
View File
@@ -19,10 +19,21 @@
package appeng.me.cache; package appeng.me.cache;
import java.util.*; import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.NavigableSet;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.*; import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
import appeng.api.config.AccessRestriction; import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
@@ -70,7 +81,7 @@ public class EnergyGridCache implements IEnergyGrid
// Should only be modified from the add/remove methods below to guard against // Should only be modified from the add/remove methods below to guard against
// concurrent modifications // concurrent modifications
private final double averageLength = 40.0; private final double averageLength = 40.0;
private final Multimap<Integer,IAEPowerStorage> providers = HashMultimap.create(); private final Set<IAEPowerStorage> providers = new LinkedHashSet<>();
// Used to track whether an extraction is currently in progress, to fail fast // Used to track whether an extraction is currently in progress, to fail fast
// when something externally // when something externally
// modifies the energy grid. // modifies the energy grid.
@@ -78,7 +89,7 @@ public class EnergyGridCache implements IEnergyGrid
// Should only be modified from the add/remove methods below to guard against // Should only be modified from the add/remove methods below to guard against
// concurrent modifications // concurrent modifications
private final Multimap<Integer,IAEPowerStorage> requesters = HashMultimap.create(); private final Set<IAEPowerStorage> requesters = new LinkedHashSet<>();
// Used to track whether an injection is currently in progress, to fail fast // Used to track whether an injection is currently in progress, to fail fast
// when something externally // when something externally
// modifies the energy grid. // modifies the energy grid.
@@ -123,8 +134,8 @@ public class EnergyGridCache implements IEnergyGrid
public EnergyGridCache( final IGrid g ) public EnergyGridCache( final IGrid g )
{ {
this.myGrid = g; this.myGrid = g;
this.requesters.put( 0, this.localStorage ); this.requesters.add( this.localStorage );
this.providers.put( 1, this.localStorage ); this.providers.add( this.localStorage );
} }
@MENetworkEventSubscribe @MENetworkEventSubscribe
@@ -220,7 +231,7 @@ public class EnergyGridCache implements IEnergyGrid
if( this.drainPerTick > 0.0001 ) if( this.drainPerTick > 0.0001 )
{ {
final double drained = this.extractAEPower( this.getIdlePowerUsage(), Actionable.MODULATE, PowerMultiplier.CONFIG ); final double drained = this.extractAEPower( this.getIdlePowerUsage(), Actionable.MODULATE, PowerMultiplier.CONFIG );
currentlyHasPower = drained >= this.drainPerTick - 0.001 && this.getStoredPower() > 0; currentlyHasPower = drained >= this.drainPerTick - 0.001;
} }
else else
{ {
@@ -307,7 +318,7 @@ public class EnergyGridCache implements IEnergyGrid
{ {
this.availableTicksSinceUpdate = 0; this.availableTicksSinceUpdate = 0;
this.globalAvailablePower = 0; this.globalAvailablePower = 0;
for( final IAEPowerStorage p : this.providers.values() ) for( final IAEPowerStorage p : this.providers )
{ {
this.globalAvailablePower += p.getAECurrentPower(); this.globalAvailablePower += p.getAECurrentPower();
} }
@@ -324,28 +335,25 @@ public class EnergyGridCache implements IEnergyGrid
{ {
double extractedPower = 0; double extractedPower = 0;
providersToAdd.forEach( provider -> { this.providers.addAll( providersToAdd );
if( provider instanceof GridPowerStorage )
{
providers.put( 1, provider );
}
else
{
providers.put( 0, provider );
}
} );
providersToAdd.clear(); providersToAdd.clear();
final Iterator<IAEPowerStorage> it = this.providers.values().iterator(); final Iterator<IAEPowerStorage> it = this.providers.iterator();
ongoingExtractOperation = true; ongoingExtractOperation = true;
boolean ls = false;
try try
{ {
while ( extractedPower < amt && it.hasNext() ) while ( extractedPower < amt && it.hasNext() )
{ {
final IAEPowerStorage node = it.next(); final IAEPowerStorage node = it.next();
if( node == localStorage && mode == Actionable.MODULATE )
{
ls = true;
continue;
}
final double req = amt - extractedPower; final double req = amt - extractedPower;
final double newPower = node.extractAEPower( req, mode, PowerMultiplier.ONE ); final double newPower = node.extractAEPower( req, mode, PowerMultiplier.ONE );
extractedPower += newPower; extractedPower += newPower;
@@ -357,20 +365,25 @@ public class EnergyGridCache implements IEnergyGrid
} }
} finally } finally
{ {
providerToRemove.forEach( provider -> {
if( provider instanceof GridPowerStorage )
{
providers.remove( 1, provider );
}
else
{
providers.remove( 0, provider );
}
} );
this.providerToRemove.clear();
ongoingExtractOperation = false; ongoingExtractOperation = false;
} }
if( ls && extractedPower < amt )
{
final double req = amt - extractedPower;
final double newPower = localStorage.extractAEPower( req, mode, PowerMultiplier.ONE );
extractedPower += newPower;
if( newPower < req )
{
providers.remove( localStorage );
}
}
providers.removeIf( p -> providerToRemove.contains( p ) );
this.providerToRemove.clear();
final double result = Math.min( extractedPower, amt ); final double result = Math.min( extractedPower, amt );
if( mode == Actionable.MODULATE ) if( mode == Actionable.MODULATE )
@@ -392,18 +405,10 @@ public class EnergyGridCache implements IEnergyGrid
{ {
final double originalAmount = amt; final double originalAmount = amt;
requesterToAdd.forEach( requester -> { this.requesters.addAll( requesterToAdd );
if( requester instanceof GridPowerStorage ) requesterToAdd.clear();
{
requesters.put( 0, requester );
}
else
{
requesters.put( 1, requester );
}
} );
final Iterator<IAEPowerStorage> it = this.requesters.values().iterator(); final Iterator<IAEPowerStorage> it = this.requesters.iterator();
ongoingInjectOperation = true; ongoingInjectOperation = true;
try try
@@ -421,20 +426,12 @@ public class EnergyGridCache implements IEnergyGrid
} }
} finally } finally
{ {
requesterToRemove.forEach( requester -> {
if( requester instanceof GridPowerStorage )
{
requesters.remove( 0, requester );
}
else
{
requesters.remove( 1, requester );
}
} );
this.requesterToRemove.clear();
ongoingInjectOperation = false; ongoingInjectOperation = false;
} }
requesters.removeIf( r -> requesterToRemove.contains( r ) );
this.requesterToRemove.clear();
final double overflow = Math.max( 0.0, amt ); final double overflow = Math.max( 0.0, amt );
if( mode == Actionable.MODULATE ) if( mode == Actionable.MODULATE )
@@ -450,8 +447,8 @@ public class EnergyGridCache implements IEnergyGrid
{ {
double required = 0; double required = 0;
final Iterator<IAEPowerStorage> it = this.requesters.values().iterator(); final Iterator<IAEPowerStorage> it = this.requesters.iterator();
while( required < maxRequired && it.hasNext() ) while ( required < maxRequired && it.hasNext() )
{ {
final IAEPowerStorage node = it.next(); final IAEPowerStorage node = it.next();
if( node.getPowerFlow() != AccessRestriction.READ ) if( node.getPowerFlow() != AccessRestriction.READ )
@@ -619,55 +616,28 @@ public class EnergyGridCache implements IEnergyGrid
private void addRequester(IAEPowerStorage requester) { private void addRequester(IAEPowerStorage requester) {
Preconditions.checkState(!ongoingInjectOperation, Preconditions.checkState(!ongoingInjectOperation,
"Cannot modify energy requesters while energy is being injected."); "Cannot modify energy requesters while energy is being injected.");
if( requester instanceof GridPowerStorage ) this.requesters.add(requester);
{
requesters.put( 0, requester );
}
else
{
requesters.put( 1, requester );
}
} }
private void removeRequester(IAEPowerStorage requester) { private void removeRequester(IAEPowerStorage requester) {
Preconditions.checkState(!ongoingInjectOperation, Preconditions.checkState(!ongoingInjectOperation,
"Cannot modify energy requesters while energy is being injected."); "Cannot modify energy requesters while energy is being injected.");
if( requester instanceof GridPowerStorage ) this.requesters.remove(requester);
{
requesters.remove( 0, requester );
}
else
{
requesters.remove( 1, requester );
}
} }
private void addProvider(IAEPowerStorage provider) { private void addProvider(IAEPowerStorage provider) {
Preconditions.checkState(!ongoingExtractOperation, Preconditions.checkState(!ongoingExtractOperation,
"Cannot modify energy providers while energy is being extracted."); "Cannot modify energy providers while energy is being extracted.");
if( provider instanceof GridPowerStorage ) this.providers.add(provider);
{
providers.put( 1, provider );
}
else
{
providers.put( 0, provider );
}
} }
private void removeProvider(IAEPowerStorage provider) private void removeProvider(IAEPowerStorage provider) {
{ Preconditions.checkState(!ongoingExtractOperation,
Preconditions.checkState( !ongoingExtractOperation, "Cannot modify energy providers while energy is being extracted." ); "Cannot modify energy providers while energy is being extracted.");
if( provider instanceof GridPowerStorage ) this.providers.remove(provider);
{
providers.remove( 1, provider );
}
else
{
providers.remove( 0, provider );
}
} }
@Override @Override
public void addNode( final IGridNode node, final IGridHost machine ) public void addNode( final IGridNode node, final IGridHost machine )
{ {
+12 -2
View File
@@ -109,6 +109,9 @@ public class GridStorageCache implements IStorageGrid
this.watchers.remove( node ); this.watchers.remove( node );
} }
} }
this.storageMonitors.forEach( ( channel, monitor ) -> monitor.forceUpdate() );
} }
@Override @Override
@@ -137,6 +140,9 @@ public class GridStorageCache implements IStorageGrid
this.watchers.put( node, iw ); this.watchers.put( node, iw );
swh.updateWatcher( iw ); swh.updateWatcher( iw );
} }
this.storageMonitors.forEach( ( channel, monitor ) -> monitor.forceUpdate() );
} }
@Override @Override
@@ -248,8 +254,6 @@ public class GridStorageCache implements IStorageGrid
} }
} }
this.storageMonitors.forEach( ( channel, monitor ) -> monitor.forceUpdate() );
tracker.applyChanges(); tracker.applyChanges();
} }
@@ -281,6 +285,12 @@ public class GridStorageCache implements IStorageGrid
this.storageMonitors.get( chan ).postChange( true, (Iterable) input, src ); this.storageMonitors.get( chan ).postChange( true, (Iterable) input, src );
} }
@Override
public void postCraftablesChanges( IStorageChannel<?> chan, Iterable<? extends IAEStack<?>> input, IActionSource src )
{
this.storageMonitors.get( chan ).updateCraftables( (Iterable) input, src );
}
@Override @Override
public void registerCellProvider( final ICellProvider provider ) public void registerCellProvider( final ICellProvider provider )
{ {
+58 -14
View File
@@ -125,6 +125,10 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
public long getGridCurrentCount() public long getGridCurrentCount()
{ {
if( forceUpdate )
{
getStorageList();
}
if( myChannel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) if( myChannel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{ {
return gridItemCount; return gridItemCount;
@@ -136,17 +140,16 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
return 0; return 0;
} }
public long incGridCurrentCount(long count) public void incGridCurrentCount(long count)
{ {
if( myChannel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) if( myChannel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{ {
return gridItemCount += count; gridItemCount += count;
} }
else if( myChannel == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) else if( myChannel == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) )
{ {
return gridFluidCount += count; gridFluidCount += count;
} }
return 0;
} }
@Nonnull @Nonnull
@@ -157,7 +160,20 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
{ {
forceUpdate = false; forceUpdate = false;
this.cachedList.resetStatus(); this.cachedList.resetStatus();
return this.getAvailableItems( this.cachedList ); this.getAvailableItems( this.cachedList );
long count = 0;
for (T stack : this.cachedList) {
count += stack.getStackSize();
}
if( myChannel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{
gridItemCount = count;
}
else if( myChannel == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) )
{
gridFluidCount = count;
}
} }
return this.cachedList; return this.cachedList;
@@ -217,38 +233,65 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
} }
} }
protected void updateCraftables( Iterable<T> input, IActionSource src )
{
for( final T changedItem : input )
{
if (changedItem.isCraftable()) {
this.cachedList.add( changedItem );
}
else
{
T i = this.cachedList.findPrecise( changedItem );
if (i != null)
i.setCraftable( false );
}
}
}
protected void postChange( final boolean add, final Iterable<T> changes, final IActionSource src ) protected void postChange( final boolean add, final Iterable<T> changes, final IActionSource src )
{ {
if ( GLOBAL_DEPTH.contains( this )) if( this.localDepthSemaphore > 0 || GLOBAL_DEPTH.contains( this ) )
{ {
return; return;
} }
this.localDepthSemaphore++;
GLOBAL_DEPTH.push( this ); GLOBAL_DEPTH.push( this );
this.sendEvent = true; this.sendEvent = true;
for ( final T changedItem : changes ) for( final T changed : changes )
{ {
if( !add && changedItem != null ) T change = changed;
if( !add && change != null )
{ {
changedItem.setStackSize( -changedItem.getStackSize() ); change = changed.copy();
change.setStackSize( -change.getStackSize() );
} }
incGridCurrentCount( changedItem.getStackSize() ); incGridCurrentCount( change.getStackSize() );
this.cachedList.add( changedItem ); this.cachedList.add( change );
if( this.myGridCache.getInterestManager().containsKey( changedItem ) ) if( this.myGridCache.getInterestManager().containsKey( change ) )
{ {
final Collection<ItemWatcher> list = this.myGridCache.getInterestManager().get( changedItem ); final Collection<ItemWatcher> list = this.myGridCache.getInterestManager().get( change );
if( !list.isEmpty() ) if( !list.isEmpty() )
{ {
IAEStack<T> fullStack = this.getStorageList().findPrecise( change );
if( fullStack == null )
{
fullStack = change.copy();
fullStack.setStackSize( 0 );
}
this.myGridCache.getInterestManager().enableTransactions(); this.myGridCache.getInterestManager().enableTransactions();
for( final ItemWatcher iw : list ) for( final ItemWatcher iw : list )
{ {
iw.getHost().onStackChange( changedItem, this.getChannel() ); iw.getHost().onStackChange( this.getStorageList(), fullStack, change, src, this.getChannel() );
} }
this.myGridCache.getInterestManager().disableTransactions(); this.myGridCache.getInterestManager().disableTransactions();
@@ -259,6 +302,7 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
this.notifyListenersOfChange( changes, src ); this.notifyListenersOfChange( changes, src );
final NetworkMonitor<?> last = GLOBAL_DEPTH.pop(); final NetworkMonitor<?> last = GLOBAL_DEPTH.pop();
this.localDepthSemaphore--;
if( last != this ) if( last != this )
{ {
@@ -19,14 +19,11 @@
package appeng.me.storage; package appeng.me.storage;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.ConcurrentSkipListMap;
import appeng.fluids.util.AEFluidStack;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fluids.capability.IFluidTankProperties;
@@ -48,16 +45,14 @@ import appeng.api.storage.data.IItemList;
public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITickingMonitor public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITickingMonitor
{ {
private final IFluidHandler handler; private final IFluidHandler handler;
private final IItemList<IAEFluidStack> list = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); private IItemList<IAEFluidStack> cache = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList();
private final HashMap<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> listeners = new HashMap<>(); private final HashMap<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> listeners = new HashMap<>();
private final NavigableMap<Integer, CachedFluidStack> memory;
private IActionSource mySource; private IActionSource mySource;
private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY; private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY;
public MEMonitorIFluidHandler( final IFluidHandler handler ) public MEMonitorIFluidHandler( final IFluidHandler handler )
{ {
this.handler = handler; this.handler = handler;
this.memory = new ConcurrentSkipListMap<>();
} }
@Override @Override
@@ -82,11 +77,6 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITicki
return input.copy(); return input.copy();
} }
if( type == Actionable.MODULATE )
{
this.onTick();
}
if( filled == input.getStackSize() ) if( filled == input.getStackSize() )
{ {
return null; return null;
@@ -94,6 +84,15 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITicki
final IAEFluidStack o = input.copy(); final IAEFluidStack o = input.copy();
o.setStackSize( input.getStackSize() - filled ); o.setStackSize( input.getStackSize() - filled );
if( type == Actionable.MODULATE )
{
IAEFluidStack added = o.copy();
this.cache.add( added );
this.postDifference( Collections.singletonList( added ) );
this.onTick();
}
return o; return o;
} }
@@ -107,13 +106,18 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITicki
return null; return null;
} }
if( type == Actionable.MODULATE )
{
this.onTick();
}
final IAEFluidStack o = request.copy(); final IAEFluidStack o = request.copy();
o.setStackSize( removed.amount ); o.setStackSize( removed.amount );
if( type == Actionable.MODULATE )
{
IAEFluidStack cachedStack = this.cache.findPrecise( request );
if( cachedStack != null )
{
cachedStack.decStackSize( o.getStackSize() );
this.postDifference( Collections.singletonList( o.copy().setStackSize( -o.getStackSize() ) ) );
}
}
return o; return o;
} }
@@ -126,111 +130,51 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITicki
@Override @Override
public TickRateModulation onTick() public TickRateModulation onTick()
{ {
final List<IAEFluidStack> changes = new ArrayList<>();
this.list.resetStatus();
int high = 0;
boolean changed = false; boolean changed = false;
final IFluidTankProperties[] props = this.handler.getTankProperties(); final List<IAEFluidStack> changes = new ArrayList<>();
for( int slot = 0; slot < this.handler.getTankProperties().length; ++slot ) final IFluidTankProperties[] tankProperties = this.handler.getTankProperties();
IItemList<IAEFluidStack> currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList();
for( IFluidTankProperties tankProperty : tankProperties )
{ {
final CachedFluidStack old = this.memory.get( slot ); if( this.mode == StorageFilter.EXTRACTABLE_ONLY && this.handler.drain( 1, false ) == null )
high = Math.max( high, slot );
final FluidStack newIS = !props[slot].canDrain() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY ? null : props[slot].getContents();
final FluidStack oldIS = old == null ? null : old.fluidStack;
if( isDifferent( newIS, oldIS ) )
{ {
final CachedFluidStack cis = new CachedFluidStack( newIS ); continue;
this.memory.put( slot, cis );
if( old != null && old.aeStack != null )
{
old.aeStack.setStackSize( -old.aeStack.getStackSize() );
changes.add( old.aeStack );
}
if( cis.aeStack != null )
{
changes.add( cis.aeStack );
this.list.add( cis.aeStack );
}
changed = true;
} }
else currentlyOnStorage.add( AEFluidStack.fromFluidStack( tankProperty.getContents() ) );
}
for( final IAEFluidStack is : cache )
{
is.setStackSize( -is.getStackSize() );
}
for( final IAEFluidStack is : currentlyOnStorage )
{
cache.add( is );
}
for( final IAEFluidStack is : cache )
{
if( is.getStackSize() != 0 )
{ {
final int newSize = newIS == null ? 0 : newIS.amount; changes.add( is );
final int diff = newSize - ( oldIS == null ? 0 : oldIS.amount );
IAEFluidStack stack = null;
if( newIS != null )
{
stack = ( old == null || old.aeStack == null ? AEApi.instance()
.storage()
.getStorageChannel( IFluidStorageChannel.class )
.createStack( newIS ) : old.aeStack.copy() );
}
if( stack != null )
{
stack.setStackSize( newSize );
this.list.add( stack );
}
if( diff != 0 && stack != null )
{
final CachedFluidStack cis = new CachedFluidStack( newIS );
this.memory.put( slot, cis );
final IAEFluidStack a = stack.copy();
a.setStackSize( diff );
changes.add( a );
changed = true;
}
} }
} }
// detect dropped items; should fix non IISided Inventory Changes. cache = currentlyOnStorage;
final NavigableMap<Integer, CachedFluidStack> end = this.memory.tailMap( high, false );
if( !end.isEmpty() )
{
for( final CachedFluidStack cis : end.values() )
{
if( cis != null && cis.aeStack != null )
{
final IAEFluidStack a = cis.aeStack.copy();
a.setStackSize( -a.getStackSize() );
changes.add( a );
changed = true;
}
}
end.clear();
}
if( !changes.isEmpty() ) if( !changes.isEmpty() )
{ {
this.postDifference( changes ); this.postDifference( changes );
changed = true;
} }
return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER; return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER;
} }
private static boolean isDifferent( FluidStack a, FluidStack b )
{
if( a == b )
{
return false;
}
if( a == null || b == null )
{
return true;
}
return !a.getFluid().equals( b.getFluid() );
}
private void postDifference( final Iterable<IAEFluidStack> a ) private void postDifference( final Iterable<IAEFluidStack> a )
{ {
if( a != null ) if( a != null )
@@ -291,9 +235,9 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITicki
@Override @Override
public IItemList<IAEFluidStack> getAvailableItems( final IItemList out ) public IItemList<IAEFluidStack> getAvailableItems( final IItemList out )
{ {
for( final CachedFluidStack is : this.memory.values() ) for( final IAEFluidStack fs : cache )
{ {
out.addStorage( is.aeStack ); out.addStorage( fs );
} }
return out; return out;
@@ -302,7 +246,7 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITicki
@Override @Override
public IItemList<IAEFluidStack> getStorageList() public IItemList<IAEFluidStack> getStorageList()
{ {
return this.list; return this.cache;
} }
private StorageFilter getMode() private StorageFilter getMode()
@@ -326,24 +270,4 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITicki
this.mySource = mySource; this.mySource = mySource;
} }
private static class CachedFluidStack
{
private final FluidStack fluidStack;
private final IAEFluidStack aeStack;
CachedFluidStack( final FluidStack is )
{
if( is == null )
{
this.fluidStack = null;
this.aeStack = null;
}
else
{
this.fluidStack = is.copy();
this.aeStack = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createStack( is );
}
}
}
} }
@@ -19,12 +19,8 @@
package appeng.me.storage; package appeng.me.storage;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.ConcurrentSkipListMap;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -50,16 +46,15 @@ public class MEMonitorIInventory implements IMEMonitor<IAEItemStack>, ITickingMo
{ {
private final InventoryAdaptor adaptor; private final InventoryAdaptor adaptor;
private final IItemList<IAEItemStack> list = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); private IItemList<IAEItemStack> cache = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final HashMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>(); private final HashMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
private final NavigableMap<Integer, CachedItemStack> memory;
private IActionSource mySource; private IActionSource mySource;
private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY; private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY;
public MEMonitorIInventory( final InventoryAdaptor adaptor ) public MEMonitorIInventory( final InventoryAdaptor adaptor )
{ {
this.adaptor = adaptor; this.adaptor = adaptor;
this.memory = new ConcurrentSkipListMap<>();
} }
@Override @Override
@@ -88,11 +83,6 @@ public class MEMonitorIInventory implements IMEMonitor<IAEItemStack>, ITickingMo
out = this.adaptor.addItems( input.createItemStack() ); out = this.adaptor.addItems( input.createItemStack() );
} }
if( type == Actionable.MODULATE )
{
this.onTick();
}
if( out.isEmpty() ) if( out.isEmpty() )
{ {
return null; return null;
@@ -101,6 +91,15 @@ public class MEMonitorIInventory implements IMEMonitor<IAEItemStack>, ITickingMo
// better then doing construction from scratch :3 // better then doing construction from scratch :3
final IAEItemStack o = input.copy(); final IAEItemStack o = input.copy();
o.setStackSize( out.getCount() ); o.setStackSize( out.getCount() );
if( type == Actionable.MODULATE )
{
IAEItemStack added = o.copy();
this.cache.add( added );
this.postDifference( Collections.singletonList( added ) );
this.onTick();
}
return o; return o;
} }
@@ -129,6 +128,12 @@ public class MEMonitorIInventory implements IMEMonitor<IAEItemStack>, ITickingMo
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
{ {
IAEItemStack cachedStack = this.cache.findPrecise( request );
if( cachedStack != null )
{
cachedStack.decStackSize( o.getStackSize() );
this.postDifference( Collections.singletonList( o.copy().setStackSize( -o.getStackSize() ) ) );
}
this.onTick(); this.onTick();
} }
@@ -144,110 +149,52 @@ public class MEMonitorIInventory implements IMEMonitor<IAEItemStack>, ITickingMo
@Override @Override
public TickRateModulation onTick() public TickRateModulation onTick()
{ {
boolean changed = false;
final List<IAEItemStack> changes = new ArrayList<>(); final List<IAEItemStack> changes = new ArrayList<>();
this.list.resetStatus(); IItemList<IAEItemStack> currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
int high = 0;
boolean changed = false; for( final ItemSlot is : adaptor )
for( final ItemSlot is : this.adaptor )
{ {
final CachedItemStack old = this.memory.get( is.getSlot() ); if( this.mode == StorageFilter.EXTRACTABLE_ONLY && !is.isExtractable() )
high = Math.max( high, is.getSlot() );
final ItemStack newIS = !is.isExtractable() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY ? ItemStack.EMPTY : is.getItemStack();
final ItemStack oldIS = old == null ? ItemStack.EMPTY : old.itemStack;
if( this.isDifferent( newIS, oldIS ) )
{ {
final CachedItemStack cis = new CachedItemStack( is.getItemStack() ); continue;
this.memory.put( is.getSlot(), cis );
if( old != null && old.aeStack != null )
{
old.aeStack.setStackSize( -old.aeStack.getStackSize() );
changes.add( old.aeStack );
}
if( cis.aeStack != null )
{
changes.add( cis.aeStack );
this.list.add( cis.aeStack );
}
changed = true;
} }
else currentlyOnStorage.add( is.getAEItemStack() );
}
for( final IAEItemStack is : cache )
{
is.setStackSize( -is.getStackSize() );
}
for( final IAEItemStack is : currentlyOnStorage )
{
cache.add( is );
}
for( final IAEItemStack is : cache )
{
if( is.getStackSize() != 0 )
{ {
final int newSize = ( newIS.isEmpty() ? 0 : newIS.getCount() ); changes.add( is );
final int diff = newSize - ( oldIS.isEmpty() ? 0 : oldIS.getCount() );
final IAEItemStack stack = ( old == null || old.aeStack == null ? AEApi.instance()
.storage()
.getStorageChannel( IItemStorageChannel.class )
.createStack( newIS ) : old.aeStack.copy() );
if( stack != null )
{
stack.setStackSize( newSize );
this.list.add( stack );
}
if( diff != 0 && stack != null )
{
final CachedItemStack cis = new CachedItemStack( is.getItemStack() );
this.memory.put( is.getSlot(), cis );
final IAEItemStack a = stack.copy();
a.setStackSize( diff );
changes.add( a );
changed = true;
}
} }
} }
// detect dropped items; should fix non IISided Inventory Changes. cache = currentlyOnStorage;
final NavigableMap<Integer, CachedItemStack> end = this.memory.tailMap( high, false );
if( !end.isEmpty() )
{
for( final CachedItemStack cis : end.values() )
{
if( cis != null && cis.aeStack != null )
{
final IAEItemStack a = cis.aeStack.copy();
a.setStackSize( -a.getStackSize() );
changes.add( a );
changed = true;
}
}
end.clear();
}
if( !changes.isEmpty() ) if( !changes.isEmpty() )
{ {
this.postDifference( changes ); this.postDifference( changes );
changed = true;
} }
return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER; return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER;
} }
private boolean isDifferent( final ItemStack a, final ItemStack b )
{
if( a == b && b.isEmpty() )
{
return false;
}
if( ( a.isEmpty() && !b.isEmpty() ) || ( !a.isEmpty() && b.isEmpty() ) )
{
return true;
}
return !Platform.itemComparisons().isSameItem( a, b );
}
private void postDifference( final Iterable<IAEItemStack> a ) private void postDifference( final Iterable<IAEItemStack> a )
{ {
// AELog.info( a.getItemStack().getUnlocalizedName() + " @ " + a.getStackSize() );
if( a != null ) if( a != null )
{ {
final Iterator<Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator(); final Iterator<Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
@@ -306,9 +253,9 @@ public class MEMonitorIInventory implements IMEMonitor<IAEItemStack>, ITickingMo
@Override @Override
public IItemList<IAEItemStack> getAvailableItems( final IItemList out ) public IItemList<IAEItemStack> getAvailableItems( final IItemList out )
{ {
for( final CachedItemStack is : this.memory.values() ) for( IAEItemStack is : cache )
{ {
out.addStorage( is.aeStack ); out.addStorage( is );
} }
return out; return out;
@@ -317,7 +264,7 @@ public class MEMonitorIInventory implements IMEMonitor<IAEItemStack>, ITickingMo
@Override @Override
public IItemList<IAEItemStack> getStorageList() public IItemList<IAEItemStack> getStorageList()
{ {
return this.list; return this.cache;
} }
private StorageFilter getMode() private StorageFilter getMode()
@@ -41,7 +41,7 @@ public class MEPassThrough<T extends IAEStack<T>> implements IMEInventoryHandler
this.setInternal( i ); this.setInternal( i );
} }
protected IMEInventory<T> getInternal() public IMEInventory<T> getInternal()
{ {
return this.internal; return this.internal;
} }
@@ -180,7 +180,10 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
} }
else else
{ {
this.pushItemIntoTarget( destination, energy, inv, ais ); if( inv.getStorageList().findPrecise( ais ) != null )
{
this.pushItemIntoTarget( destination, energy, inv, ais );
}
} }
if( this.itemToSend == before && this.isCraftingEnabled() ) if( this.itemToSend == before && this.isCraftingEnabled() )
@@ -283,12 +283,12 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
final ItemStack simResult; final ItemStack simResult;
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{ {
simResult = myAdaptor.simulateSimilarRemove( toSend, itemStackToImport, fzMode, this ); simResult = myAdaptor.simulateSimilarRemove( toSend, itemStackToImport, fzMode, null );
itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source ); itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
} }
else else
{ {
simResult = myAdaptor.simulateRemove( toSend, itemStackToImport, this ); simResult = myAdaptor.simulateRemove( toSend, itemStackToImport, null );
itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source ); itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
} }
@@ -41,6 +41,7 @@ import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList;
import appeng.api.util.AECableType; import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation; import appeng.api.util.AEPartLocation;
import appeng.api.util.IConfigManager; import appeng.api.util.IConfigManager;
@@ -362,7 +363,7 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH
} }
@Override @Override
public void onStackChange( final IAEStack diffStack, final IStorageChannel chan ) public void onStackChange( IItemList<?> o, IAEStack<?> fullStack, IAEStack<?> diffStack, IActionSource src, IStorageChannel<?> chan )
{ {
if( chan == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) if( chan == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{ {
@@ -506,6 +507,7 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH
public void upgradesChanged() public void upgradesChanged()
{ {
this.configureWatchers(); this.configureWatchers();
this.updateState();
} }
@Override @Override
@@ -21,6 +21,7 @@ package appeng.parts.misc;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.config.Settings; import appeng.api.config.Settings;
import appeng.api.config.StorageFilter; import appeng.api.config.StorageFilter;
@@ -59,6 +60,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
private final IGridProxyable proxyable; private final IGridProxyable proxyable;
private final InventoryCache cache; private final InventoryCache cache;
private StorageFilter mode; private StorageFilter mode;
private AccessRestriction access;
private ItemStack stackCache = null; private ItemStack stackCache = null;
@@ -70,8 +72,10 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
{ {
PartStorageBus partStorageBus = (PartStorageBus) this.proxyable; PartStorageBus partStorageBus = (PartStorageBus) this.proxyable;
this.mode = ( (StorageFilter) partStorageBus.getConfigManager().getSetting( Settings.STORAGE_FILTER ) ); this.mode = ( (StorageFilter) partStorageBus.getConfigManager().getSetting( Settings.STORAGE_FILTER ) );
this.access = ( (AccessRestriction) partStorageBus.getConfigManager().getSetting( Settings.ACCESS ) );
} }
this.cache = new InventoryCache( this.itemHandler, this.mode ); this.cache = new InventoryCache( this.itemHandler, this.mode );
this.cache.update();
} }
@Override @Override
@@ -98,7 +102,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
ItemStack remaining = orgInput; ItemStack remaining = orgInput;
for ( int i = 0; i < slotCount && !remaining.isEmpty(); i++ ) for( int i = 0; i < slotCount && !remaining.isEmpty(); i++ )
{ {
remaining = this.itemHandler.insertItem( i, remaining, type == Actionable.SIMULATE ); remaining = this.itemHandler.insertItem( i, remaining, type == Actionable.SIMULATE );
} }
@@ -118,6 +122,9 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
{ {
IAEItemStack added = iox.copy().setStackSize( iox.getStackSize() - remaining.getCount() );
this.cache.currentlyCached.add( added );
this.postDifference( Collections.singletonList( added ) );
try try
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
@@ -126,7 +133,6 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
{ {
// meh // meh
} }
} }
return AEItemStack.fromItemStack( remaining ); return AEItemStack.fromItemStack( remaining );
@@ -200,6 +206,12 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
IAEItemStack gatheredAEItemStack = AEItemStack.fromItemStack( gathered ); IAEItemStack gatheredAEItemStack = AEItemStack.fromItemStack( gathered );
if( mode == Actionable.MODULATE ) if( mode == Actionable.MODULATE )
{ {
IAEItemStack cachedStack = this.cache.currentlyCached.findPrecise( request );
if( cachedStack != null )
{
cachedStack.decStackSize( gatheredAEItemStack.getStackSize() );
this.postDifference( Collections.singletonList( gatheredAEItemStack.copy().setStackSize( -gatheredAEItemStack.getStackSize() ) ) );
}
try try
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
@@ -220,7 +232,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
public TickRateModulation onTick() public TickRateModulation onTick()
{ {
List<IAEItemStack> changes = this.cache.update(); List<IAEItemStack> changes = this.cache.update();
if( !changes.isEmpty() ) if( !changes.isEmpty() && access.hasPermission( AccessRestriction.READ ) )
{ {
this.postDifference( changes ); this.postDifference( changes );
return TickRateModulation.URGENT; return TickRateModulation.URGENT;
@@ -308,13 +320,13 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
IItemList<IAEItemStack> currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); IItemList<IAEItemStack> currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
for ( final ItemSlot is : this ) for( final ItemSlot is : this )
{ {
final ItemStack newIS = !is.isExtractable() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY ? ItemStack.EMPTY : is.getItemStack(); if( this.mode == StorageFilter.EXTRACTABLE_ONLY && !is.isExtractable() )
if( !newIS.isEmpty() )
{ {
currentlyOnStorage.add( is.getAEItemStack() ); continue;
} }
currentlyOnStorage.add( is.getAEItemStack() );
} }
for ( final IAEItemStack is : currentlyCached ) for ( final IAEItemStack is : currentlyCached )
@@ -2,7 +2,9 @@ package appeng.parts.misc;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.config.Settings;
import appeng.api.networking.security.IActionSource; import appeng.api.networking.security.IActionSource;
import appeng.api.networking.storage.IBaseMonitor; import appeng.api.networking.storage.IBaseMonitor;
import appeng.api.networking.ticking.TickRateModulation; import appeng.api.networking.ticking.TickRateModulation;
@@ -38,6 +40,7 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
private final IItemRepository itemRepository; private final IItemRepository itemRepository;
private final IGridProxyable proxyable; private final IGridProxyable proxyable;
private final InventoryCache cache; private final InventoryCache cache;
private AccessRestriction access;
private ItemStack stackCache; private ItemStack stackCache;
@@ -46,6 +49,12 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
this.itemRepository = itemRepository; this.itemRepository = itemRepository;
this.proxyable = proxy; this.proxyable = proxy;
this.cache = new InventoryCache( this.itemRepository ); 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 @Override
@@ -70,7 +79,7 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
ItemStack remaining = this.itemRepository.insertItem( orgInput, type == Actionable.SIMULATE ); ItemStack remaining = this.itemRepository.insertItem( orgInput, type == Actionable.SIMULATE );
// Store the stack in the cache for next time. // Store the stack in the cache for next time.
if (!remaining.isEmpty() && remaining != orgInput) if( !remaining.isEmpty() && remaining != orgInput )
{ {
stackCache = remaining; stackCache = remaining;
} }
@@ -84,6 +93,9 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
{ {
IAEItemStack added = iox.copy().setStackSize( iox.getStackSize() - remaining.getCount() );
this.cache.currentlyCached.add( added );
this.postDifference( Collections.singletonList( added ) );
try try
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
@@ -121,6 +133,12 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
IAEItemStack extractedAEItemStack = AEItemStack.fromItemStack( extracted ); IAEItemStack extractedAEItemStack = AEItemStack.fromItemStack( extracted );
if( mode == Actionable.MODULATE ) 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 try
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
@@ -180,17 +198,15 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
@Override @Override
public TickRateModulation onTick() public TickRateModulation onTick()
{ {
List<IAEItemStack> changes = this.cache.update();
if( !changes.isEmpty() && access.hasPermission( AccessRestriction.READ ) )
{ {
List<IAEItemStack> changes = this.cache.update(); this.postDifference( changes );
if( !changes.isEmpty() ) return TickRateModulation.URGENT;
{ }
this.postDifference( changes ); else
return TickRateModulation.URGENT; {
} return TickRateModulation.SLOWER;
else
{
return TickRateModulation.SLOWER;
}
} }
} }
@@ -22,8 +22,14 @@ package appeng.parts.misc;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import appeng.api.config.AccessRestriction;
import appeng.fluids.parts.PartFluidInterface;
import appeng.fluids.tile.TileFluidInterface;
import appeng.tile.misc.TileInterface;
import appeng.tile.networking.TileCableBus;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess; import net.minecraft.world.IBlockAccess;
@@ -55,6 +61,7 @@ public abstract class PartSharedStorageBus extends PartUpgradeable implements IG
{ {
private boolean wasActive = false; private boolean wasActive = false;
private int priority = 0; private int priority = 0;
protected boolean accessChanged;
public PartSharedStorageBus( ItemStack is ) public PartSharedStorageBus( ItemStack is )
{ {
@@ -146,6 +153,10 @@ public abstract class PartSharedStorageBus extends PartUpgradeable implements IG
@Override @Override
public void updateSetting( final IConfigManager manager, final Enum settingName, final Enum newValue ) public void updateSetting( final IConfigManager manager, final Enum settingName, final Enum newValue )
{ {
if( settingName instanceof AccessRestriction )
{
this.accessChanged = true;
}
this.resetCache( true ); this.resetCache( true );
this.getHost().markForSave(); this.getHost().markForSave();
} }
@@ -155,7 +166,27 @@ public abstract class PartSharedStorageBus extends PartUpgradeable implements IG
{ {
if( pos.offset( this.getSide().getFacing() ).equals( neighbor ) ) if( pos.offset( this.getSide().getFacing() ).equals( neighbor ) )
{ {
this.resetCache( false );
final TileEntity te = w.getTileEntity( neighbor );
// In case the TE was destroyed, we have to do a full reset immediately.
if( te instanceof TileCableBus )
{
if( ( (TileCableBus) te ).getPart( this.getSide().getOpposite() ) instanceof PartFluidInterface )
{
this.resetCache( true );
this.resetCache();
}
}
if( te == null || te instanceof TileFluidInterface )
{
this.resetCache( true );
this.resetCache();
}
else
{
this.resetCache( false );
}
} }
} }
@@ -23,6 +23,12 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import appeng.fluids.parts.FluidHandlerAdapter;
import appeng.me.storage.MEPassThrough;
import appeng.parts.AEBasePart;
import appeng.tile.misc.TileInterface;
import appeng.tile.networking.TileCableBus;
import appeng.util.ConfigManager;
import com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository; import com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -121,6 +127,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
private int handlerHash = 0; private int handlerHash = 0;
private boolean wasActive = false; private boolean wasActive = false;
private byte resetCacheLogic = 0; private byte resetCacheLogic = 0;
private boolean accessChanged;
@Reflected @Reflected
public PartStorageBus( final ItemStack is ) public PartStorageBus( final ItemStack is )
@@ -172,6 +179,10 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
@Override @Override
public void updateSetting( final IConfigManager manager, final Enum settingName, final Enum newValue ) public void updateSetting( final IConfigManager manager, final Enum settingName, final Enum newValue )
{ {
if( settingName instanceof AccessRestriction )
{
this.accessChanged = true;
}
this.resetCache( true ); this.resetCache( true );
this.getHost().markForSave(); this.getHost().markForSave();
} }
@@ -234,7 +245,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
{ {
this.resetCacheLogic = 2; this.resetCacheLogic = 2;
} }
else else if( this.resetCacheLogic < 2 )
{ {
this.resetCacheLogic = 1; this.resetCacheLogic = 1;
} }
@@ -258,13 +269,22 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
@Override @Override
public void postChange( final IBaseMonitor<IAEItemStack> monitor, final Iterable<IAEItemStack> change, final IActionSource source ) public void postChange( final IBaseMonitor<IAEItemStack> monitor, final Iterable<IAEItemStack> change, final IActionSource source )
{ {
if( this.mySrc.machine().map( machine -> machine == this ).orElse( false ) && monitor != null )
{
AccessRestriction currentAccess = (AccessRestriction) ( (ConfigManager) this.getConfigManager() ).getSetting( Settings.ACCESS );
if( !currentAccess.hasPermission( AccessRestriction.READ ) )
{
return;
}
}
try try
{ {
if( this.getProxy().isActive() ) if( this.getProxy().isActive() )
{ {
this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), change, this.mySrc ); this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), change, this.mySrc );
} }
} catch ( final GridAccessException e ) }
catch( final GridAccessException e )
{ {
// :( // :(
} }
@@ -289,10 +309,19 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
{ {
if( pos.offset( this.getSide().getFacing() ).equals( neighbor ) ) if( pos.offset( this.getSide().getFacing() ).equals( neighbor ) )
{ {
final TileEntity te = w.getTileEntity( neighbor ); final TileEntity te = w.getTileEntity( neighbor );
// In case the TE was destroyed, we have to do a full reset immediately. // In case the TE was destroyed, we have to do a full reset immediately.
if( te == null ) if( te instanceof TileCableBus )
{
if( ( (TileCableBus) te ).getPart( this.getSide().getOpposite() ) instanceof PartInterface )
{
this.resetCache( true );
this.resetCache();
}
}
if( te == null || te instanceof TileInterface )
{ {
this.resetCache( true ); this.resetCache( true );
this.resetCache(); this.resetCache();
@@ -347,11 +376,28 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
final boolean fullReset = this.resetCacheLogic == 2; final boolean fullReset = this.resetCacheLogic == 2;
this.resetCacheLogic = 0; this.resetCacheLogic = 0;
final IMEInventory<IAEItemStack> in = this.getInternalHandler(); final MEInventoryHandler<IAEItemStack> in = this.getInternalHandler();
IItemList<IAEItemStack> before = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); IItemList<IAEItemStack> before = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
boolean denyRead = false;
if( in != null ) if( in != null )
{ {
before = in.getAvailableItems( before ); if( accessChanged )
{
AccessRestriction currentAccess = (AccessRestriction) ( (ConfigManager) this.getConfigManager() ).getSetting( Settings.ACCESS );
AccessRestriction oldAccess = (AccessRestriction) ( (ConfigManager) this.getConfigManager() ).getOldSetting( Settings.ACCESS );
if( oldAccess.hasPermission( AccessRestriction.READ ) && !currentAccess.hasPermission( AccessRestriction.READ ) )
{
denyRead = true;
}
in.setBaseAccess( oldAccess );
before = in.getAvailableItems( before );
in.setBaseAccess( currentAccess );
accessChanged = false;
}
else
{
before = in.getAvailableItems( before );
}
} }
this.cached = false; this.cached = false;
@@ -360,16 +406,19 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
this.handlerHash = 0; this.handlerHash = 0;
} }
final IMEInventory<IAEItemStack> out = this.getInternalHandler(); final MEInventoryHandler<IAEItemStack> out = this.getInternalHandler();
if( in != out ) if( in != out || denyRead )
{ {
IItemList<IAEItemStack> after = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); IItemList<IAEItemStack> after = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
if( out != null )
if( out != null && !denyRead )
{ {
after = out.getAvailableItems( after ); after = out.getAvailableItems( after );
} }
Platform.postListChanges( before, after, this, this.mySrc ); Platform.postListChanges( before, after, this, this.mySrc );
} }
} }
@@ -430,16 +479,6 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
return Objects.hash( target, target.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, targetSide ) ); return Objects.hash( target, target.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, targetSide ) );
} }
if (ITEM_REPOSITORY_CAPABILITY != null && target.hasCapability( ITEM_REPOSITORY_CAPABILITY, targetSide ))
{
final IItemRepository handlerRepo = target.getCapability( ITEM_REPOSITORY_CAPABILITY, targetSide );
if( handlerRepo != null )
{
return Objects.hash( target, handlerRepo, handlerRepo.getAllItems().size() );
}
}
final IItemHandler itemHandler = target.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetSide ); final IItemHandler itemHandler = target.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetSide );
if( itemHandler != null ) if( itemHandler != null )
@@ -471,17 +510,15 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
this.handlerHash = newHandlerHash; this.handlerHash = newHandlerHash;
this.handler = null; this.handler = null;
if( this.monitor != null )
{
( (IBaseMonitor<IAEItemStack>) monitor ).removeListener( this );
}
this.monitor = null; this.monitor = null;
if( target != null ) if( target != null )
{ {
IMEInventory<IAEItemStack> inv = this.getInventoryWrapper( target ); IMEInventory<IAEItemStack> inv = this.getInventoryWrapper( target );
if( inv instanceof MEMonitorIInventory )
{
final MEMonitorIInventory h = (MEMonitorIInventory) inv;
h.setMode( (StorageFilter) this.getConfigManager().getSetting( Settings.STORAGE_FILTER ) );
}
if( inv instanceof ITickingMonitor ) if( inv instanceof ITickingMonitor )
{ {
this.monitor = (ITickingMonitor) inv; this.monitor = (ITickingMonitor) inv;
@@ -350,9 +350,25 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
if( needsNewFrequency ) if( needsNewFrequency )
{ {
newFreq = this.getProxy().getP2P().newFrequency(); newFreq = this.getProxy().getP2P().newFrequency();
}
this.getProxy().getP2P().updateFreq( this, newFreq ); final ItemStack newType = this.getHost().getPart( this.getSide() ).getItemStack( PartItemStack.WRENCH );
this.getHost().removePart( this.getSide(), false );
final AEPartLocation dir = this.getHost().addPart( newType, this.getSide(), player, hand );
final IPart newBus = this.getHost().getPart( dir );
if( newBus instanceof PartP2PTunnel )
{
final PartP2PTunnel newTunnel = (PartP2PTunnel) newBus;
newTunnel.setOutput( false );
newTunnel.onTunnelNetworkChange();
newTunnel.getProxy().getP2P().updateFreq( newTunnel, newFreq );
}
}
else
{
this.getProxy().getP2P().updateFreq( this, newFreq );
}
} }
catch( final GridAccessException e ) catch( final GridAccessException e )
{ {
@@ -365,10 +381,17 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
final String type = p2pItem.getUnlocalizedName(); final String type = p2pItem.getUnlocalizedName();
p2pItem.writeToNBT( data ); p2pItem.writeToNBT( data );
data.setShort( "freq", this.getFrequency() ); if( needsNewFrequency )
{
data.setShort( "freq", newFreq );
}
else
{
data.setShort( "freq", this.getFrequency() );
}
final AEColor[] colors = Platform.p2p().toColors( this.getFrequency() ); final AEColor[] colors = Platform.p2p().toColors( this.getFrequency() );
final int[] colorCode = new int[] { final int[] colorCode = new int[]{
colors[0].ordinal(), colors[0].ordinal(), colors[1].ordinal(), colors[1].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(), colors[2].ordinal(), colors[2].ordinal(), colors[3].ordinal(), colors[3].ordinal(),
}; };
@@ -24,8 +24,10 @@ import java.io.IOException;
import appeng.api.networking.events.MENetworkChannelsChanged; import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkEventSubscribe; import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange; import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.networking.security.IActionSource;
import appeng.api.storage.channels.IFluidStorageChannel; import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IItemList;
import appeng.fluids.util.AEFluidStack; import appeng.fluids.util.AEFluidStack;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
@@ -80,6 +82,7 @@ public abstract class AbstractPartMonitor extends AbstractPartDisplay implements
private IAEItemStack configuredItem; private IAEItemStack configuredItem;
private IAEFluidStack configuredFluid; private IAEFluidStack configuredFluid;
private long configuredAmount;
private String lastHumanReadableText; private String lastHumanReadableText;
private boolean isLocked; private boolean isLocked;
private IStackWatcher myWatcher; private IStackWatcher myWatcher;
@@ -206,14 +209,21 @@ public abstract class AbstractPartMonitor extends AbstractPartDisplay implements
fluidInTank = fluidHandlerItem.drain( Integer.MAX_VALUE, false ); fluidInTank = fluidHandlerItem.drain( Integer.MAX_VALUE, false );
} }
if (fluidInTank == null) if( fluidInTank == null )
{ {
this.configuredFluid = null; this.configuredFluid = null;
this.configuredItem = AEItemStack.fromItemStack( eq ); if( !eq.isEmpty() )
{
this.configuredItem = AEItemStack.fromItemStack( eq ).setStackSize( 0 );
}
else
{
this.configuredItem = null;
}
} }
else if( fluidInTank.amount > 0 ) else if( fluidInTank.amount > 0 )
{ {
this.configuredFluid = AEFluidStack.fromFluidStack( fluidInTank ); this.configuredFluid = AEFluidStack.fromFluidStack( fluidInTank ).setStackSize( 0 );
this.configuredItem = null; this.configuredItem = null;
} }
@@ -297,30 +307,31 @@ public abstract class AbstractPartMonitor extends AbstractPartDisplay implements
private <T extends IAEStack<T>> void updateReportingValue ( final IMEMonitor<T> monitor ) private <T extends IAEStack<T>> void updateReportingValue ( final IMEMonitor<T> monitor )
{ {
if( this.configuredItem != null) if( this.configuredItem != null)
{ {
final IAEItemStack result = (IAEItemStack) monitor.getStorageList().findPrecise( (T) this.configuredItem ); final IAEItemStack result = (IAEItemStack) monitor.getStorageList().findPrecise( (T) this.configuredItem );
if( result == null ) if( result == null )
{ {
this.configuredItem.setStackSize( 0 ); this.configuredAmount = 0;
} }
else else
{ {
this.configuredItem.setStackSize( result.getStackSize() ); this.configuredAmount = result.getStackSize();
} }
this.configuredItem.setStackSize( this.configuredAmount );
} }
else if( this.configuredFluid != null) else if( this.configuredFluid != null)
{ {
final IAEFluidStack result = (IAEFluidStack) monitor.getStorageList().findPrecise( (T) this.configuredFluid ); final IAEFluidStack result = (IAEFluidStack) monitor.getStorageList().findPrecise( (T) this.configuredFluid );
if( result == null ) if( result == null )
{ {
this.configuredFluid.setStackSize( 0 ); this.configuredAmount = 0;
} }
else else
{ {
this.configuredFluid.setStackSize( result.getStackSize() ); this.configuredAmount = result.getStackSize();
} }
this.configuredFluid.setStackSize( this.configuredAmount );
} }
} }
@@ -388,108 +399,35 @@ public abstract class AbstractPartMonitor extends AbstractPartDisplay implements
@MENetworkEventSubscribe @MENetworkEventSubscribe
public void powerStatusChange( final MENetworkPowerStatusChange ev ) public void powerStatusChange( final MENetworkPowerStatusChange ev )
{ {
if( !this.getProxy().isPowered() ) if( this.getProxy().isPowered() )
{ {
if( this.myWatcher != null ) this.configureWatchers();
{
if( this.configuredItem != null )
{
this.configuredItem.setStackSize( 0 );
}
if( this.configuredFluid != null )
{
this.configuredFluid.setStackSize( 0 );
}
}
}
else
{
try
{
if( this.configuredItem != null )
{
this.updateReportingValue( this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) );
}
if( this.configuredFluid != null )
{
this.updateReportingValue( this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) );
}
}
catch( final GridAccessException e )
{
// ;P
}
} }
} }
@MENetworkEventSubscribe @MENetworkEventSubscribe
public void channelChanged( final MENetworkChannelsChanged c ) public void channelChanged( final MENetworkChannelsChanged c )
{ {
if( !this.getProxy().isPowered() ) if( this.getProxy().isPowered() )
{ {
if( this.myWatcher != null ) this.configureWatchers();
{
if( this.configuredItem != null )
{
this.configuredItem.setStackSize( 0 );
}
if( this.configuredFluid != null )
{
this.configuredFluid.setStackSize( 0 );
}
}
}
else
{
try
{
if( this.configuredItem != null )
{
this.updateReportingValue( this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) );
}
if( this.configuredFluid != null )
{
this.updateReportingValue( this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) );
}
}
catch( final GridAccessException e )
{
// ;P
}
} }
} }
@Override @Override
public void onStackChange( final IAEStack diffStack, final IStorageChannel chan ) public void onStackChange( IItemList<?> o, IAEStack<?> fullStack, IAEStack<?> diffStack, IActionSource src, IStorageChannel<?> chan )
{ {
this.configuredAmount = this.configuredAmount + diffStack.getStackSize();
if( this.configuredItem != null ) if( this.configuredItem != null )
{ {
long diff = this.configuredItem.getStackSize() + diffStack.getStackSize(); this.configuredItem.setStackSize( this.configuredAmount );
this.configuredItem.setStackSize( diff >= 0 ? this.configuredItem.getStackSize() + diffStack.getStackSize() : 0 );
final long stackSize = this.configuredItem.getStackSize();
final String humanReadableText = NUMBER_CONVERTER.toWideReadableForm( stackSize );
if( !humanReadableText.equals( this.lastHumanReadableText ) )
{
this.lastHumanReadableText = humanReadableText;
this.getHost().markForUpdate();
}
} }
else if( this.configuredFluid != null ) else if( this.configuredFluid != null )
{ {
long diff = this.configuredFluid.getStackSize() + diffStack.getStackSize(); this.configuredFluid.setStackSize( this.configuredAmount );
this.configuredFluid.setStackSize( diff >= 0 ? this.configuredFluid.getStackSize() + diffStack.getStackSize() : 0 );
final long stackSize = this.configuredFluid.getStackSize() / 1000;
final String humanReadableText = NUMBER_CONVERTER.toWideReadableForm( stackSize ) + "B";
if( !humanReadableText.equals( this.lastHumanReadableText ) )
{
this.lastHumanReadableText = humanReadableText;
this.getHost().markForUpdate();
}
} }
this.getHost().markForUpdate();
} }
@Override @Override
@@ -137,14 +137,10 @@ public class PartConversionMonitor extends AbstractPartMonitor
{ {
this.insertItem( player, hand, false ); this.insertItem( player, hand, false );
} }
} }
//If its a fluid container, grab its fluidstack. if its empty pass its itemstack; //If its a fluid container, grab its fluidstack. if its empty pass its itemstack;
if (eq.isEmpty()){
return super.onPartActivate( player, hand, pos );
}
if( fluidInTank != null && fluidInTank.amount > 0 ) if( fluidInTank != null && fluidInTank.amount > 0 )
{ {
if( getDisplayed() instanceof IAEItemStack || getDisplayed() == null ) if( getDisplayed() instanceof IAEItemStack || getDisplayed() == null )
@@ -155,23 +151,16 @@ public class PartConversionMonitor extends AbstractPartMonitor
{ {
this.drainFluidContainer( player, hand ); this.drainFluidContainer( player, hand );
} }
else { else
{
return super.onPartActivate( player, hand, pos ); return super.onPartActivate( player, hand, pos );
} }
} }
else else if( this.getDisplayed() != null && this.getDisplayed().equals( player.getHeldItem( hand ) ) )
{ {
if( getDisplayed() instanceof IAEFluidStack || getDisplayed() == null ) this.insertItem( player, hand, false );
{
return super.onPartActivate( player, hand, pos );
}
if( ( (IAEItemStack) this.getDisplayed() ).equals( eq ) )
{
this.insertItem( player, hand, false );
}
} }
return super.onPartActivate( player, hand, pos );
return true;
} }
@Override @Override
@@ -192,7 +181,6 @@ public class PartConversionMonitor extends AbstractPartMonitor
return false; return false;
} }
ItemStack eq = player.getHeldItem( hand );
if( this.getDisplayed() != null && this.getDisplayed() instanceof IAEItemStack ) if( this.getDisplayed() != null && this.getDisplayed() instanceof IAEItemStack )
{ {
this.extractItem( player, ( (IAEItemStack) this.getDisplayed() ).getDefinition().getMaxStackSize() ); this.extractItem( player, ( (IAEItemStack) this.getDisplayed() ).getDefinition().getMaxStackSize() );
@@ -282,7 +270,7 @@ public class PartConversionMonitor extends AbstractPartMonitor
{ {
if (!(this.getDisplayed() instanceof IAEItemStack)) if (!(this.getDisplayed() instanceof IAEItemStack))
return; return;
final IAEItemStack input = (IAEItemStack) this.getDisplayed(); final IAEItemStack input = (IAEItemStack) this.getDisplayed().copy();
if( input != null ) if( input != null )
{ {
try try
@@ -494,12 +494,14 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
try try
{ {
this.getProxy().getGrid().postEvent( new MENetworkCellArrayUpdate() ); this.getProxy().getGrid().postEvent( new MENetworkCellArrayUpdate() );
final IStorageGrid gs = this.getProxy().getStorage(); if( this.getProxy().isActive() )
Platform.postChanges( gs, removed, added, this.mySrc ); {
final IStorageGrid gs = this.getProxy().getStorage();
Platform.postChanges( gs, removed, added, this.mySrc );
}
} }
catch( final GridAccessException ignored ) catch( final GridAccessException ignored )
{ {
} }
// update the neighbors // update the neighbors
@@ -264,9 +264,11 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior
try try
{ {
this.getProxy().getGrid().postEvent( new MENetworkCellArrayUpdate() ); this.getProxy().getGrid().postEvent( new MENetworkCellArrayUpdate() );
if( this.getProxy().isActive() )
final IStorageGrid gs = this.getProxy().getStorage(); {
Platform.postChanges( gs, removed, added, this.mySrc ); final IStorageGrid gs = this.getProxy().getStorage();
Platform.postChanges( gs, removed, added, this.mySrc );
}
} }
catch( final GridAccessException ignored ) catch( final GridAccessException ignored )
{ {
@@ -418,10 +418,12 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
if( possible > 0 ) if( possible > 0 )
{ {
possible = Math.min( possible, itemsToMove ); IAEStack injectable = s.copy();
s.setStackSize( possible );
final IAEStack extracted = src.extractItems( s, Actionable.MODULATE, this.mySrc ); possible = Math.min( possible, itemsToMove );
injectable.setStackSize( possible );
final IAEStack extracted = src.extractItems( injectable, Actionable.MODULATE, this.mySrc );
if( extracted != null ) if( extracted != null )
{ {
possible = extracted.getStackSize(); possible = extracted.getStackSize();
@@ -500,8 +502,9 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
final IAEStack test = myList.getFirstItem(); final IAEStack test = myList.getFirstItem();
if( test != null ) if( test != null )
{ {
test.setStackSize( 1 ); IAEStack testCopy = test.copy();
return src.injectItems( test, Actionable.SIMULATE, this.mySrc ) != null; testCopy.setStackSize( 1 );
return src.injectItems( testCopy, Actionable.SIMULATE, this.mySrc ) != null;
} }
return false; return false;
} }
@@ -36,6 +36,7 @@ public final class ConfigManager implements IConfigManager
{ {
private final Map<Settings, Enum<?>> settings = new EnumMap<>( Settings.class ); private final Map<Settings, Enum<?>> settings = new EnumMap<>( Settings.class );
private final IConfigManagerHost target; private final IConfigManagerHost target;
private Map<Settings, Enum<?>> oldSettings = new EnumMap<>( Settings.class );
public ConfigManager( final IConfigManagerHost tile ) public ConfigManager( final IConfigManagerHost tile )
{ {
@@ -72,10 +73,15 @@ public final class ConfigManager implements IConfigManager
{ {
final Enum<?> oldValue = this.getSetting( settingName ); final Enum<?> oldValue = this.getSetting( settingName );
this.settings.put( settingName, newValue ); this.settings.put( settingName, newValue );
this.oldSettings.put( settingName, oldValue );
this.target.updateSetting( this, settingName, newValue ); this.target.updateSetting( this, settingName, newValue );
return oldValue; return oldValue;
} }
public Enum<?> getOldSetting(final Settings settingName){
return this.oldSettings.get( settingName );
}
/** /**
* save all settings using config manager. * save all settings using config manager.
* *