2022-03-17 15:21:30 +01:00
package com.falsepattern.endlessids ;
2022-03-17 20:13:02 +01:00
import com.falsepattern.endlessids.constants.ExtendedConstants ;
2022-06-17 21:53:59 +02:00
import com.falsepattern.endlessids.mixin.helpers.IChunkMixin ;
2022-03-17 15:21:30 +01:00
import com.falsepattern.endlessids.mixin.helpers.IExtendedBlockStorageMixin ;
2022-03-17 22:24:32 +01:00
import lombok.val ;
2022-03-17 15:21:30 +01:00
import net.minecraft.init.Blocks ;
import net.minecraft.block.Block ;
import net.minecraft.nbt.NBTTagCompound ;
2022-06-17 21:53:59 +02:00
import net.minecraft.world.chunk.Chunk ;
2022-03-17 15:21:30 +01:00
import java.nio.ShortBuffer ;
import java.nio.ByteBuffer ;
2022-03-17 22:24:32 +01:00
public class Hooks {
2022-03-17 15:21:30 +01:00
public static byte [] getBlockData ( final IExtendedBlockStorageMixin ebs ) {
2022-03-17 22:24:32 +01:00
val lsb = ebs . getLSB ();
val msb = ebs . getMSB ();
final byte [] ret = new byte [ lsb . length * 3 ] ;
ByteBuffer . wrap ( ret ). asShortBuffer (). put ( lsb );
System . arraycopy ( msb , 0 , ret , lsb . length * 2 , lsb . length );
2022-03-17 15:21:30 +01:00
return ret ;
}
public static void setBlockData ( final IExtendedBlockStorageMixin ebs , final byte [] data , final int offset ) {
2022-03-17 22:24:32 +01:00
val lsb = ebs . getLSB ();
val msb = ebs . getMSB ();
val lsbBytes = lsb . length * 2 ;
ShortBuffer . wrap ( ebs . getLSB ()). put ( ByteBuffer . wrap ( data , offset , lsbBytes ). asShortBuffer ());
System . arraycopy ( data , offset + lsbBytes , msb , 0 , msb . length );
2022-03-17 15:21:30 +01:00
}
2022-03-17 22:24:32 +01:00
2022-03-17 15:21:30 +01:00
public static void writeChunkToNbt ( final NBTTagCompound nbt , final IExtendedBlockStorageMixin ebs ) {
2022-03-17 22:24:32 +01:00
val ebsLSB = ebs . getLSB ();
val ebsMSB = ebs . getMSB ();
val byte1Data = new byte [ ebsLSB . length ] ;
byte [] byte2BottomNibbleData = null ;
byte [] byte2TopNibbleData = null ;
byte [] byte3Data = null ;
for ( int i = 0 ; i < ebsLSB . length ; ++ i ) {
if ( ebsMSB [ i ] != 0 ) {
if ( byte3Data == null ) {
byte3Data = new byte [ ebsLSB . length ] ;
2022-03-17 15:21:30 +01:00
}
2022-03-17 22:24:32 +01:00
byte3Data [ i ] = ebsMSB [ i ] ;
}
val idLSB = ( ebsLSB [ i ] & 0xFFFF );
byte1Data [ i ] = ( byte )( idLSB & 0xFF );
if ( idLSB <= 0xFF ) continue ;
val nibbleIndex = i >> 1 ;
val nibbleShift = ( i & 1 ) * 4 ;
if ( byte2BottomNibbleData == null ) {
byte2BottomNibbleData = new byte [ ebsLSB . length / 2 ] ;
2022-03-17 15:21:30 +01:00
}
2022-03-17 22:24:32 +01:00
byte2BottomNibbleData [ nibbleIndex ] |= (( idLSB >>> 8 ) & 0xF ) << nibbleShift ;
if ( idLSB <= 0xFFF ) continue ;
if ( byte2TopNibbleData == null ) {
byte2TopNibbleData = new byte [ ebsLSB . length / 2 ] ;
2022-03-17 15:21:30 +01:00
}
2022-03-17 22:24:32 +01:00
byte2TopNibbleData [ nibbleIndex ] |= (( idLSB >>> 12 ) & 0xF ) << nibbleShift ;
2022-03-17 15:21:30 +01:00
}
2022-03-17 22:24:32 +01:00
nbt . setByteArray ( "Blocks" , byte1Data );
if ( byte2BottomNibbleData != null )
nbt . setByteArray ( "Add" , byte2BottomNibbleData );
if ( byte2TopNibbleData != null )
nbt . setByteArray ( "BlocksB2Hi" , byte2TopNibbleData );
if ( byte3Data != null )
nbt . setByteArray ( "BlocksB3" , byte3Data );
2022-03-17 15:21:30 +01:00
}
2022-03-17 22:24:32 +01:00
2022-03-17 15:21:30 +01:00
public static void readChunkFromNbt ( final IExtendedBlockStorageMixin ebs , final NBTTagCompound nbt ) {
2022-03-17 22:24:32 +01:00
assert nbt . hasKey ( "Blocks" );
val byte1Data = nbt . getByteArray ( "Blocks" );
val byte2BottomNibbleData = nbt . hasKey ( "Add" ) ? nbt . getByteArray ( "Add" ) : null ;
val byte2TopNibbleData = nbt . hasKey ( "BlocksB2Hi" ) ? nbt . getByteArray ( "BlocksB2Hi" ) : null ;
val byte3Data = nbt . hasKey ( "BlocksB3" ) ? nbt . getByteArray ( "BlocksB3" ) : null ;
val lsb = ebs . getLSB ();
val msb = ebs . getMSB ();
for ( int i = 0 ; i < lsb . length ; i ++ ) {
if ( byte3Data != null ) {
msb [ i ] = byte3Data [ i ] ;
2022-03-17 15:21:30 +01:00
}
2022-03-17 22:24:32 +01:00
int nibbleShift = ( i & 1 ) * 4 ;
int id = byte1Data [ i ] & 0xFF ;
if ( byte2BottomNibbleData != null ) {
id |= (( byte2BottomNibbleData [ i >> 1 ] >> nibbleShift ) & 0xF ) << 8 ;
2022-03-17 15:21:30 +01:00
}
2022-03-17 22:24:32 +01:00
if ( byte2TopNibbleData != null ) {
id |= (( byte2TopNibbleData [ i >> 1 ] >> nibbleShift ) & 0xF ) << 12 ;
}
lsb [ i ] = ( short ) id ;
2022-03-17 15:21:30 +01:00
}
2022-03-17 20:13:02 +01:00
}
2022-03-17 15:21:30 +01:00
public static void removeInvalidBlocksHook ( final IExtendedBlockStorageMixin ebs ) {
2022-03-17 22:24:32 +01:00
val blkIdsLSB = ebs . getLSB ();
val blkIdsMSB = ebs . getMSB ();
2022-03-17 15:21:30 +01:00
int cntNonEmpty = 0 ;
int cntTicking = 0 ;
2022-03-17 22:24:32 +01:00
for ( int off = 0 ; off < blkIdsLSB . length ; ++ off ) {
final int id = (( blkIdsLSB [ off ] & 0xFFFF ) | (( blkIdsMSB [ off ] & 0xFF ) << 16 )) & ExtendedConstants . blockIDMask ;
2022-03-17 15:21:30 +01:00
if ( id > 0 ) {
final Block block = ( Block ) Block . blockRegistry . getObjectById ( id );
if ( block == null ) {
if ( IEConfig . removeInvalidBlocks ) {
2022-03-17 22:24:32 +01:00
blkIdsLSB [ off ] = 0 ;
2022-03-17 15:21:30 +01:00
}
}
else if ( block != Blocks . air ) {
++ cntNonEmpty ;
if ( block . getTickRandomly ()) {
++ cntTicking ;
}
}
}
}
ebs . setBlockRefCount ( cntNonEmpty );
ebs . setTickRefCount ( cntTicking );
}
public static int getIdFromBlockWithCheck ( final Block block , final Block oldBlock ) {
final int id = Block . getIdFromBlock ( block );
if ( IEConfig . catchUnregisteredBlocks && id == - 1 ) {
2022-06-15 22:28:32 +02:00
throw new IllegalArgumentException ( "Block " + block + " is not registered. <-- Say about this to the author of this mod, or you can try to enable \"RemoveInvalidBlocks\" option in EID config." );
2022-03-17 15:21:30 +01:00
}
2022-03-17 20:13:02 +01:00
if ( id >= 0 && id <= ExtendedConstants . maxBlockID ) {
2022-03-17 15:21:30 +01:00
return id ;
}
if ( id == - 1 ) {
return Block . getIdFromBlock ( oldBlock );
}
throw new IllegalArgumentException ( "id out of range: " + id );
}
2022-06-17 21:53:59 +02:00
//Biome ID Extender Code
public static byte [] shortToByteArray ( short [] shortArray ) {
byte [] byteArray = new byte [ 512 ] ;
for ( int i = 0 ; i < 256 ; ++ i ) {
byteArray [ i ] = ( byte )( shortArray [ i ] & 255 );
byteArray [ i + 256 ] = ( byte )( shortArray [ i ] >>> 8 );
}
return byteArray ;
}
public static short [] byteToShortArray ( byte [] byteArray ) {
short [] shortArray = new short [ 256 ] ;
for ( int i = 0 ; i < 256 ; ++ i ) {
shortArray [ i ] = ( short )( byteArray [ i + 256 ] << 8 | byteArray [ i ] );
}
return shortArray ;
}
public static short [] oldBiomeByteToNewShortArray ( byte [] byteArray ) {
short [] shortArray = new short [ 256 ] ;
for ( int i = 0 ; i < 256 ; i ++ ) {
shortArray [ i ] = ( short )( byteArray [ i ] & 0xff );
}
return shortArray ;
}
public static int readBiomeArrayFromPacket ( Chunk chunk , byte [] array , int offset ) {
byte [] byteArray = new byte [ 512 ] ;
System . arraycopy ( array , offset , byteArray , 0 , 512 );
(( IChunkMixin ) chunk ). setBiomeShortArray ( byteToShortArray ( byteArray ));
return byteArray . length ;
}
public static int writeBiomeArrayToPacket ( Chunk chunk , byte [] array , int offset ) {
byte [] byteArray = shortToByteArray ((( IChunkMixin ) chunk ). getBiomeShortArray ());
System . arraycopy ( byteArray , 0 , array , offset , 512 );
return byteArray . length ;
}
public static void writeChunkBiomeArrayToNbt ( Chunk chunk , NBTTagCompound nbt ) {
byte [] byteArray = shortToByteArray ((( IChunkMixin ) chunk ). getBiomeShortArray ());
nbt . setByteArray ( "Biomes16" , byteArray );
}
public static void readChunkBiomeArrayFromNbt ( Chunk chunk , NBTTagCompound nbt ) {
short [] data = null ;
if ( nbt . hasKey ( "Biomes16" , 7 )) {
data = byteToShortArray ( nbt . getByteArray ( "Biomes16" ));
} else if ( nbt . hasKey ( "Biomes" , 7 )) {
data = oldBiomeByteToNewShortArray ( nbt . getByteArray ( "Biomes" ));
}
if ( data != null ) {
(( IChunkMixin ) chunk ). setBiomeShortArray ( data );
}
}
2022-03-17 15:21:30 +01:00
}