Fluid cleanup and performance improvements (#3581)
Use custom gui widget with custom synchronization for rendering fake fluid slots.
This commit is contained in:
@@ -0,0 +1,377 @@
|
||||
|
||||
package appeng.fluids.util;
|
||||
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.IFluidTankProperties;
|
||||
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.core.AELog;
|
||||
import appeng.util.Platform;
|
||||
|
||||
|
||||
public class AEFluidInventory implements IAEFluidTank
|
||||
{
|
||||
private final IAEFluidStack[] fluids;
|
||||
private final IAEFluidInventory handler;
|
||||
private final long capacity;
|
||||
private IFluidTankProperties[] props = null;
|
||||
|
||||
public AEFluidInventory( final IAEFluidInventory handler, final int slots, final long capcity )
|
||||
{
|
||||
this.fluids = new IAEFluidStack[slots];
|
||||
this.handler = handler;
|
||||
this.capacity = capcity;
|
||||
}
|
||||
|
||||
public AEFluidInventory( final IAEFluidInventory handler, final int slots )
|
||||
{
|
||||
this( handler, slots, Long.MAX_VALUE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFluidInSlot( final int slot, final IAEFluidStack fluid )
|
||||
{
|
||||
if( slot >= 0 && slot < this.getSlots() )
|
||||
{
|
||||
if( Objects.equals( this.fluids[slot], fluid ) )
|
||||
{
|
||||
if( fluid != null && fluid.getStackSize() != this.fluids[slot].getStackSize() )
|
||||
{
|
||||
this.fluids[slot].setStackSize( Math.min( fluid.getStackSize(), this.capacity ) );
|
||||
this.onContentChanged( slot );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fluid == null )
|
||||
{
|
||||
this.fluids[slot] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.fluids[slot] = fluid.copy();
|
||||
this.fluids[slot].setStackSize( Math.min( fluid.getStackSize(), this.capacity ) );
|
||||
}
|
||||
|
||||
this.onContentChanged( slot );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onContentChanged( final int slot )
|
||||
{
|
||||
if( this.handler != null && Platform.isServer() )
|
||||
{
|
||||
this.handler.onFluidInventoryChanged( this, slot );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEFluidStack getFluidInSlot( final int slot )
|
||||
{
|
||||
if( slot >= 0 && slot < this.getSlots() )
|
||||
{
|
||||
return this.fluids[slot];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlots()
|
||||
{
|
||||
return fluids.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFluidTankProperties[] getTankProperties()
|
||||
{
|
||||
if( this.props == null )
|
||||
{
|
||||
this.props = new IFluidTankProperties[this.getSlots()];
|
||||
for( int i = 0; i < this.getSlots(); ++i )
|
||||
{
|
||||
this.props[i] = new FluidTankPropertiesWrapper( i );
|
||||
}
|
||||
|
||||
}
|
||||
return this.props;
|
||||
}
|
||||
|
||||
public int fill( final int slot, final FluidStack resource, final boolean doFill )
|
||||
{
|
||||
if( resource == null || resource.amount <= 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
final IAEFluidStack fluid = this.fluids[slot];
|
||||
|
||||
if( !doFill )
|
||||
{
|
||||
if( fluid == null )
|
||||
{
|
||||
return resource.amount;
|
||||
}
|
||||
|
||||
if( !fluid.equals( resource ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) Math.min( Math.min( this.capacity - fluid.getStackSize(), resource.amount ), Integer.MAX_VALUE );
|
||||
}
|
||||
|
||||
if( fluid == null )
|
||||
{
|
||||
this.setFluidInSlot( slot, AEFluidStack.fromFluidStack( resource ) );
|
||||
return resource.amount;
|
||||
}
|
||||
|
||||
if( !fluid.equals( resource ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
long filled = this.capacity - fluid.getStackSize();
|
||||
|
||||
if( resource.amount < filled )
|
||||
{
|
||||
fluid.setStackSize( fluid.getStackSize() + resource.amount );
|
||||
filled = resource.amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
fluid.setStackSize( this.capacity );
|
||||
}
|
||||
|
||||
onContentChanged( slot );
|
||||
return (int) filled;
|
||||
}
|
||||
|
||||
public FluidStack drain( final int slot, final FluidStack resource, final boolean doDrain )
|
||||
{
|
||||
final IAEFluidStack fluid = this.fluids[slot];
|
||||
if( resource == null || fluid == null || !fluid.equals( resource ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return drain( slot, resource.amount, doDrain );
|
||||
}
|
||||
|
||||
public FluidStack drain( final int slot, final int maxDrain, boolean doDrain )
|
||||
{
|
||||
final IAEFluidStack fluid = this.fluids[slot];
|
||||
if( fluid == null || maxDrain <= 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int drained = maxDrain;
|
||||
if( fluid.getStackSize() < drained )
|
||||
{
|
||||
drained = (int) fluid.getStackSize();
|
||||
}
|
||||
|
||||
FluidStack stack = new FluidStack( fluid.getFluid(), drained );
|
||||
if( doDrain )
|
||||
{
|
||||
fluid.setStackSize( fluid.getStackSize() - drained );
|
||||
if( fluid.getStackSize() <= 0 )
|
||||
{
|
||||
this.fluids[slot] = null;
|
||||
}
|
||||
onContentChanged( slot );
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fill( final FluidStack fluid, final boolean doFill )
|
||||
{
|
||||
if( fluid == null || fluid.amount <= 0 )
|
||||
return 0;
|
||||
|
||||
final FluidStack insert = fluid.copy();
|
||||
|
||||
int totalFillAmount = 0;
|
||||
for( int slot = 0; slot < this.getSlots(); ++slot )
|
||||
{
|
||||
int fillAmount = this.fill( slot, insert, doFill );
|
||||
totalFillAmount += fillAmount;
|
||||
insert.amount -= fillAmount;
|
||||
if( insert.amount <= 0 )
|
||||
break;
|
||||
}
|
||||
return totalFillAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack drain( final FluidStack fluid, final boolean doDrain )
|
||||
{
|
||||
if( fluid == null || fluid.amount <= 0 )
|
||||
return null;
|
||||
|
||||
final FluidStack resource = fluid.copy();
|
||||
|
||||
FluidStack totalDrained = null;
|
||||
for( int slot = 0; slot < this.getSlots(); ++slot )
|
||||
{
|
||||
FluidStack drain = this.drain( slot, resource, doDrain );
|
||||
if( drain != null )
|
||||
{
|
||||
if( totalDrained == null )
|
||||
totalDrained = drain;
|
||||
else
|
||||
totalDrained.amount += drain.amount;
|
||||
|
||||
resource.amount -= drain.amount;
|
||||
if( resource.amount <= 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
return totalDrained;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack drain( final int maxDrain, final boolean doDrain )
|
||||
{
|
||||
if( maxDrain == 0 )
|
||||
return null;
|
||||
|
||||
FluidStack totalDrained = null;
|
||||
int toDrain = maxDrain;
|
||||
|
||||
for( int slot = 0; slot < this.getSlots(); ++slot )
|
||||
{
|
||||
if( totalDrained == null )
|
||||
{
|
||||
totalDrained = this.drain( slot, toDrain, doDrain );
|
||||
if( totalDrained != null )
|
||||
{
|
||||
toDrain -= totalDrained.amount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FluidStack copy = totalDrained.copy();
|
||||
copy.amount = toDrain;
|
||||
FluidStack drain = this.drain( slot, copy, doDrain );
|
||||
if( drain != null )
|
||||
{
|
||||
totalDrained.amount += drain.amount;
|
||||
toDrain -= drain.amount;
|
||||
}
|
||||
}
|
||||
|
||||
if( toDrain <= 0 )
|
||||
break;
|
||||
}
|
||||
return totalDrained;
|
||||
}
|
||||
|
||||
public void writeToNBT( final NBTTagCompound data, final String name )
|
||||
{
|
||||
final NBTTagCompound c = new NBTTagCompound();
|
||||
this.writeToNBT( c );
|
||||
data.setTag( name, c );
|
||||
}
|
||||
|
||||
private void writeToNBT( final NBTTagCompound target )
|
||||
{
|
||||
for( int x = 0; x < this.fluids.length; x++ )
|
||||
{
|
||||
try
|
||||
{
|
||||
final NBTTagCompound c = new NBTTagCompound();
|
||||
|
||||
if( this.fluids[x] != null )
|
||||
{
|
||||
this.fluids[x].writeToNBT( c );
|
||||
}
|
||||
|
||||
target.setTag( "#" + x, c );
|
||||
}
|
||||
catch( final Exception ignored )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void readFromNBT( final NBTTagCompound data, final String name )
|
||||
{
|
||||
final NBTTagCompound c = data.getCompoundTag( name );
|
||||
if( c != null )
|
||||
{
|
||||
this.readFromNBT( c );
|
||||
}
|
||||
}
|
||||
|
||||
private void readFromNBT( final NBTTagCompound target )
|
||||
{
|
||||
for( int x = 0; x < this.fluids.length; x++ )
|
||||
{
|
||||
try
|
||||
{
|
||||
final NBTTagCompound c = target.getCompoundTag( "#" + x );
|
||||
|
||||
if( c != null )
|
||||
{
|
||||
this.fluids[x] = AEFluidStack.fromNBT( c );
|
||||
}
|
||||
}
|
||||
catch( final Exception e )
|
||||
{
|
||||
AELog.debug( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class FluidTankPropertiesWrapper implements IFluidTankProperties
|
||||
{
|
||||
private final int slot;
|
||||
|
||||
public FluidTankPropertiesWrapper( final int slot )
|
||||
{
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack getContents()
|
||||
{
|
||||
return AEFluidInventory.this.fluids[slot] == null ? null : AEFluidInventory.this.fluids[slot].getFluidStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCapacity()
|
||||
{
|
||||
return (int) Math.min( AEFluidInventory.this.capacity, Integer.MAX_VALUE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFill()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDrain()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFillFluidType( FluidStack fluidStack )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDrainFluidType( FluidStack fluidStack )
|
||||
{
|
||||
return fluidStack != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,13 +34,14 @@ import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.FluidUtil;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.FuzzyMode;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.channels.IFluidStorageChannel;
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.core.Api;
|
||||
import appeng.fluids.items.FluidDummyItem;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.item.AEStack;
|
||||
|
||||
@@ -271,34 +272,13 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
||||
{
|
||||
if( ia instanceof AEFluidStack )
|
||||
{
|
||||
return ( (AEFluidStack) ia ).fluid == this.fluid && this.tagCompound == ( (AEFluidStack) ia ).tagCompound;
|
||||
final AEFluidStack is = (AEFluidStack) ia;
|
||||
return is.fluid == this.fluid && Platform.itemComparisons().isNbtTagEqual( this.tagCompound, is.tagCompound );
|
||||
}
|
||||
else if( ia instanceof FluidStack )
|
||||
{
|
||||
final FluidStack is = (FluidStack) ia;
|
||||
|
||||
if( is.getFluid() == this.fluid )
|
||||
{
|
||||
final NBTTagCompound ta = this.tagCompound;
|
||||
final NBTTagCompound tb = is.tag;
|
||||
if( ta == tb )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if( ( ta == null && tb == null ) || ( ta != null && ta.hasNoTags() && tb == null ) || ( tb != null && tb
|
||||
.hasNoTags() && ta == null ) || ( ta != null && ta.hasNoTags() && tb != null && tb.hasNoTags() ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if( ( ta == null && tb != null ) || ( ta != null && tb == null ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Platform.itemComparisons().isNbtTagEqual( ta, tb );
|
||||
}
|
||||
return is.getFluid() == this.fluid && Platform.itemComparisons().isNbtTagEqual( this.tagCompound, is.tag );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -336,8 +316,14 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
||||
@Override
|
||||
public ItemStack asItemStackRepresentation()
|
||||
{
|
||||
// TODO: fluids, how do they even work?
|
||||
return FluidUtil.getFilledBucket( this.getFluidStack() );
|
||||
ItemStack is = Api.INSTANCE.definitions().items().dummyFluidItem().maybeStack( 1 ).orElse( ItemStack.EMPTY );
|
||||
if( !is.isEmpty() )
|
||||
{
|
||||
FluidDummyItem item = (FluidDummyItem) is.getItem();
|
||||
item.setFluidStack( is, this.getFluidStack() );
|
||||
return is;
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.fluids.util;
|
||||
|
||||
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraftforge.fluids.FluidTank;
|
||||
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.util.Platform;
|
||||
|
||||
|
||||
public class AEFluidTank extends FluidTank implements IAEFluidTank
|
||||
{
|
||||
private final IAEFluidInventory host;
|
||||
|
||||
public AEFluidTank( IAEFluidInventory host, int capacity )
|
||||
{
|
||||
super( capacity );
|
||||
this.host = host;
|
||||
if (host instanceof TileEntity)
|
||||
{
|
||||
this.setTileEntity( (TileEntity) host );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onContentsChanged()
|
||||
{
|
||||
if( host != null && Platform.isServer() )
|
||||
{
|
||||
host.onFluidInventoryChanged( this, 0 );
|
||||
}
|
||||
super.onContentsChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFluidInSlot( int slot, IAEFluidStack fluid )
|
||||
{
|
||||
if( slot == 0 )
|
||||
{
|
||||
this.setFluid( fluid == null ? null : fluid.getFluidStack() );
|
||||
this.onContentsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEFluidStack getFluidInSlot( int slot )
|
||||
{
|
||||
if( slot == 0 )
|
||||
{
|
||||
return AEFluidStack.fromFluidStack( this.getFluid() );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlots()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.fluids.util;
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface IAEFluidInventory
|
||||
{
|
||||
void onFluidInventoryChanged( final IAEFluidTank inv, final int slot );
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
package appeng.fluids.util;
|
||||
|
||||
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
|
||||
|
||||
public interface IAEFluidTank extends IFluidHandler
|
||||
{
|
||||
void setFluidInSlot( final int slot, final IAEFluidStack fluid );
|
||||
|
||||
IAEFluidStack getFluidInSlot( final int slot );
|
||||
|
||||
int getSlots();
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user