From 99fd5a9d53c3ee8806f8b68192d420dcab843138 Mon Sep 17 00:00:00 2001 From: yueh Date: Sun, 21 Oct 2018 11:17:27 +0200 Subject: [PATCH] Fixes #3790: Correctly handle fluids with NBT data. (#3791) --- .../java/appeng/fluids/util/AEFluidStack.java | 171 +++++++++--------- 1 file changed, 81 insertions(+), 90 deletions(-) diff --git a/src/main/java/appeng/fluids/util/AEFluidStack.java b/src/main/java/appeng/fluids/util/AEFluidStack.java index 5145b4003..d04652bcb 100644 --- a/src/main/java/appeng/fluids/util/AEFluidStack.java +++ b/src/main/java/appeng/fluids/util/AEFluidStack.java @@ -49,37 +49,41 @@ import appeng.util.item.AEStack; public final class AEFluidStack extends AEStack implements IAEFluidStack, Comparable { - private final int myHash; private final Fluid fluid; private NBTTagCompound tagCompound; - private AEFluidStack( final AEFluidStack is ) + private AEFluidStack( final AEFluidStack fluidStack ) { - - this.fluid = is.fluid; - this.setStackSize( is.getStackSize() ); + this.fluid = fluidStack.fluid; + this.setStackSize( fluidStack.getStackSize() ); // priority = is.priority; - this.setCraftable( is.isCraftable() ); - this.setCountRequestable( is.getCountRequestable() ); + this.setCraftable( fluidStack.isCraftable() ); + 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 ) { throw new IllegalArgumentException( "Fluid is null." ); } - this.setStackSize( is.amount ); + this.setStackSize( fluidStack.amount ); this.setCraftable( false ); 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 ) @@ -92,9 +96,9 @@ public final class AEFluidStack extends AEStack implements IAEFlu 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 ) { @@ -102,15 +106,21 @@ public final class AEFluidStack extends AEStack implements IAEFlu } final AEFluidStack fluid = AEFluidStack.fromFluidStack( fluidStack ); - fluid.setStackSize( i.getLong( "Cnt" ) ); - fluid.setCountRequestable( i.getLong( "Req" ) ); - fluid.setCraftable( i.getBoolean( "Craft" ) ); + fluid.setStackSize( data.getLong( "Cnt" ) ); + fluid.setCountRequestable( data.getLong( "Req" ) ); + fluid.setCraftable( data.getBoolean( "Craft" ) ); + + if( fluid.hasTagCompound() ) + { + fluid.tagCompound = fluid.tagCompound.copy(); + } + 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 countReqType = (byte) ( ( mask & 0x30 ) >> 4 ); final boolean isCraftable = ( mask & 0x40 ) > 0; @@ -119,26 +129,26 @@ public final class AEFluidStack extends AEStack implements IAEFlu // don't send this... final NBTTagCompound d = new NBTTagCompound(); - final byte len2 = data.readByte(); + final byte len2 = buffer.readByte(); 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.setByte( "Count", (byte) 0 ); if( hasTagCompound ) { - final int len = data.readInt(); + final int len = buffer.readInt(); final byte[] bd = new byte[len]; - data.readBytes( bd ); + buffer.readBytes( 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 countRequestable = getPacketValue( countReqType, data ); + final long stackSize = getPacketValue( stackType, buffer ); + final long countRequestable = getPacketValue( countReqType, buffer ); final FluidStack fluidStack = FluidStack.loadFluidStackFromNBT( d ); @@ -168,51 +178,21 @@ public final class AEFluidStack extends AEStack implements IAEFlu } @Override - public void writeToNBT( final NBTTagCompound i ) + public void writeToNBT( final NBTTagCompound data ) { - /* - * Mojang Fucked this over ; GC Optimization - Ugly Yes, but it saves a lot in the memory department. - */ + data.setString( "FluidName", this.fluid.getName() ); + data.setByte( "Count", (byte) 0 ); + data.setLong( "Cnt", this.getStackSize() ); + data.setLong( "Req", this.getCountRequestable() ); + data.setBoolean( "Craft", this.isCraftable() ); - /* - * 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 ) + if( this.hasTagCompound() ) { - i.setTag( "tag", this.tagCompound ); + data.setTag( "Tag", this.tagCompound ); } else { - i.removeTag( "tag" ); + data.removeTag( "Tag" ); } } @@ -255,29 +235,43 @@ public final class AEFluidStack extends AEStack implements IAEFlu } @Override - public int compareTo( final AEFluidStack b ) + public int compareTo( final AEFluidStack other ) { - final int diff = this.hashCode() - b.hashCode(); - return diff > 0 ? 1 : ( diff < 0 ? -1 : 0 ); + if( this.fluid != other.fluid ) + { + 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 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 - 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 ); } - 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 false; @@ -286,7 +280,7 @@ public final class AEFluidStack extends AEStack implements IAEFlu @Override public String toString() { - return this.getFluidStack().toString(); + return this.getStackSize() + "x" + this.getFluidStack().getFluid().getName() + " " + this.tagCompound; } @Override @@ -298,11 +292,8 @@ public final class AEFluidStack extends AEStack implements IAEFlu @Override public FluidStack getFluidStack() { - final FluidStack is = new FluidStack( this.fluid, (int) Math.min( Integer.MAX_VALUE, this.getStackSize() ) ); - if( this.tagCompound != null ) - { - is.tag = this.tagCompound.copy(); - } + final int amount = (int) Math.min( Integer.MAX_VALUE, this.getStackSize() ); + final FluidStack is = new FluidStack( this.fluid, amount, this.tagCompound ); return is; } @@ -327,24 +318,24 @@ public final class AEFluidStack extends AEStack implements IAEFlu } @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 .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( i, this.getCountRequestable() ); + this.putPacketValue( buffer, this.getStackSize() ); + 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" ); - i.writeByte( (byte) name.length ); - i.writeBytes( name ); + buffer.writeByte( (byte) name.length ); + buffer.writeBytes( name ); if( this.hasTagCompound() ) { final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); @@ -355,8 +346,8 @@ public final class AEFluidStack extends AEStack implements IAEFlu final byte[] tagBytes = bytes.toByteArray(); final int size = tagBytes.length; - i.writeInt( size ); - i.writeBytes( tagBytes ); + buffer.writeInt( size ); + buffer.writeBytes( tagBytes ); } } }