Fixes #3790: Correctly handle fluids with NBT data. (#3791)

This commit is contained in:
yueh
2018-10-21 11:17:27 +02:00
committed by GitHub
parent 416c7d2683
commit 99fd5a9d53
@@ -49,37 +49,41 @@ import appeng.util.item.AEStack;
public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFluidStack, Comparable<AEFluidStack> public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFluidStack, Comparable<AEFluidStack>
{ {
private final int myHash;
private final Fluid fluid; private final Fluid fluid;
private NBTTagCompound tagCompound; private NBTTagCompound tagCompound;
private AEFluidStack( final AEFluidStack is ) private AEFluidStack( final AEFluidStack fluidStack )
{ {
this.fluid = fluidStack.fluid;
this.fluid = is.fluid; this.setStackSize( fluidStack.getStackSize() );
this.setStackSize( is.getStackSize() );
// priority = is.priority; // priority = is.priority;
this.setCraftable( is.isCraftable() ); this.setCraftable( fluidStack.isCraftable() );
this.setCountRequestable( is.getCountRequestable() ); this.setCountRequestable( fluidStack.getCountRequestable() );
this.myHash = is.myHash; if( fluidStack.hasTagCompound() )
{
this.tagCompound = fluidStack.tagCompound.copy();
}
} }
private AEFluidStack( @Nonnull final FluidStack is ) private AEFluidStack( @Nonnull final FluidStack fluidStack )
{ {
this.fluid = is.getFluid(); this.fluid = fluidStack.getFluid();
if( this.fluid == null ) if( this.fluid == null )
{ {
throw new IllegalArgumentException( "Fluid is null." ); throw new IllegalArgumentException( "Fluid is null." );
} }
this.setStackSize( is.amount ); this.setStackSize( fluidStack.amount );
this.setCraftable( false ); this.setCraftable( false );
this.setCountRequestable( 0 ); this.setCountRequestable( 0 );
this.myHash = this.fluid.hashCode() ^ ( this.tagCompound == null ? 0 : System.identityHashCode( this.tagCompound ) ); if( fluidStack.tag != null )
{
this.tagCompound = fluidStack.tag.copy();
}
} }
public static AEFluidStack fromFluidStack( final FluidStack input ) public static AEFluidStack fromFluidStack( final FluidStack input )
@@ -92,9 +96,9 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
return new AEFluidStack( input ); return new AEFluidStack( input );
} }
public static IAEFluidStack fromNBT( final NBTTagCompound i ) public static IAEFluidStack fromNBT( final NBTTagCompound data )
{ {
final FluidStack fluidStack = FluidStack.loadFluidStackFromNBT( i ); final FluidStack fluidStack = FluidStack.loadFluidStackFromNBT( data );
if( fluidStack == null ) if( fluidStack == null )
{ {
@@ -102,15 +106,21 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
} }
final AEFluidStack fluid = AEFluidStack.fromFluidStack( fluidStack ); final AEFluidStack fluid = AEFluidStack.fromFluidStack( fluidStack );
fluid.setStackSize( i.getLong( "Cnt" ) ); fluid.setStackSize( data.getLong( "Cnt" ) );
fluid.setCountRequestable( i.getLong( "Req" ) ); fluid.setCountRequestable( data.getLong( "Req" ) );
fluid.setCraftable( i.getBoolean( "Craft" ) ); fluid.setCraftable( data.getBoolean( "Craft" ) );
if( fluid.hasTagCompound() )
{
fluid.tagCompound = fluid.tagCompound.copy();
}
return fluid; return fluid;
} }
public static IAEFluidStack fromPacket( final ByteBuf data ) throws IOException public static IAEFluidStack fromPacket( final ByteBuf buffer ) throws IOException
{ {
final byte mask = data.readByte(); final byte mask = buffer.readByte();
final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 ); final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 );
final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 ); final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 );
final boolean isCraftable = ( mask & 0x40 ) > 0; final boolean isCraftable = ( mask & 0x40 ) > 0;
@@ -119,26 +129,26 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
// don't send this... // don't send this...
final NBTTagCompound d = new NBTTagCompound(); final NBTTagCompound d = new NBTTagCompound();
final byte len2 = data.readByte(); final byte len2 = buffer.readByte();
final byte[] name = new byte[len2]; final byte[] name = new byte[len2];
data.readBytes( name, 0, len2 ); buffer.readBytes( name, 0, len2 );
d.setString( "FluidName", new String( name, "UTF-8" ) ); d.setString( "FluidName", new String( name, "UTF-8" ) );
d.setByte( "Count", (byte) 0 ); d.setByte( "Count", (byte) 0 );
if( hasTagCompound ) if( hasTagCompound )
{ {
final int len = data.readInt(); final int len = buffer.readInt();
final byte[] bd = new byte[len]; final byte[] bd = new byte[len];
data.readBytes( bd ); buffer.readBytes( bd );
final DataInputStream di = new DataInputStream( new ByteArrayInputStream( bd ) ); final DataInputStream di = new DataInputStream( new ByteArrayInputStream( bd ) );
d.setTag( "tag", CompressedStreamTools.read( di ) ); d.setTag( "Tag", CompressedStreamTools.read( di ) );
} }
final long stackSize = getPacketValue( stackType, data ); final long stackSize = getPacketValue( stackType, buffer );
final long countRequestable = getPacketValue( countReqType, data ); final long countRequestable = getPacketValue( countReqType, buffer );
final FluidStack fluidStack = FluidStack.loadFluidStackFromNBT( d ); final FluidStack fluidStack = FluidStack.loadFluidStackFromNBT( d );
@@ -168,51 +178,21 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
} }
@Override @Override
public void writeToNBT( final NBTTagCompound i ) public void writeToNBT( final NBTTagCompound data )
{ {
/* data.setString( "FluidName", this.fluid.getName() );
* Mojang Fucked this over ; GC Optimization - Ugly Yes, but it saves a lot in the memory department. data.setByte( "Count", (byte) 0 );
*/ data.setLong( "Cnt", this.getStackSize() );
data.setLong( "Req", this.getCountRequestable() );
data.setBoolean( "Craft", this.isCraftable() );
/* if( this.hasTagCompound() )
* NBTBase FluidName = i.getTag( "FluidName" ); NBTBase Count = i.getTag( "Count" ); NBTBase Cnt = i.getTag(
* "Cnt" ); NBTBase Req = i.getTag( "Req" ); NBTBase Craft = i.getTag( "Craft" );
*/
/*
* if ( FluidName != null && FluidName instanceof NBTTagString ) ((NBTTagString) FluidName).data = (String)
* this.fluid.getName(); else
*/
i.setString( "FluidName", this.fluid.getName() );
/*
* if ( Count != null && Count instanceof NBTTagByte ) ((NBTTagByte) Count).data = (byte) 0; else
*/
i.setByte( "Count", (byte) 0 );
/*
* if ( Cnt != null && Cnt instanceof NBTTagLong ) ((NBTTagLong) Cnt).data = this.stackSize; else
*/
i.setLong( "Cnt", this.getStackSize() );
/*
* if ( Req != null && Req instanceof NBTTagLong ) ((NBTTagLong) Req).data = this.stackSize; else
*/
i.setLong( "Req", this.getCountRequestable() );
/*
* if ( Craft != null && Craft instanceof NBTTagByte ) ((NBTTagByte) Craft).data = (byte) (this.isCraftable() ?
* 1 : 0); else
*/
i.setBoolean( "Craft", this.isCraftable() );
if( this.tagCompound != null )
{ {
i.setTag( "tag", this.tagCompound ); data.setTag( "Tag", this.tagCompound );
} }
else else
{ {
i.removeTag( "tag" ); data.removeTag( "Tag" );
} }
} }
@@ -255,29 +235,43 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
} }
@Override @Override
public int compareTo( final AEFluidStack b ) public int compareTo( final AEFluidStack other )
{ {
final int diff = this.hashCode() - b.hashCode(); if( this.fluid != other.fluid )
return diff > 0 ? 1 : ( diff < 0 ? -1 : 0 ); {
return this.fluid.getName().compareTo( other.fluid.getName() );
}
if( Platform.itemComparisons().isNbtTagEqual( this.tagCompound, other.tagCompound ) )
{
return 0;
}
return this.tagCompound.hashCode() - other.tagCompound.hashCode();
} }
@Override @Override
public int hashCode() public int hashCode()
{ {
return this.myHash; final int prime = 31;
int result = 1;
result = prime * result + ( ( this.fluid == null ) ? 0 : this.fluid.hashCode() );
result = prime * result + ( ( this.tagCompound == null ) ? 0 : this.tagCompound.hashCode() );
return result;
} }
@Override @Override
public boolean equals( final Object ia ) public boolean equals( final Object other )
{ {
if( ia instanceof AEFluidStack ) if( other instanceof AEFluidStack )
{ {
final AEFluidStack is = (AEFluidStack) ia; final AEFluidStack is = (AEFluidStack) other;
return is.fluid == this.fluid && Platform.itemComparisons().isNbtTagEqual( this.tagCompound, is.tagCompound ); return is.fluid == this.fluid && Platform.itemComparisons().isNbtTagEqual( this.tagCompound, is.tagCompound );
} }
else if( ia instanceof FluidStack ) else if( other instanceof FluidStack )
{ {
final FluidStack is = (FluidStack) ia; final FluidStack is = (FluidStack) other;
return is.getFluid() == this.fluid && Platform.itemComparisons().isNbtTagEqual( this.tagCompound, is.tag ); return is.getFluid() == this.fluid && Platform.itemComparisons().isNbtTagEqual( this.tagCompound, is.tag );
} }
return false; return false;
@@ -286,7 +280,7 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
@Override @Override
public String toString() public String toString()
{ {
return this.getFluidStack().toString(); return this.getStackSize() + "x" + this.getFluidStack().getFluid().getName() + " " + this.tagCompound;
} }
@Override @Override
@@ -298,11 +292,8 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
@Override @Override
public FluidStack getFluidStack() public FluidStack getFluidStack()
{ {
final FluidStack is = new FluidStack( this.fluid, (int) Math.min( Integer.MAX_VALUE, this.getStackSize() ) ); final int amount = (int) Math.min( Integer.MAX_VALUE, this.getStackSize() );
if( this.tagCompound != null ) final FluidStack is = new FluidStack( this.fluid, amount, this.tagCompound );
{
is.tag = this.tagCompound.copy();
}
return is; return is;
} }
@@ -327,24 +318,24 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
} }
@Override @Override
public void writeToPacket( final ByteBuf i ) throws IOException public void writeToPacket( final ByteBuf buffer ) throws IOException
{ {
final byte mask = (byte) ( ( this.getType( this.getStackSize() ) << 2 ) | ( this final byte mask = (byte) ( ( this.getType( this.getStackSize() ) << 2 ) | ( this
.getType( this.getCountRequestable() ) << 4 ) | ( (byte) ( this.isCraftable() ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 ); .getType( this.getCountRequestable() ) << 4 ) | ( (byte) ( this.isCraftable() ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 );
i.writeByte( mask ); buffer.writeByte( mask );
this.writeToStream( i ); this.writeToStream( buffer );
this.putPacketValue( i, this.getStackSize() ); this.putPacketValue( buffer, this.getStackSize() );
this.putPacketValue( i, this.getCountRequestable() ); this.putPacketValue( buffer, this.getCountRequestable() );
} }
private void writeToStream( final ByteBuf i ) throws IOException private void writeToStream( final ByteBuf buffer ) throws IOException
{ {
final byte[] name = this.fluid.getName().getBytes( "UTF-8" ); final byte[] name = this.fluid.getName().getBytes( "UTF-8" );
i.writeByte( (byte) name.length ); buffer.writeByte( (byte) name.length );
i.writeBytes( name ); buffer.writeBytes( name );
if( this.hasTagCompound() ) if( this.hasTagCompound() )
{ {
final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
@@ -355,8 +346,8 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
final byte[] tagBytes = bytes.toByteArray(); final byte[] tagBytes = bytes.toByteArray();
final int size = tagBytes.length; final int size = tagBytes.length;
i.writeInt( size ); buffer.writeInt( size );
i.writeBytes( tagBytes ); buffer.writeBytes( tagBytes );
} }
} }
} }