Fixes #2526: Using 5-bit for 0-32 is not sufficient. Rewrote packet for syncing cables to clients to use an easier to deal with format while still saving space in the normal case (2 sides connected to a cable).

This commit is contained in:
Sebastian Hartte 2016-10-29 18:06:10 +02:00
parent 1832be3118
commit 6b90c70755

View file

@ -286,23 +286,26 @@ public class PartCable extends AEBasePart implements IPartCable
@Override @Override
public void writeToStream( final ByteBuf data ) throws IOException public void writeToStream( final ByteBuf data ) throws IOException
{ {
int cs = 0; int flags = 0;
int sideOut = 0; boolean[] writeSide = new boolean[EnumFacing.values().length];
int[] channelsPerSide = new int[EnumFacing.values().length];
final IGridNode n = this.getGridNode(); IGridNode n = this.getGridNode();
if( n != null ) if( n != null )
{ {
for( final AEPartLocation thisSide : AEPartLocation.SIDE_LOCATIONS ) for( EnumFacing thisSide : EnumFacing.values() )
{ {
final IPart part = this.getHost().getPart( thisSide ); final IPart part = this.getHost().getPart( thisSide );
if( part != null ) if( part != null )
{ {
if( part.getGridNode() != null ) if( part.getGridNode() != null )
{ {
writeSide[thisSide.ordinal()] = true;
final IReadOnlyCollection<IGridConnection> set = part.getGridNode().getConnections(); final IReadOnlyCollection<IGridConnection> set = part.getGridNode().getConnections();
for( final IGridConnection gc : set ) for( final IGridConnection gc : set )
{ {
sideOut |= ( gc.getUsedChannels() ) << ( 5 * thisSide.ordinal() ); channelsPerSide[thisSide.ordinal()] = gc.getUsedChannels();
} }
} }
} }
@ -313,8 +316,9 @@ public class PartCable extends AEBasePart implements IPartCable
final AEPartLocation side = gc.getDirection( n ); final AEPartLocation side = gc.getDirection( n );
if( side != AEPartLocation.INTERNAL ) if( side != AEPartLocation.INTERNAL )
{ {
sideOut |= gc.getUsedChannels() << ( 5 * side.ordinal() ); writeSide[side.ordinal()] = true;
cs |= ( 1 << side.ordinal() ); channelsPerSide[side.ordinal()] = gc.getUsedChannels();
flags |= ( 1 << side.ordinal() );
} }
} }
} }
@ -323,7 +327,7 @@ public class PartCable extends AEBasePart implements IPartCable
{ {
if( this.getProxy().getEnergy().isNetworkPowered() ) if( this.getProxy().getEnergy().isNetworkPowered() )
{ {
cs |= ( 1 << AEPartLocation.INTERNAL.ordinal() ); flags |= ( 1 << AEPartLocation.INTERNAL.ordinal() );
} }
} }
catch( final GridAccessException e ) catch( final GridAccessException e )
@ -331,16 +335,21 @@ public class PartCable extends AEBasePart implements IPartCable
// aww... // aww...
} }
data.writeByte( (byte) cs ); data.writeByte( (byte) flags );
data.writeInt( sideOut ); // Only write the used channels for sides where we have a part or another cable
for( int i = 0; i < writeSide.length; i++ )
{
if( writeSide[i] )
{
data.writeByte( channelsPerSide[i] );
}
}
} }
@Override @Override
public boolean readFromStream( final ByteBuf data ) throws IOException public boolean readFromStream( final ByteBuf data ) throws IOException
{ {
final int cs = data.readByte(); int cs = data.readByte();
final int sideOut = data.readInt();
final EnumSet<AEPartLocation> myC = this.getConnections().clone(); final EnumSet<AEPartLocation> myC = this.getConnections().clone();
final boolean wasPowered = this.powered; final boolean wasPowered = this.powered;
this.powered = false; this.powered = false;
@ -348,16 +357,6 @@ public class PartCable extends AEBasePart implements IPartCable
for( final AEPartLocation d : AEPartLocation.values() ) for( final AEPartLocation d : AEPartLocation.values() )
{ {
if( d != AEPartLocation.INTERNAL )
{
final int ch = ( sideOut >> ( d.ordinal() * 5 ) ) & 0x1F;
if( ch != this.getChannelsOnSide( d.ordinal() ) )
{
channelsChanged = true;
this.setChannelsOnSide( d.ordinal(), ch );
}
}
if( d == AEPartLocation.INTERNAL ) if( d == AEPartLocation.INTERNAL )
{ {
final int id = 1 << d.ordinal(); final int id = 1 << d.ordinal();
@ -368,8 +367,8 @@ public class PartCable extends AEBasePart implements IPartCable
} }
else else
{ {
final int id = 1 << d.ordinal(); boolean conOnSide = ( cs & ( 1 << d.ordinal() ) ) != 0;
if( id == ( cs & id ) ) if( conOnSide )
{ {
this.getConnections().add( d ); this.getConnections().add( d );
} }
@ -377,6 +376,22 @@ public class PartCable extends AEBasePart implements IPartCable
{ {
this.getConnections().remove( d ); this.getConnections().remove( d );
} }
int ch = 0;
// Only read channels if there's a part on this side or a cable connection
// This works only because cables are always read *last* from the packet update for
// a cable bus
if( conOnSide || getHost().getPart( d ) != null )
{
ch = ( (int) data.readByte() ) & 0xFF;
}
if( ch != this.getChannelsOnSide(d.ordinal()) )
{
channelsChanged = true;
this.setChannelsOnSide(d.ordinal(), ch);
}
} }
} }