Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 058e91b7e4 | |||
| 67bdd885d5 | |||
| 188e3a75cc | |||
| b9f6029005 | |||
| b607e018e6 | |||
| e6ccc24ae0 | |||
| 2cb452fd9e | |||
| 855c6f61a9 | |||
| 89a5ba46b1 | |||
| 69a3268549 | |||
| 4b42e478f1 | |||
| 6d03c860c5 | |||
| 6404f26cca | |||
| ced6ad865c | |||
| df08ce0513 | |||
| f9c274fb48 | |||
| 3582582e3f | |||
| 6de48f8541 | |||
| 5a2c2d06d3 | |||
| 98d3cafdfd | |||
| 904de49543 | |||
| b0772bf94c |
+1
-1
@@ -3,7 +3,7 @@ aechannel=stable
|
|||||||
aebuild=7
|
aebuild=7
|
||||||
aegroup=appeng
|
aegroup=appeng
|
||||||
aebasename=appliedenergistics2
|
aebasename=appliedenergistics2
|
||||||
trousers=omni-fixes-v43
|
trousers=omni-fixes-v47
|
||||||
|
|
||||||
#########################################################
|
#########################################################
|
||||||
# Versions #
|
# Versions #
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ import net.minecraft.world.World;
|
|||||||
import appeng.api.implementations.ICraftingPatternItem;
|
import appeng.api.implementations.ICraftingPatternItem;
|
||||||
import appeng.api.storage.data.IAEItemStack;
|
import appeng.api.storage.data.IAEItemStack;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* do not implement provided by {@link ICraftingPatternItem}
|
* do not implement provided by {@link ICraftingPatternItem}
|
||||||
@@ -84,6 +87,11 @@ public interface ICraftingPatternDetails
|
|||||||
*/
|
*/
|
||||||
boolean canSubstitute();
|
boolean canSubstitute();
|
||||||
|
|
||||||
|
default List<IAEItemStack> getSubstituteInputs( int slot )
|
||||||
|
{
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow using this INSTANCE of the pattern details to preform the crafting action with performance enhancements.
|
* Allow using this INSTANCE of the pattern details to preform the crafting action with performance enhancements.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
@@ -418,8 +422,12 @@ public class GuiInterfaceTerminal extends AEBaseGui
|
|||||||
// Search if the current inventory holds a pattern containing the search term.
|
// Search if the current inventory holds a pattern containing the search term.
|
||||||
if( !found )
|
if( !found )
|
||||||
{
|
{
|
||||||
|
int slot = 0;
|
||||||
for( final ItemStack itemStack : entry.getInventory() )
|
for( final ItemStack itemStack : entry.getInventory() )
|
||||||
{
|
{
|
||||||
|
if (slot > 8 + numUpgradesMap.get(entry) * 9) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if( !searchFieldInputs.isEmpty() && !searchFieldOutputs.isEmpty() ) {
|
if( !searchFieldInputs.isEmpty() && !searchFieldOutputs.isEmpty() ) {
|
||||||
if (this.itemStackMatchesSearchTerm(itemStack, searchFieldInputs, 0) || this.itemStackMatchesSearchTerm(itemStack, searchFieldOutputs, 1)) {
|
if (this.itemStackMatchesSearchTerm(itemStack, searchFieldInputs, 0) || this.itemStackMatchesSearchTerm(itemStack, searchFieldOutputs, 1)) {
|
||||||
found = true;
|
found = true;
|
||||||
@@ -441,6 +449,7 @@ public class GuiInterfaceTerminal extends AEBaseGui
|
|||||||
// If only Interfaces with empty slots should be shown, check that here
|
// If only Interfaces with empty slots should be shown, check that here
|
||||||
if(itemStack.isEmpty())
|
if(itemStack.isEmpty())
|
||||||
interfaceHasFreeSlots = true;
|
interfaceHasFreeSlots = true;
|
||||||
|
slot++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if found, filter skipped or machine name matching the search term, add it
|
// if found, filter skipped or machine name matching the search term, add it
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public class CraftingJob implements Runnable, ICraftingJob
|
|||||||
private final IItemList<IAEItemStack> missing = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
|
private final IItemList<IAEItemStack> missing = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
|
||||||
private final HashMap<String, TwoIntegers> opsAndMultiplier = new HashMap<>();
|
private final HashMap<String, TwoIntegers> opsAndMultiplier = new HashMap<>();
|
||||||
private final Object monitor = new Object();
|
private final Object monitor = new Object();
|
||||||
|
private final Stopwatch watch = Stopwatch.createUnstarted();
|
||||||
private CraftingTreeNode tree;
|
private CraftingTreeNode tree;
|
||||||
private final IAEItemStack output;
|
private final IAEItemStack output;
|
||||||
private boolean simulate = false;
|
private boolean simulate = false;
|
||||||
@@ -66,7 +67,10 @@ public class CraftingJob implements Runnable, ICraftingJob
|
|||||||
private long bytes = 0;
|
private long bytes = 0;
|
||||||
private final IActionSource actionSrc;
|
private final IActionSource actionSrc;
|
||||||
private final ICraftingCallback callback;
|
private final ICraftingCallback callback;
|
||||||
|
private boolean running = false;
|
||||||
private boolean done = false;
|
private boolean done = false;
|
||||||
|
private int time;
|
||||||
|
private int incTime;
|
||||||
|
|
||||||
private World wrapWorld( final World w )
|
private World wrapWorld( final World w )
|
||||||
{
|
{
|
||||||
@@ -133,6 +137,7 @@ public class CraftingJob implements Runnable, ICraftingJob
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
TickHandler.INSTANCE.registerCraftingSimulation( this.world, this );
|
TickHandler.INSTANCE.registerCraftingSimulation( this.world, this );
|
||||||
|
this.handlePausing();
|
||||||
|
|
||||||
final Stopwatch timer = Stopwatch.createStarted();
|
final Stopwatch timer = Stopwatch.createStarted();
|
||||||
|
|
||||||
@@ -214,6 +219,41 @@ public class CraftingJob implements Runnable, ICraftingJob
|
|||||||
this.finish();
|
this.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handlePausing() throws InterruptedException
|
||||||
|
{
|
||||||
|
if( !this.actionSrc.player().isPresent() && this.incTime > 100 )
|
||||||
|
{
|
||||||
|
this.incTime = 0;
|
||||||
|
synchronized ( this.monitor )
|
||||||
|
{
|
||||||
|
if( this.watch.elapsed( TimeUnit.MICROSECONDS ) > this.time )
|
||||||
|
{
|
||||||
|
this.running = false;
|
||||||
|
this.watch.stop();
|
||||||
|
this.monitor.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !this.running )
|
||||||
|
{
|
||||||
|
AELog.craftingDebug( "crafting job will now sleep" );
|
||||||
|
|
||||||
|
while ( !this.running )
|
||||||
|
{
|
||||||
|
this.monitor.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
AELog.craftingDebug( "crafting job now active" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Thread.interrupted() )
|
||||||
|
{
|
||||||
|
throw new InterruptedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.incTime++;
|
||||||
|
}
|
||||||
|
|
||||||
private void finish()
|
private void finish()
|
||||||
{
|
{
|
||||||
if( this.callback != null )
|
if( this.callback != null )
|
||||||
@@ -225,6 +265,7 @@ public class CraftingJob implements Runnable, ICraftingJob
|
|||||||
|
|
||||||
synchronized( this.monitor )
|
synchronized( this.monitor )
|
||||||
{
|
{
|
||||||
|
this.running = false;
|
||||||
this.done = true;
|
this.done = true;
|
||||||
this.monitor.notify();
|
this.monitor.notify();
|
||||||
}
|
}
|
||||||
@@ -270,13 +311,41 @@ public class CraftingJob implements Runnable, ICraftingJob
|
|||||||
/**
|
/**
|
||||||
* @return true if this needs more simulation
|
* @return true if this needs more simulation
|
||||||
*/
|
*/
|
||||||
public boolean simulateFor()
|
public boolean simulateFor(final int milli)
|
||||||
{
|
{
|
||||||
synchronized( this.monitor ) {
|
this.time = milli;
|
||||||
if ( this.done ) {
|
|
||||||
|
synchronized ( this.monitor )
|
||||||
|
{
|
||||||
|
if( this.done )
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if( !this.actionSrc.player().isPresent() )
|
||||||
|
{
|
||||||
|
this.watch.reset();
|
||||||
|
this.watch.start();
|
||||||
|
this.running = true;
|
||||||
|
|
||||||
|
AELog.craftingDebug( "main thread is now going to sleep" );
|
||||||
|
|
||||||
|
this.monitor.notify();
|
||||||
|
|
||||||
|
while ( this.running )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.monitor.wait();
|
||||||
|
}
|
||||||
|
catch( final InterruptedException ignored )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AELog.craftingDebug( "main thread is now active" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public class CraftingTreeNode
|
|||||||
|
|
||||||
IAEItemStack request( final MECraftingInventory inv, long l, final IActionSource src ) throws CraftBranchFailure, InterruptedException
|
IAEItemStack request( final MECraftingInventory inv, long l, final IActionSource src ) throws CraftBranchFailure, InterruptedException
|
||||||
{
|
{
|
||||||
|
this.job.handlePausing();
|
||||||
final List<IAEItemStack> thingsUsed = new ArrayList<>();
|
final List<IAEItemStack> thingsUsed = new ArrayList<>();
|
||||||
|
|
||||||
this.what.setStackSize( l );
|
this.what.setStackSize( l );
|
||||||
@@ -130,7 +130,12 @@ public class CraftingTreeNode
|
|||||||
|
|
||||||
if( this.parent.details.canSubstitute() )
|
if( this.parent.details.canSubstitute() )
|
||||||
{
|
{
|
||||||
itemList = inventoryList.findFuzzy( this.what, FuzzyMode.IGNORE_ALL );
|
final List<IAEItemStack> substitutes = this.parent.details.getSubstituteInputs(this.slot);
|
||||||
|
itemList = new ArrayList<>(substitutes.size());
|
||||||
|
|
||||||
|
for (IAEItemStack stack : substitutes) {
|
||||||
|
itemList.addAll(inventoryList.findFuzzy(stack, FuzzyMode.IGNORE_ALL));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ public class CraftingTreeProcess
|
|||||||
|
|
||||||
void request( final MECraftingInventory inv, final long i, final IActionSource src ) throws CraftBranchFailure, InterruptedException
|
void request( final MECraftingInventory inv, final long i, final IActionSource src ) throws CraftBranchFailure, InterruptedException
|
||||||
{
|
{
|
||||||
|
this.job.handlePausing();
|
||||||
if( this.fullSimulation )
|
if( this.fullSimulation )
|
||||||
{
|
{
|
||||||
final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
|
final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
|
||||||
|
|||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ import java.nio.BufferOverflowException;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import appeng.container.slot.AppEngSlot;
|
||||||
|
import appeng.container.slot.SlotPlayerHotBar;
|
||||||
|
import appeng.container.slot.SlotPlayerInv;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.entity.player.InventoryPlayer;
|
import net.minecraft.entity.player.InventoryPlayer;
|
||||||
@@ -70,6 +73,7 @@ import appeng.me.helpers.ChannelPowerSrc;
|
|||||||
import appeng.util.ConfigManager;
|
import appeng.util.ConfigManager;
|
||||||
import appeng.util.IConfigManagerHost;
|
import appeng.util.IConfigManagerHost;
|
||||||
import appeng.util.Platform;
|
import appeng.util.Platform;
|
||||||
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -342,6 +346,89 @@ public class ContainerFluidTerminal extends AEBaseContainer implements IConfigMa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack transferStackInSlot( final EntityPlayer p, final int idx )
|
||||||
|
{
|
||||||
|
if( Platform.isClient() )
|
||||||
|
{
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
EntityPlayerMP player = (EntityPlayerMP) p;
|
||||||
|
if( this.inventorySlots.get( idx ) instanceof SlotPlayerInv || this.inventorySlots.get( idx ) instanceof SlotPlayerHotBar )
|
||||||
|
{
|
||||||
|
final AppEngSlot clickSlot = (AppEngSlot) this.inventorySlots.get( idx ); // require AE SLots!
|
||||||
|
ItemStack itemStack = clickSlot.getStack();
|
||||||
|
|
||||||
|
ItemStack copy = itemStack.copy();
|
||||||
|
copy.setCount( 1 );
|
||||||
|
IFluidHandlerItem fh = FluidUtil.getFluidHandler( copy );
|
||||||
|
if( fh == null )
|
||||||
|
{
|
||||||
|
// only fluid handlers items
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
int heldAmount = itemStack.getCount();
|
||||||
|
for( int i = 0; i < heldAmount; i++ )
|
||||||
|
{
|
||||||
|
copy = itemStack.copy();
|
||||||
|
copy.setCount( 1 );
|
||||||
|
fh = FluidUtil.getFluidHandler( copy );
|
||||||
|
|
||||||
|
final FluidStack extract = fh.drain( Integer.MAX_VALUE, false );
|
||||||
|
if( extract == null || extract.amount < 1 )
|
||||||
|
{
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we can push into the system
|
||||||
|
final IAEFluidStack notStorable = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), this.getActionSource(), Actionable.SIMULATE );
|
||||||
|
|
||||||
|
if( notStorable != null && notStorable.getStackSize() > 0 )
|
||||||
|
{
|
||||||
|
final int toStore = (int) ( extract.amount - notStorable.getStackSize() );
|
||||||
|
final FluidStack storable = fh.drain( toStore, false );
|
||||||
|
|
||||||
|
if( storable == null || storable.amount == 0 )
|
||||||
|
{
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
extract.amount = storable.amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually drain
|
||||||
|
final FluidStack drained = fh.drain( extract, true );
|
||||||
|
extract.amount = drained.amount;
|
||||||
|
|
||||||
|
final IAEFluidStack notInserted = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), this.getActionSource() );
|
||||||
|
|
||||||
|
if( notInserted != null && notInserted.getStackSize() > 0 )
|
||||||
|
{
|
||||||
|
IAEFluidStack spill = this.monitor.injectItems( notInserted, Actionable.MODULATE, this.getActionSource() );
|
||||||
|
if( spill != null && spill.getStackSize() > 0 )
|
||||||
|
{
|
||||||
|
fh.fill( spill.getFluidStack(), true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( notInserted == null )
|
||||||
|
{
|
||||||
|
if( !player.inventory.addItemStackToInventory( fh.getContainer() ) )
|
||||||
|
{
|
||||||
|
player.dropItem( fh.getContainer(), false );
|
||||||
|
}
|
||||||
|
clickSlot.decrStackSize( 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.detectAndSendChanges();
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
return super.transferStackInSlot( p, idx );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAction( EntityPlayerMP player, InventoryAction action, int slot, long id )
|
public void doAction( EntityPlayerMP player, InventoryAction action, int slot, long id )
|
||||||
{
|
{
|
||||||
@@ -352,13 +439,9 @@ public class ContainerFluidTerminal extends AEBaseContainer implements IConfigMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
final ItemStack held = player.inventory.getItemStack();
|
final ItemStack held = player.inventory.getItemStack();
|
||||||
if( held.getCount() != 1 )
|
ItemStack heldCopy = held.copy();
|
||||||
{
|
heldCopy.setCount( 1 );
|
||||||
// only support stacksize 1 for now
|
IFluidHandlerItem fh = FluidUtil.getFluidHandler( heldCopy );
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final IFluidHandlerItem fh = FluidUtil.getFluidHandler( held );
|
|
||||||
if( fh == null )
|
if( fh == null )
|
||||||
{
|
{
|
||||||
// only fluid handlers items
|
// only fluid handlers items
|
||||||
@@ -372,88 +455,122 @@ public class ContainerFluidTerminal extends AEBaseContainer implements IConfigMa
|
|||||||
// Check how much we can store in the item
|
// Check how much we can store in the item
|
||||||
stack.setStackSize( Integer.MAX_VALUE );
|
stack.setStackSize( Integer.MAX_VALUE );
|
||||||
int amountAllowed = fh.fill( stack.getFluidStack(), false );
|
int amountAllowed = fh.fill( stack.getFluidStack(), false );
|
||||||
stack.setStackSize( amountAllowed );
|
int heldAmount = held.getCount();
|
||||||
|
for( int i = 0; i < heldAmount; i++ )
|
||||||
// Check if we can pull out of the system
|
|
||||||
final IAEFluidStack canPull = Platform.poweredExtraction( this.getPowerSource(), this.monitor, stack, this.getActionSource(), Actionable.SIMULATE );
|
|
||||||
if( canPull == null || canPull.getStackSize() < 1 )
|
|
||||||
{
|
{
|
||||||
return;
|
ItemStack copiedFluidContainer = held.copy();
|
||||||
}
|
copiedFluidContainer.setCount( 1 );
|
||||||
|
fh = FluidUtil.getFluidHandler( copiedFluidContainer );
|
||||||
|
|
||||||
// How much could fit into the container
|
// Check if we can pull out of the system
|
||||||
final int canFill = fh.fill( canPull.getFluidStack(), false );
|
final IAEFluidStack canPull = Platform.poweredExtraction( this.getPowerSource(), this.monitor, stack.setStackSize( amountAllowed ), this.getActionSource(), Actionable.SIMULATE );
|
||||||
if( canFill == 0 )
|
if( canPull == null || canPull.getStackSize() < 1 )
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now actually pull out of the system
|
|
||||||
stack.setStackSize( canFill );
|
|
||||||
final IAEFluidStack pulled = Platform.poweredExtraction( this.getPowerSource(), this.monitor, stack, this.getActionSource() );
|
|
||||||
if( pulled == null || pulled.getStackSize() < 1 )
|
|
||||||
{
|
|
||||||
// Something went wrong
|
|
||||||
AELog.error( "Unable to pull fluid out of the ME system even though the simulation said yes " );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actually fill
|
|
||||||
final int used = fh.fill( pulled.getFluidStack(), true );
|
|
||||||
|
|
||||||
if( used != canFill )
|
|
||||||
{
|
|
||||||
AELog.error( "Fluid item [%s] reported a different possible amount than it actually accepted.", held.getDisplayName() );
|
|
||||||
}
|
|
||||||
|
|
||||||
player.inventory.setItemStack( fh.getContainer() );
|
|
||||||
this.updateHeld( player );
|
|
||||||
}
|
|
||||||
else if( action == InventoryAction.EMPTY_ITEM )
|
|
||||||
{
|
|
||||||
// See how much we can drain from the item
|
|
||||||
final FluidStack extract = fh.drain( Integer.MAX_VALUE, false );
|
|
||||||
if( extract == null || extract.amount < 1 )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we can push into the system
|
|
||||||
final IAEFluidStack notStorable = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ),
|
|
||||||
this.getActionSource(), Actionable.SIMULATE );
|
|
||||||
|
|
||||||
if( notStorable != null && notStorable.getStackSize() > 0 )
|
|
||||||
{
|
|
||||||
final int toStore = (int) ( extract.amount - notStorable.getStackSize() );
|
|
||||||
final FluidStack storable = fh.drain( toStore, false );
|
|
||||||
|
|
||||||
if( storable == null || storable.amount == 0 )
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// How much could fit into the container
|
||||||
|
final int canFill = fh.fill( canPull.getFluidStack(), false );
|
||||||
|
if( canFill == 0 )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now actually pull out of the system
|
||||||
|
final IAEFluidStack pulled = Platform.poweredExtraction( this.getPowerSource(), this.monitor, stack.setStackSize( canFill ), this.getActionSource() );
|
||||||
|
if( pulled == null || pulled.getStackSize() < 1 )
|
||||||
|
{
|
||||||
|
// Something went wrong
|
||||||
|
AELog.error( "Unable to pull fluid out of the ME system even though the simulation said yes " );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually fill
|
||||||
|
final int used = fh.fill( pulled.getFluidStack(), true );
|
||||||
|
|
||||||
|
if( used != canFill )
|
||||||
|
{
|
||||||
|
AELog.error( "Fluid item [%s] reported a different possible amount than it actually accepted.", held.getDisplayName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( held.getCount() == 1 )
|
||||||
|
{
|
||||||
|
player.inventory.setItemStack( fh.getContainer() );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
extract.amount = storable.amount;
|
player.inventory.getItemStack().shrink( 1 );
|
||||||
|
if( !player.inventory.addItemStackToInventory( fh.getContainer() ) )
|
||||||
|
{
|
||||||
|
player.dropItem( fh.getContainer(), false );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.updateHeld( player );
|
||||||
|
|
||||||
// Actually drain
|
}
|
||||||
final FluidStack drained = fh.drain( extract, true );
|
else if( action == InventoryAction.EMPTY_ITEM )
|
||||||
extract.amount = drained.amount;
|
{
|
||||||
|
int heldAmount = held.getCount();
|
||||||
final IAEFluidStack notInserted = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ),
|
for( int i = 0; i < heldAmount; i++ )
|
||||||
this.getActionSource() );
|
|
||||||
|
|
||||||
if( notInserted != null && notInserted.getStackSize() > 0 )
|
|
||||||
{
|
{
|
||||||
IAEFluidStack spill = this.monitor.injectItems( notInserted, Actionable.MODULATE, this.getActionSource() );
|
ItemStack copiedFluidContainer = held.copy();
|
||||||
if( spill != null && spill.getStackSize() > 0 )
|
copiedFluidContainer.setCount( 1 );
|
||||||
|
fh = FluidUtil.getFluidHandler( copiedFluidContainer );
|
||||||
|
|
||||||
|
// See how much we can drain from the item
|
||||||
|
final FluidStack extract = fh.drain( Integer.MAX_VALUE, false );
|
||||||
|
if( extract == null || extract.amount < 1 )
|
||||||
{
|
{
|
||||||
fh.fill( spill.getFluidStack(), true );
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we can push into the system
|
||||||
|
final IAEFluidStack notStorable = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), this.getActionSource(), Actionable.SIMULATE );
|
||||||
|
|
||||||
|
if( notStorable != null && notStorable.getStackSize() > 0 )
|
||||||
|
{
|
||||||
|
final int toStore = (int) ( extract.amount - notStorable.getStackSize() );
|
||||||
|
final FluidStack storable = fh.drain( toStore, false );
|
||||||
|
|
||||||
|
if( storable == null || storable.amount == 0 )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
extract.amount = storable.amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually drain
|
||||||
|
final FluidStack drained = fh.drain( extract, true );
|
||||||
|
extract.amount = drained.amount;
|
||||||
|
|
||||||
|
final IAEFluidStack notInserted = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), this.getActionSource() );
|
||||||
|
|
||||||
|
if( notInserted != null && notInserted.getStackSize() > 0 )
|
||||||
|
{
|
||||||
|
IAEFluidStack spill = this.monitor.injectItems( notInserted, Actionable.MODULATE, this.getActionSource() );
|
||||||
|
if( spill != null && spill.getStackSize() > 0 )
|
||||||
|
{
|
||||||
|
fh.fill( spill.getFluidStack(), 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 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player.inventory.setItemStack( fh.getContainer() );
|
|
||||||
this.updateHeld( player );
|
this.updateHeld( player );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -608,14 +608,14 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
|
|||||||
List<ItemStack> dropList = new ArrayList<>();
|
List<ItemStack> dropList = new ArrayList<>();
|
||||||
for( int invSlot = 0; invSlot < patterns.getSlots(); invSlot++ )
|
for( int invSlot = 0; invSlot < patterns.getSlots(); invSlot++ )
|
||||||
{
|
{
|
||||||
if( invSlot >= 9 + ( this.getInstalledUpgrades( Upgrades.PATTERN_EXPANSION ) ) * 9 )
|
if( invSlot > 8 + this.getInstalledUpgrades( Upgrades.PATTERN_EXPANSION ) * 9 )
|
||||||
{
|
{
|
||||||
ItemStack is = patterns.getStackInSlot( invSlot );
|
ItemStack is = patterns.getStackInSlot( invSlot );
|
||||||
if( is.isEmpty() ) continue;
|
if( is.isEmpty() ) continue;
|
||||||
dropList.add( patterns.extractItem( invSlot, Integer.MAX_VALUE, false ) );
|
dropList.add( patterns.extractItem( invSlot, Integer.MAX_VALUE, false ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( dropList.size() > 1 )
|
if( dropList.size() > 0 )
|
||||||
{
|
{
|
||||||
World world = this.getLocation().getWorld();
|
World world = this.getLocation().getWorld();
|
||||||
BlockPos blockPos = this.getLocation().getPos();
|
BlockPos blockPos = this.getLocation().getPos();
|
||||||
|
|||||||
@@ -19,21 +19,18 @@
|
|||||||
package appeng.helpers;
|
package appeng.helpers;
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
import java.util.stream.Collectors;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.StringJoiner;
|
|
||||||
|
|
||||||
import net.minecraft.inventory.InventoryCrafting;
|
import net.minecraft.inventory.InventoryCrafting;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.crafting.CraftingManager;
|
import net.minecraft.item.crafting.CraftingManager;
|
||||||
import net.minecraft.item.crafting.IRecipe;
|
import net.minecraft.item.crafting.IRecipe;
|
||||||
|
import net.minecraft.item.crafting.Ingredient;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.nbt.NBTTagList;
|
import net.minecraft.nbt.NBTTagList;
|
||||||
|
import net.minecraft.util.NonNullList;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import appeng.api.AEApi;
|
import appeng.api.AEApi;
|
||||||
@@ -46,11 +43,17 @@ import appeng.core.AELog;
|
|||||||
import appeng.core.features.AEFeature;
|
import appeng.core.features.AEFeature;
|
||||||
import appeng.util.Platform;
|
import appeng.util.Platform;
|
||||||
import appeng.util.item.AEItemStack;
|
import appeng.util.item.AEItemStack;
|
||||||
|
import net.minecraftforge.common.crafting.IShapedRecipe;
|
||||||
|
|
||||||
|
|
||||||
public class PatternHelper implements ICraftingPatternDetails, Comparable<PatternHelper>
|
public class PatternHelper implements ICraftingPatternDetails, Comparable<PatternHelper>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private static final int CRAFTING_GRID_DIMENSION = 3;
|
||||||
|
private static final int ALL_INPUT_LIMIT = CRAFTING_GRID_DIMENSION * CRAFTING_GRID_DIMENSION;
|
||||||
|
private static final int CRAFTING_OUTPUT_LIMIT = 1;
|
||||||
|
private static final int PROCESSING_OUTPUT_LIMIT = 3;
|
||||||
|
|
||||||
private final ItemStack patternItem;
|
private final ItemStack patternItem;
|
||||||
private final InventoryCrafting crafting = new InventoryCrafting( new ContainerNull(), 3, 3 );
|
private final InventoryCrafting crafting = new InventoryCrafting( new ContainerNull(), 3, 3 );
|
||||||
private final InventoryCrafting testFrame = new InventoryCrafting( new ContainerNull(), 3, 3 );
|
private final InventoryCrafting testFrame = new InventoryCrafting( new ContainerNull(), 3, 3 );
|
||||||
@@ -60,6 +63,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
private final IAEItemStack[] condensedOutputs;
|
private final IAEItemStack[] condensedOutputs;
|
||||||
private final IAEItemStack[] inputs;
|
private final IAEItemStack[] inputs;
|
||||||
private final IAEItemStack[] outputs;
|
private final IAEItemStack[] outputs;
|
||||||
|
private final Map<Integer, List<IAEItemStack>> substituteInputs;
|
||||||
private final boolean isCrafting;
|
private final boolean isCrafting;
|
||||||
private final boolean canSubstitute;
|
private final boolean canSubstitute;
|
||||||
private final Set<TestLookup> failCache = new HashSet<>();
|
private final Set<TestLookup> failCache = new HashSet<>();
|
||||||
@@ -143,9 +147,11 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final int outputLength = out.size();
|
||||||
|
|
||||||
this.outputs = out.toArray( new IAEItemStack[out.size()] );
|
this.inputs = in.toArray(new IAEItemStack[ALL_INPUT_LIMIT]);
|
||||||
this.inputs = in.toArray( new IAEItemStack[in.size()] );
|
this.outputs = out.toArray(new IAEItemStack[outputLength]);
|
||||||
|
this.substituteInputs = new HashMap<>(ALL_INPUT_LIMIT);
|
||||||
|
|
||||||
final Map<IAEItemStack, IAEItemStack> tmpOutputs = new HashMap<>();
|
final Map<IAEItemStack, IAEItemStack> tmpOutputs = new HashMap<>();
|
||||||
|
|
||||||
@@ -257,6 +263,14 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
|
|
||||||
this.testFrame.setInventorySlotContents( slotIndex, i );
|
this.testFrame.setInventorySlotContents( slotIndex, i );
|
||||||
|
|
||||||
|
// If we cannot substitute, the items must match exactly
|
||||||
|
if (!canSubstitute && slotIndex < inputs.length) {
|
||||||
|
if (!inputs[slotIndex].isSameType(i)) {
|
||||||
|
this.markItemAs(slotIndex, i, TestStatus.DECLINE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( this.standardRecipe.matches( this.testFrame, w ) )
|
if( this.standardRecipe.matches( this.testFrame, w ) )
|
||||||
{
|
{
|
||||||
final ItemStack testOutput = this.standardRecipe.getCraftingResult( this.testFrame );
|
final ItemStack testOutput = this.standardRecipe.getCraftingResult( this.testFrame );
|
||||||
@@ -268,25 +282,6 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( AEConfig.instance().isFeatureEnabled( AEFeature.CRAFTING_MANAGER_FALLBACK ) )
|
|
||||||
{
|
|
||||||
final ItemStack testOutput = CraftingManager.findMatchingResult( this.testFrame, w );
|
|
||||||
|
|
||||||
if( Platform.itemComparisons().isSameItem( this.correctOutput, testOutput ) )
|
|
||||||
{
|
|
||||||
this.testFrame.setInventorySlotContents( slotIndex, this.crafting.getStackInSlot( slotIndex ) );
|
|
||||||
this.markItemAs( slotIndex, i, TestStatus.ACCEPT );
|
|
||||||
|
|
||||||
if( AELog.isCraftingDebugLogEnabled() )
|
|
||||||
{
|
|
||||||
this.warnAboutCraftingManager( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.warnAboutCraftingManager( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
this.markItemAs( slotIndex, i, TestStatus.DECLINE );
|
this.markItemAs( slotIndex, i, TestStatus.DECLINE );
|
||||||
return false;
|
return false;
|
||||||
@@ -328,6 +323,97 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
return this.canSubstitute;
|
return this.canSubstitute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IAEItemStack> getSubstituteInputs(int slot) {
|
||||||
|
if (this.inputs[slot] == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.substituteInputs.computeIfAbsent(slot, value -> {
|
||||||
|
ItemStack[] matchingStacks = getRecipeIngredient(slot).getMatchingStacks();
|
||||||
|
List<IAEItemStack> itemList = new ArrayList<>(matchingStacks.length + 1);
|
||||||
|
for (ItemStack matchingStack : matchingStacks) {
|
||||||
|
itemList.add(AEItemStack.fromItemStack(matchingStack));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the specific item put in by the user is at the beginning,
|
||||||
|
// so that it takes precedence over substitutions
|
||||||
|
itemList.add(0, this.inputs[slot]);
|
||||||
|
return itemList;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link Ingredient} from the actual used recipe for a given slot-index into {@link #getInputs()}.
|
||||||
|
* <p/>
|
||||||
|
* Conversion is needed for two reasons: our sparse ingredients are always organized in a 3x3 grid, while Vanilla's
|
||||||
|
* ingredient list will be condensed to the actual recipe's grid size. In addition, in our 3x3 grid, the user can
|
||||||
|
* shift the actual recipe input to the right and down.
|
||||||
|
*/
|
||||||
|
private Ingredient getRecipeIngredient(int slot) {
|
||||||
|
|
||||||
|
if (standardRecipe instanceof IShapedRecipe ) {
|
||||||
|
IShapedRecipe shapedRecipe = (IShapedRecipe) standardRecipe;
|
||||||
|
|
||||||
|
return getShapedRecipeIngredient(slot, shapedRecipe.getRecipeWidth());
|
||||||
|
} else {
|
||||||
|
return getShapelessRecipeIngredient(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Ingredient getShapedRecipeIngredient(int slot, int recipeWidth) {
|
||||||
|
// Compute the offset of the user's input vs. crafting grid origin
|
||||||
|
// Which is >0 if they have empty rows above or to the left of their input
|
||||||
|
int topOffset = 0;
|
||||||
|
if (inputs[0] == null && inputs[1] == null && inputs[2] == null) {
|
||||||
|
topOffset++; // First row is fully empty
|
||||||
|
if (inputs[3] == null && inputs[4] == null && inputs[5] == null) {
|
||||||
|
topOffset++; // Second row is fully empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int leftOffset = 0;
|
||||||
|
if (inputs[0] == null && inputs[3] == null && inputs[6] == null) {
|
||||||
|
leftOffset++; // First column is fully empty
|
||||||
|
if (inputs[1] == null && inputs[4] == null && inputs[7] == null) {
|
||||||
|
leftOffset++; // Second column is fully empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the x,y of the slot, as-if the recipe was anchored to 0,0
|
||||||
|
int slotX = slot % CRAFTING_GRID_DIMENSION - leftOffset;
|
||||||
|
int slotY = slot / CRAFTING_GRID_DIMENSION - topOffset;
|
||||||
|
|
||||||
|
// Compute the index into the recipe's ingredient list now
|
||||||
|
int ingredientIndex = slotY * recipeWidth + slotX;
|
||||||
|
|
||||||
|
NonNullList<Ingredient> ingredients = standardRecipe.getIngredients();
|
||||||
|
|
||||||
|
if (ingredientIndex < 0 || ingredientIndex > ingredients.size()) {
|
||||||
|
return Ingredient.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ingredients.get(ingredientIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Ingredient getShapelessRecipeIngredient(int slot) {
|
||||||
|
// We map the list of *filled* sparse inputs to the shapeless (ergo unordered)
|
||||||
|
// ingredients. While these do not actually correspond to each other,
|
||||||
|
// since both lists have the same length, the mapping is at least stable.
|
||||||
|
int ingredientIndex = 0;
|
||||||
|
for (int i = 0; i < slot; i++) {
|
||||||
|
if (inputs[i] != null) {
|
||||||
|
ingredientIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NonNullList<Ingredient> ingredients = standardRecipe.getIngredients();
|
||||||
|
if (ingredientIndex < ingredients.size()) {
|
||||||
|
return ingredients.get(ingredientIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ingredient.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getOutput( final InventoryCrafting craftingInv, final World w )
|
public ItemStack getOutput( final InventoryCrafting craftingInv, final World w )
|
||||||
{
|
{
|
||||||
@@ -406,24 +492,6 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
return this.pattern.hashCode();
|
return this.pattern.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void warnAboutCraftingManager( boolean foundAlternative )
|
|
||||||
{
|
|
||||||
final String foundAlternativeRecipe = foundAlternative ? "Found alternative recipe." : "NOT FOUND, please report.";
|
|
||||||
|
|
||||||
final StringJoiner joinActualInputs = new StringJoiner( ", " );
|
|
||||||
for( int j = 0; j < this.testFrame.getSizeInventory(); j++ )
|
|
||||||
{
|
|
||||||
final ItemStack stack = this.testFrame.getStackInSlot( j );
|
|
||||||
if( !stack.isEmpty() )
|
|
||||||
{
|
|
||||||
joinActualInputs.add( stack.toString() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AELog.warn( "Using CraftingManager fallback: Recipe <%s> for output <%s> rejected inputs [%s]. %s",
|
|
||||||
this.standardRecipe.getRegistryName(), this.standardRecipe.getRecipeOutput(), joinActualInputs, foundAlternativeRecipe );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals( final Object obj )
|
public boolean equals( final Object obj )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -187,20 +187,15 @@ public class TickHandler
|
|||||||
if( ev.type == Type.WORLD && ev.phase == Phase.END )
|
if( ev.type == Type.WORLD && ev.phase == Phase.END )
|
||||||
{
|
{
|
||||||
final WorldTickEvent wte = (WorldTickEvent) ev;
|
final WorldTickEvent wte = (WorldTickEvent) ev;
|
||||||
synchronized( this.craftingJobs )
|
synchronized ( this.craftingJobs )
|
||||||
{
|
{
|
||||||
final Collection<CraftingJob> jobSet = this.craftingJobs.get( wte.world );
|
final Collection<CraftingJob> jobSet = this.craftingJobs.get( wte.world );
|
||||||
if( !jobSet.isEmpty() )
|
if (!jobSet.isEmpty()) {
|
||||||
{
|
final int jobSize = jobSet.size();
|
||||||
final Iterator<CraftingJob> i = jobSet.iterator();
|
final int microSecondsPerTick = AEConfig.instance().getCraftingCalculationTimePerTick() * 1000;
|
||||||
while( i.hasNext() )
|
final int simTime = Math.max(1, microSecondsPerTick / jobSize);
|
||||||
{
|
|
||||||
final CraftingJob cj = i.next();
|
jobSet.removeIf( cj -> !cj.simulateFor( simTime ) );
|
||||||
if( !cj.simulateFor() )
|
|
||||||
{
|
|
||||||
i.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,8 +147,12 @@ class RecipeTransferHandler<T extends Container> implements IRecipeTransferHandl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// prefer pure crystals.
|
// prefer pure crystals.
|
||||||
for( ItemStack stack : ingredient.getAllIngredients() )
|
for ( ItemStack stack : ingredient.getAllIngredients() )
|
||||||
{
|
{
|
||||||
|
if( stack == null )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if( Platform.isRecipePrioritized( stack ) )
|
if( Platform.isRecipePrioritized( stack ) )
|
||||||
{
|
{
|
||||||
list.add( 0, stack );
|
list.add( 0, stack );
|
||||||
@@ -159,7 +163,7 @@ class RecipeTransferHandler<T extends Container> implements IRecipeTransferHandl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for( final ItemStack is : list )
|
for ( final ItemStack is : list )
|
||||||
{
|
{
|
||||||
final NBTTagCompound tag = new NBTTagCompound();
|
final NBTTagCompound tag = new NBTTagCompound();
|
||||||
is.writeToNBT( tag );
|
is.writeToNBT( tag );
|
||||||
|
|||||||
+26
-156
@@ -30,7 +30,6 @@ import java.util.PriorityQueue;
|
|||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.collect.HashMultiset;
|
import com.google.common.collect.HashMultiset;
|
||||||
import com.google.common.collect.Multiset;
|
import com.google.common.collect.Multiset;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
@@ -64,9 +63,8 @@ import appeng.me.energy.EnergyWatcher;
|
|||||||
public class EnergyGridCache implements IEnergyGrid
|
public class EnergyGridCache implements IEnergyGrid
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final double MAX_BUFFER_STORAGE = 800;
|
private static final double MAX_BUFFER_STORAGE = 200;
|
||||||
private static final Comparator<IEnergyGridProvider> COMPARATOR_HIGHEST_AMOUNT_STORED_FIRST = ( o1, o2 ) -> Double.compare( o2.getProviderStoredEnergy(),
|
private static final Comparator<IEnergyGridProvider> COMPARATOR_HIGHEST_AMOUNT_STORED_FIRST = ( o1, o2 ) -> Double.compare( o2.getProviderStoredEnergy(), o1.getProviderStoredEnergy() );
|
||||||
o1.getProviderStoredEnergy() );
|
|
||||||
|
|
||||||
private static final Comparator<IEnergyGridProvider> COMPARATOR_LOWEST_PERCENTAGE_FIRST = ( o1, o2 ) ->
|
private static final Comparator<IEnergyGridProvider> COMPARATOR_LOWEST_PERCENTAGE_FIRST = ( o1, o2 ) ->
|
||||||
{
|
{
|
||||||
@@ -77,24 +75,9 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
};
|
};
|
||||||
|
|
||||||
private final NavigableSet<EnergyThreshold> interests = Sets.newTreeSet();
|
private final NavigableSet<EnergyThreshold> interests = Sets.newTreeSet();
|
||||||
|
|
||||||
// Should only be modified from the add/remove methods below to guard against
|
|
||||||
// concurrent modifications
|
|
||||||
private final double averageLength = 40.0;
|
private final double averageLength = 40.0;
|
||||||
private final Set<IAEPowerStorage> providers = new LinkedHashSet<>();
|
private final Set<IAEPowerStorage> providers = new LinkedHashSet<>();
|
||||||
// Used to track whether an extraction is currently in progress, to fail fast
|
|
||||||
// when something externally
|
|
||||||
// modifies the energy grid.
|
|
||||||
private boolean ongoingExtractOperation = false;
|
|
||||||
|
|
||||||
// Should only be modified from the add/remove methods below to guard against
|
|
||||||
// concurrent modifications
|
|
||||||
private final Set<IAEPowerStorage> requesters = new LinkedHashSet<>();
|
private final Set<IAEPowerStorage> requesters = new LinkedHashSet<>();
|
||||||
// Used to track whether an injection is currently in progress, to fail fast
|
|
||||||
// when something externally
|
|
||||||
// modifies the energy grid.
|
|
||||||
private boolean ongoingInjectOperation = false;
|
|
||||||
|
|
||||||
private final Multiset<IEnergyGridProvider> energyGridProviders = HashMultiset.create();
|
private final Multiset<IEnergyGridProvider> energyGridProviders = HashMultiset.create();
|
||||||
private final IGrid myGrid;
|
private final IGrid myGrid;
|
||||||
private final HashMap<IGridNode, IEnergyWatcher> watchers = new HashMap<>();
|
private final HashMap<IGridNode, IEnergyWatcher> watchers = new HashMap<>();
|
||||||
@@ -126,10 +109,6 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
private double lastStoredPower = -1;
|
private double lastStoredPower = -1;
|
||||||
|
|
||||||
private final GridPowerStorage localStorage = new GridPowerStorage();
|
private final GridPowerStorage localStorage = new GridPowerStorage();
|
||||||
private Set<IAEPowerStorage> providerToRemove = new HashSet<>();
|
|
||||||
private Set<IAEPowerStorage> requesterToRemove = new HashSet<>();
|
|
||||||
private Set<IAEPowerStorage> providersToAdd = new HashSet<>();
|
|
||||||
private Set<IAEPowerStorage> requesterToAdd = new HashSet<>();
|
|
||||||
|
|
||||||
public EnergyGridCache( final IGrid g )
|
public EnergyGridCache( final IGrid g )
|
||||||
{
|
{
|
||||||
@@ -168,27 +147,13 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
case PROVIDE_POWER:
|
case PROVIDE_POWER:
|
||||||
if( ev.storage.getPowerFlow() != AccessRestriction.WRITE )
|
if( ev.storage.getPowerFlow() != AccessRestriction.WRITE )
|
||||||
{
|
{
|
||||||
if( !ongoingExtractOperation )
|
this.providers.add( ev.storage );
|
||||||
{
|
|
||||||
addProvider( ev.storage );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.providersToAdd.add( ev.storage );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REQUEST_POWER:
|
case REQUEST_POWER:
|
||||||
if( ev.storage.getPowerFlow() != AccessRestriction.READ )
|
if( ev.storage.getPowerFlow() != AccessRestriction.READ )
|
||||||
{
|
{
|
||||||
if( !ongoingInjectOperation )
|
this.requesters.add( ev.storage );
|
||||||
{
|
|
||||||
addRequester( ev.storage );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.requesterToAdd.add( ev.storage );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -202,23 +167,6 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
@Override
|
@Override
|
||||||
public void onUpdateTick()
|
public void onUpdateTick()
|
||||||
{
|
{
|
||||||
if (!providerToRemove.isEmpty() && !ongoingExtractOperation) {
|
|
||||||
this.providers.removeIf( p -> providerToRemove.contains( p ) );
|
|
||||||
providerToRemove.clear();
|
|
||||||
}
|
|
||||||
if (!requesterToRemove.isEmpty() && !ongoingInjectOperation) {
|
|
||||||
this.requesters.removeIf( r -> providerToRemove.contains( r ) );
|
|
||||||
requesterToRemove.clear();
|
|
||||||
}
|
|
||||||
if (!providersToAdd.isEmpty() && !ongoingExtractOperation) {
|
|
||||||
this.providers.addAll(providersToAdd);
|
|
||||||
providersToAdd.clear();
|
|
||||||
}
|
|
||||||
if( !requesterToAdd.isEmpty() && !ongoingInjectOperation){
|
|
||||||
this.requesters.addAll(requesterToAdd);
|
|
||||||
requesterToAdd.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !this.interests.isEmpty() )
|
if( !this.interests.isEmpty() )
|
||||||
{
|
{
|
||||||
final double oldPower = this.lastStoredPower;
|
final double oldPower = this.lastStoredPower;
|
||||||
@@ -354,30 +302,18 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
|
|
||||||
final Iterator<IAEPowerStorage> it = this.providers.iterator();
|
final Iterator<IAEPowerStorage> it = this.providers.iterator();
|
||||||
|
|
||||||
ongoingExtractOperation = true;
|
while ( extractedPower < amt && it.hasNext() )
|
||||||
try
|
|
||||||
{
|
{
|
||||||
while ( extractedPower < amt && it.hasNext() )
|
final IAEPowerStorage node = it.next();
|
||||||
|
|
||||||
|
final double req = amt - extractedPower;
|
||||||
|
final double newPower = node.extractAEPower( req, mode, PowerMultiplier.ONE );
|
||||||
|
extractedPower += newPower;
|
||||||
|
|
||||||
|
if( newPower < req && mode == Actionable.MODULATE )
|
||||||
{
|
{
|
||||||
final IAEPowerStorage node = it.next();
|
it.remove();
|
||||||
|
|
||||||
if ( providerToRemove.contains( node )) {
|
|
||||||
it.remove();
|
|
||||||
providerToRemove.remove( node );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final double req = amt - extractedPower;
|
|
||||||
final double newPower = node.extractAEPower( req, mode, PowerMultiplier.ONE );
|
|
||||||
extractedPower += newPower;
|
|
||||||
|
|
||||||
if( newPower < req && mode == Actionable.MODULATE )
|
|
||||||
{
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
ongoingExtractOperation = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final double result = Math.min( extractedPower, amt );
|
final double result = Math.min( extractedPower, amt );
|
||||||
@@ -403,29 +339,15 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
|
|
||||||
final Iterator<IAEPowerStorage> it = this.requesters.iterator();
|
final Iterator<IAEPowerStorage> it = this.requesters.iterator();
|
||||||
|
|
||||||
ongoingInjectOperation = true;
|
while ( amt > 0 && it.hasNext() )
|
||||||
try
|
|
||||||
{
|
{
|
||||||
while ( amt > 0 && it.hasNext() )
|
final IAEPowerStorage node = it.next();
|
||||||
|
amt = node.injectAEPower( amt, mode );
|
||||||
|
|
||||||
|
if( amt > 0 && mode == Actionable.MODULATE )
|
||||||
{
|
{
|
||||||
final IAEPowerStorage node = it.next();
|
it.remove();
|
||||||
|
|
||||||
if ( requesterToRemove.contains( node )) {
|
|
||||||
it.remove();
|
|
||||||
requesterToRemove.remove( node );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
amt = node.injectAEPower( amt, mode );
|
|
||||||
|
|
||||||
if( amt > 0 && mode == Actionable.MODULATE )
|
|
||||||
{
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} finally
|
|
||||||
{
|
|
||||||
ongoingInjectOperation = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final double overflow = Math.max( 0.0, amt );
|
final double overflow = Math.max( 0.0, amt );
|
||||||
@@ -505,7 +427,7 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
@Override
|
@Override
|
||||||
public double getStoredPower()
|
public double getStoredPower()
|
||||||
{
|
{
|
||||||
if( this.availableTicksSinceUpdate > 2 )
|
if( this.availableTicksSinceUpdate > 90 )
|
||||||
{
|
{
|
||||||
this.refreshPower();
|
this.refreshPower();
|
||||||
}
|
}
|
||||||
@@ -582,22 +504,9 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
this.globalMaxPower -= ps.getAEMaxPower();
|
this.globalMaxPower -= ps.getAEMaxPower();
|
||||||
this.globalAvailablePower -= ps.getAECurrentPower();
|
this.globalAvailablePower -= ps.getAECurrentPower();
|
||||||
}
|
}
|
||||||
if( !ongoingExtractOperation )
|
|
||||||
{
|
this.providers.remove( ps );
|
||||||
removeProvider( ps );
|
this.requesters.remove( ps );
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.providerToRemove.add( ps );
|
|
||||||
}
|
|
||||||
if( !ongoingInjectOperation )
|
|
||||||
{
|
|
||||||
removeRequester( ps );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.requesterToRemove.add( ps );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,31 +522,6 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRequester(IAEPowerStorage requester) {
|
|
||||||
Preconditions.checkState(!ongoingInjectOperation,
|
|
||||||
"Cannot modify energy requesters while energy is being injected.");
|
|
||||||
this.requesters.add(requester);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeRequester(IAEPowerStorage requester) {
|
|
||||||
Preconditions.checkState(!ongoingInjectOperation,
|
|
||||||
"Cannot modify energy requesters while energy is being injected.");
|
|
||||||
this.requesters.remove(requester);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addProvider(IAEPowerStorage provider) {
|
|
||||||
Preconditions.checkState(!ongoingExtractOperation,
|
|
||||||
"Cannot modify energy providers while energy is being extracted.");
|
|
||||||
this.providers.add(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeProvider(IAEPowerStorage provider) {
|
|
||||||
Preconditions.checkState(!ongoingExtractOperation,
|
|
||||||
"Cannot modify energy providers while energy is being extracted.");
|
|
||||||
this.providers.remove(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addNode( final IGridNode node, final IGridHost machine )
|
public void addNode( final IGridNode node, final IGridHost machine )
|
||||||
{
|
{
|
||||||
@@ -669,26 +553,12 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
if( current > 0 && ps.getPowerFlow() != AccessRestriction.WRITE )
|
if( current > 0 && ps.getPowerFlow() != AccessRestriction.WRITE )
|
||||||
{
|
{
|
||||||
this.globalAvailablePower += current;
|
this.globalAvailablePower += current;
|
||||||
if( !ongoingExtractOperation )
|
this.providers.add( ps );
|
||||||
{
|
|
||||||
addProvider( ps );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.providersToAdd.add( ps );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( current < max && ps.getPowerFlow() != AccessRestriction.READ )
|
if( current < max && ps.getPowerFlow() != AccessRestriction.READ )
|
||||||
{
|
{
|
||||||
if( !ongoingInjectOperation )
|
this.requesters.add( ps );
|
||||||
{
|
|
||||||
addRequester( ps );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.requesterToAdd.add( ps );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -815,4 +685,4 @@ public class EnergyGridCache implements IEnergyGrid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -494,22 +494,87 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canCraft( final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs )
|
private boolean canCraft(final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs)
|
||||||
{
|
{
|
||||||
for( IAEItemStack g : condensedInputs )
|
if( !details.isCraftable() )
|
||||||
{
|
{
|
||||||
|
// Processing patterns are relatively easy
|
||||||
|
for ( IAEItemStack input : condensedInputs )
|
||||||
|
{
|
||||||
|
final IAEItemStack ais = this.inventory.extractItems( input.copy(), Actionable.SIMULATE,
|
||||||
|
this.machineSrc );
|
||||||
|
|
||||||
if( details.isCraftable() )
|
if( ais == null || ais.getStackSize() < input.getStackSize() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( details.canSubstitute() )
|
||||||
|
{
|
||||||
|
// When substitutions are allowed, we have to keep track of which items we've reserved
|
||||||
|
IAEItemStack[] inputs = details.getInputs();
|
||||||
|
Map<IAEItemStack, Integer> consumedCount = new HashMap<>();
|
||||||
|
for ( int i = 0; i < inputs.length; i++ )
|
||||||
|
{
|
||||||
|
List<IAEItemStack> substitutes = details.getSubstituteInputs( i );
|
||||||
|
if( substitutes.isEmpty() )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean found = false;
|
||||||
|
for ( IAEItemStack substitute : substitutes )
|
||||||
|
{
|
||||||
|
for ( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( substitute, FuzzyMode.IGNORE_ALL ) )
|
||||||
|
{
|
||||||
|
int alreadyConsumed = consumedCount.getOrDefault( fuzz, 0 );
|
||||||
|
if( fuzz.getStackSize() - alreadyConsumed <= 0 )
|
||||||
|
{
|
||||||
|
continue; // Already fully consumed by a previous slot of this recipe
|
||||||
|
}
|
||||||
|
|
||||||
|
fuzz = fuzz.copy();
|
||||||
|
fuzz.setStackSize( 1 ); // We're iterating over non condensed inputs which means there's 1 of each needed
|
||||||
|
final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.SIMULATE,
|
||||||
|
this.machineSrc );
|
||||||
|
|
||||||
|
if( ais != null && ais.getStackSize() > 0 )
|
||||||
|
{
|
||||||
|
// Mark 1 of the stack as consumed
|
||||||
|
consumedCount.merge( fuzz, 1, Integer::sum );
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( found )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !found )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// When no substitutions can occur, we can simply check that all items are accounted since
|
||||||
|
// each type of item should only occur once
|
||||||
|
for ( IAEItemStack g : condensedInputs )
|
||||||
{
|
{
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
|
||||||
for( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( g, FuzzyMode.IGNORE_ALL ) )
|
for ( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( g, FuzzyMode.IGNORE_ALL ) )
|
||||||
{
|
{
|
||||||
fuzz = fuzz.copy();
|
fuzz = fuzz.copy();
|
||||||
fuzz.setStackSize( g.getStackSize() );
|
fuzz.setStackSize( g.getStackSize() );
|
||||||
final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.SIMULATE, this.machineSrc );
|
final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.SIMULATE, this.machineSrc );
|
||||||
|
|
||||||
if (ais != null && ais.getStackSize() == g.getStackSize())
|
if( ais != null && ais.getStackSize() >= g.getStackSize() )
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@@ -526,15 +591,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
final IAEItemStack ais = this.inventory.extractItems( g.copy(), Actionable.SIMULATE, this.machineSrc );
|
|
||||||
|
|
||||||
if (ais == null || ais.getStackSize() < g.getStackSize())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -689,71 +746,67 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
|
|||||||
ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
|
ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
|
||||||
for( int x = 0; x < input.length; x++ )
|
for (int x = 0; x < input.length; x++) {
|
||||||
{
|
if (input[x] != null) {
|
||||||
if( input[x] != null )
|
|
||||||
{
|
|
||||||
found = false;
|
found = false;
|
||||||
|
|
||||||
if( details.isCraftable() )
|
if (details.isCraftable()) {
|
||||||
{
|
|
||||||
final Collection<IAEItemStack> itemList;
|
final Collection<IAEItemStack> itemList;
|
||||||
|
|
||||||
if( details.canSubstitute() )
|
if (details.canSubstitute()) {
|
||||||
{
|
final List<IAEItemStack> substitutes = details.getSubstituteInputs(x);
|
||||||
itemList = this.inventory.getItemList().findFuzzy( input[x], FuzzyMode.IGNORE_ALL );
|
itemList = new ArrayList<>(substitutes.size());
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
itemList = new ArrayList<>( 1 );
|
|
||||||
|
|
||||||
final IAEItemStack item = this.inventory.getItemList().findPrecise( input[x] );
|
for (IAEItemStack stack : substitutes) {
|
||||||
|
itemList.addAll(this.inventory.getItemList().findFuzzy(stack,
|
||||||
|
FuzzyMode.IGNORE_ALL));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
itemList = new ArrayList<>(1);
|
||||||
|
|
||||||
if( item != null )
|
final IAEItemStack item = this.inventory.getItemList()
|
||||||
{
|
.findPrecise(input[x]);
|
||||||
itemList.add( item );
|
|
||||||
|
if (item != null) {
|
||||||
|
itemList.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for( IAEItemStack fuzz : itemList )
|
for (IAEItemStack fuzz : itemList) {
|
||||||
{
|
|
||||||
fuzz = fuzz.copy();
|
fuzz = fuzz.copy();
|
||||||
fuzz.setStackSize( input[x].getStackSize() );
|
fuzz.setStackSize(input[x].getStackSize());
|
||||||
|
|
||||||
if( details.isValidItemForSlot( x, fuzz.createItemStack(), this.getWorld() ) )
|
if (details.isValidItemForSlot(x, fuzz.createItemStack(),
|
||||||
{
|
this.getWorld())) {
|
||||||
final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.MODULATE, this.machineSrc );
|
final IAEItemStack ais = this.inventory.extractItems(fuzz,
|
||||||
final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack();
|
Actionable.MODULATE, this.machineSrc);
|
||||||
|
final ItemStack is = ais == null ? ItemStack.EMPTY
|
||||||
|
: ais.createItemStack();
|
||||||
|
|
||||||
if( !is.isEmpty() )
|
if (!is.isEmpty()) {
|
||||||
{
|
this.postChange(AEItemStack.fromItemStack(is), this.machineSrc);
|
||||||
this.postChange( AEItemStack.fromItemStack( is ), this.machineSrc );
|
ic.setInventorySlotContents(x, is);
|
||||||
ic.setInventorySlotContents( x, is );
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
final IAEItemStack ais = this.inventory.extractItems(input[x].copy(),
|
||||||
{
|
Actionable.MODULATE, this.machineSrc);
|
||||||
final IAEItemStack ais = this.inventory.extractItems( input[x].copy(), Actionable.MODULATE, this.machineSrc );
|
|
||||||
final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack();
|
final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack();
|
||||||
|
|
||||||
if( !is.isEmpty() )
|
if (!is.isEmpty()) {
|
||||||
{
|
this.postChange(input[x], this.machineSrc);
|
||||||
this.postChange( input[x], this.machineSrc );
|
ic.setInventorySlotContents(x, is);
|
||||||
ic.setInventorySlotContents( x, is );
|
if (is.getCount() == input[x].getStackSize()) {
|
||||||
if( is.getCount() == input[x].getStackSize() )
|
|
||||||
{
|
|
||||||
found = true;
|
found = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !found )
|
if (!found) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class MEMonitorPassThrough<T extends IAEStack<T>> extends MEPassThrough<T
|
|||||||
final IItemList<T> after = this.getInternal() == null ? this.getWrappedChannel().createList() : this.getInternal()
|
final IItemList<T> after = this.getInternal() == null ? this.getWrappedChannel().createList() : this.getInternal()
|
||||||
.getAvailableItems( new ItemListIgnoreCrafting( this.getWrappedChannel().createList() ) );
|
.getAvailableItems( new ItemListIgnoreCrafting( this.getWrappedChannel().createList() ) );
|
||||||
|
|
||||||
if( this.monitor != null )
|
if( this.monitor != null && this.listeners.size() > 0 )
|
||||||
{
|
{
|
||||||
this.monitor.addListener( this, this.monitor );
|
this.monitor.addListener( this, this.monitor );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -434,16 +434,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 )
|
||||||
|
|||||||
@@ -206,10 +206,17 @@ 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 )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -170,8 +170,7 @@ public class PartConversionMonitor extends AbstractPartMonitor
|
|||||||
this.insertItem( player, hand, false );
|
this.insertItem( player, hand, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return super.onPartActivate( player, hand, pos );
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1246,18 +1246,20 @@ public class Platform
|
|||||||
if( itemToAdd < input.getStackSize() )
|
if( itemToAdd < input.getStackSize() )
|
||||||
{
|
{
|
||||||
final long original = input.getStackSize();
|
final long original = input.getStackSize();
|
||||||
|
final T leftover = input.copy();
|
||||||
final T split = input.copy();
|
final T split = input.copy();
|
||||||
split.decStackSize( itemToAdd );
|
|
||||||
input.setStackSize( itemToAdd );
|
leftover.decStackSize(itemToAdd);
|
||||||
split.add( cell.injectItems( input, Actionable.MODULATE, src ) );
|
split.setStackSize(itemToAdd);
|
||||||
|
leftover.add(cell.injectItems(split, Actionable.MODULATE, src));
|
||||||
|
|
||||||
src.player().ifPresent( player ->
|
src.player().ifPresent( player ->
|
||||||
{
|
{
|
||||||
final long diff = original - split.getStackSize();
|
final long diff = original - leftover.getStackSize();
|
||||||
Stats.ItemsInserted.addToPlayer( player, (int) diff );
|
Stats.ItemsInserted.addToPlayer( player, (int) diff );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
return split;
|
return leftover;
|
||||||
}
|
}
|
||||||
|
|
||||||
final T ret = cell.injectItems( input, Actionable.MODULATE, src );
|
final T ret = cell.injectItems( input, Actionable.MODULATE, src );
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ class FuzzyItemVariantList extends ItemVariantList {
|
|||||||
*/
|
*/
|
||||||
static ItemDamageBound makeLowerBound(final ItemStack stack, final FuzzyMode fuzzy)
|
static ItemDamageBound makeLowerBound(final ItemStack stack, final FuzzyMode fuzzy)
|
||||||
{
|
{
|
||||||
Preconditions.checkState( stack.getItem().isDamageable() || (Platform.isModLoaded( "gregtech" ) && stack.getItem() instanceof MetaTool), "Item#isDamageable() has to be true" );
|
Preconditions.checkState( stack.getItem().isDamageable() , "Item#isDamageable() has to be true" );
|
||||||
|
|
||||||
int damage;
|
int damage;
|
||||||
if( fuzzy == FuzzyMode.IGNORE_ALL )
|
if( fuzzy == FuzzyMode.IGNORE_ALL )
|
||||||
@@ -176,7 +176,7 @@ class FuzzyItemVariantList extends ItemVariantList {
|
|||||||
* lower number than the lower bound. It also is exclusive.
|
* lower number than the lower bound. It also is exclusive.
|
||||||
*/
|
*/
|
||||||
static ItemDamageBound makeUpperBound(final ItemStack stack, final FuzzyMode fuzzy) {
|
static ItemDamageBound makeUpperBound(final ItemStack stack, final FuzzyMode fuzzy) {
|
||||||
Preconditions.checkState(stack.getItem().isDamageable() || (Platform.isModLoaded( "gregtech" ) && stack.getItem() instanceof MetaTool), "Item#isDamageable() has to be true");
|
Preconditions.checkState(stack.getItem().isDamageable() , "Item#isDamageable() has to be true");
|
||||||
|
|
||||||
int damage;
|
int damage;
|
||||||
if (fuzzy == FuzzyMode.IGNORE_ALL) {
|
if (fuzzy == FuzzyMode.IGNORE_ALL) {
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ public final class ItemList implements IItemList<IAEItemStack> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ItemVariantList makeRecordMap(Item item) {
|
private ItemVariantList makeRecordMap(Item item) {
|
||||||
if (item.isDamageable() || (Platform.isModLoaded( "gregtech" ) && item instanceof MetaTool) ) {
|
if (item.isDamageable() ) {
|
||||||
return new FuzzyItemVariantList();
|
return new FuzzyItemVariantList();
|
||||||
} else {
|
} else {
|
||||||
return new NormalItemVariantList();
|
return new NormalItemVariantList();
|
||||||
|
|||||||
+12
-24
@@ -18,32 +18,20 @@
|
|||||||
"type": "appliedenergistics2:part",
|
"type": "appliedenergistics2:part",
|
||||||
"part": "material.card_pattern_expansion"
|
"part": "material.card_pattern_expansion"
|
||||||
},
|
},
|
||||||
"type": "appliedenergistics2:part_shaped",
|
"type": "appliedenergistics2:part_shapeless",
|
||||||
"pattern": [
|
|
||||||
"ci"
|
|
||||||
],
|
|
||||||
"ingredients": [
|
"ingredients": [
|
||||||
{
|
{
|
||||||
"type": "appliedenergistics2:part",
|
"type": "appliedenergistics2:part",
|
||||||
"part": "material.advanced_card"
|
"part": "material.advanced_card"
|
||||||
},
|
},
|
||||||
{
|
[
|
||||||
"key": "#"
|
{
|
||||||
}
|
"item": "appliedenergistics2:interface"
|
||||||
],
|
},
|
||||||
"key": {
|
{
|
||||||
"i": [
|
"type": "appliedenergistics2:part",
|
||||||
{
|
"part": "part.interface"
|
||||||
"item": "appliedenergistics2:interface"
|
}
|
||||||
},
|
]
|
||||||
{
|
]
|
||||||
"type": "appliedenergistics2:part",
|
|
||||||
"part": "part.interface"
|
|
||||||
}],
|
|
||||||
"c": {
|
|
||||||
"type": "appliedenergistics2:part",
|
|
||||||
"part": "material.advanced_card"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user