Fluid cleanup and performance improvements (#3581)

Use custom gui widget with custom synchronization for rendering fake fluid slots.
This commit is contained in:
fscan
2018-07-04 19:12:12 +02:00
committed by GitHub
parent 979531afb7
commit 5d26b98ab8
40 changed files with 1499 additions and 777 deletions
@@ -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();
}