NullPointerException в пакетах

Версия Minecraft
1.7.10
В первую очередь, этот вопрос будет довольно таки необычном, так как он связан с созданием аддона для AE2. Возможно кто-то слышал(но врядле) о моём моде, он называется Applied Integrations

Я пытаюсь создать пакеты для установки фильтров машинок, сами по себе пакеты работают (отправляются), но когда я пытаюсь в этих же пакетах получить хоть какие-то переменные от самой машинки, то у меня выдаёт null pointer exception...

Вот немного кода:

Сам класс пакета:
Java:
/**
* @Author Azazell
*/
// Sends data from client to server (gui to part)
public class PacketClientFilter extends AIPacket<PacketClientFilter> {

    public LiquidAIEnergy energy;
    public int index;
    public AIPart part;

    public PacketClientFilter(){}

    // Only neutral point between client, and server
    public PacketClientFilter(EntityPlayer player ,AIPart part, LiquidAIEnergy energy, int index) {

        this.energy = energy;
        this.index = index;
        this.part = part;

        try {
            AILog.chatLog(part.toString());
            AILog.chatLog(part.getSide().toString());
        }catch (NullPointerException CENSOREDException){
            AILog.chatLog(CENSOREDException.toString());
        }

    }
    @Override
    public IMessage HandleMessage(MessageContext ctx) {
        AILog.chatLog("Message handled");

        if(this.part != null) {
            ((IEnergyMachine)part).updateFilter(RF, 0);
        }
        return null;
    }
}
Сразу скажу, что: в пакете нету функций: fromBytes, toBytes, они объявлены в AIPacket и как я многократно убеждался, они нормально работают..

Итак, далее: как я отправляю пакеты:
Java:
public void mouseClicked( final LiquidAIEnergy energy )
{

    this.setEnergy( energy, 1 );

    AIContainer container = hostGUI.getNodeContainer();

    if(container != null) {

        NetworkHandler.sendToServer(new PacketClientFilter(this.player,(AIPart)part,energy,id));

    }

}
Тут LiquidAIEnergy это класс для жидкостей, которые будут отображать привязанную к ним энергию (RF, EU и т.п.)

И наконец нам нужен сам класс AIPart, если что это не класс обычного тайла, а class extends IPart, IPart это интерфейс из AE2Api:
Java:
/**
* @Author Azazell
*/
public abstract class AIPart
        implements IPart, IGridHost, IActionHost, IPowerChannelState, IPriorityHost
{
    private final static String NBT_KEY_OWNER = "Owner";

    protected final static int ACTIVE_FACE_BRIGHTNESS = 0xD000D0;

   
    protected final static int ACTIVE_TERMINAL_LIGHT_LEVEL = 9;

    private final SecurityPermissions[] interactionPermissions;
    public final int uniquePacketID;

    protected IPartHost host;

    protected TileEntity hostTile;
    private ForgeDirection cableSide;


    private boolean isActive;
    private boolean isPowered;

    private int ownerID;
    public final ItemStack associatedItem;
    protected IGridNode node;
    protected AEPartGridBlock gridBlock;

    protected int capacity = 1000000;
    protected int maxTransfer = 500000;

    public AIPart(final PartEnum associatedPart, final SecurityPermissions ... interactionPermissions )
    {
        // Set the associated item
        this.associatedItem = associatedPart.getStack();

        this.uniquePacketID = getNewID();
        // Set clearance
        if( ( interactionPermissions != null ) && ( interactionPermissions.length > 0 ) )
        {
            this.interactionPermissions = interactionPermissions;
        }
        else
        {
            this.interactionPermissions = null;
        }
            // Create the grid block
        if(EffectiveSide.isServerSide()) {
            this.gridBlock = new AEPartGridBlock(this);
        }else{
            this.gridBlock = null;
        }
    }

    private void updateStatus()
    {
        // Ignored client side
        if( EffectiveSide.isClientSide() )
        {
            return;
        }

        // Do we have a node?
        if( this.node != null )
        {
            // Get the active state
            boolean currentlyActive = this.node.isActive();

            // Has that state changed?
            if( currentlyActive != this.isActive )
            {
                // Set our active state
                this.isActive = currentlyActive;

                // Mark the host for an update
                this.host.markForUpdate();
            }
        }

        // Fire the neighbor changed event
        this.onNeighborChanged();
    }
    protected abstract AIPrivateInventory getUpgradeInventory();
   
    protected boolean doesPlayerHavePermission( final EntityPlayer player, final SecurityPermissions permission )
    {
        if( EffectiveSide.isClientSide() )
        {
            return false;
        }

        // Get the security grid
        ISecurityGrid sGrid = this.gridBlock.getSecurityGrid();

        // Did we get the grid?
        if( sGrid == null )
        {
            // No security grid to check against.
            return false;
        }

        // Return the permission
        return sGrid.hasPermission( player, permission );
    }

   

    protected boolean doesPlayerHavePermission( final int playerID, final SecurityPermissions permission )
    {
        if( EffectiveSide.isClientSide() )
        {
            return false;
        }

        // Get the security grid
        ISecurityGrid sGrid = this.gridBlock.getSecurityGrid();

        // Did we get the grid?
        if( sGrid == null )
        {
            // No security grid to check against.
            return false;
        }

        // Return the permission
        return sGrid.hasPermission( playerID, permission );
    }


    protected TileEntity getFacingTile()
    {
        if( this.hostTile == null )
        {
            return null;
        }

        // Get the world
        World world = this.hostTile.getWorldObj();

        // Get our location
        int x = this.hostTile.xCoord;
        int y = this.hostTile.yCoord;
        int z = this.hostTile.zCoord;

        // Get the tile entity we are facing
        return world.getTileEntity( x + this.cableSide.offsetX, y + this.cableSide.offsetY, z + this.cableSide.offsetZ );
    }



    @Override
    public void addToWorld()
    {
        // Ignored on client side
        if( EffectiveSide.isClientSide() )
        {
            return;
        }
        this.gridBlock = new AEPartGridBlock(this);
        this.node = AEApi.instance().createGridNode( this.gridBlock );

        // Set the player id
        this.node.setPlayerID( this.ownerID );

        // Update state
        if( ( this.hostTile != null ) && ( this.host != null ) && ( this.hostTile.getWorldObj() != null ) )
        {
            try
            {
                this.node.updateState();
            }
            catch( Exception e )
            {
                AILog.error( e, "Machine (%s) was unable to update it's node. The part may not function correctly",
                        this.associatedItem.getDisplayName() );
            }
        }

        // Update the part
        this.updateStatus();
        AILog.info("Machine:" + this.associatedItem.getDisplayName() + " Placed by Player with AE2 ID:" + this.getGridNode().getPlayerID());
    }

    @Override
    public abstract int cableConnectionRenderTo();

    @Override
    public boolean canBePlacedOn( final BusSupport type )
    {
        // Can only be placed on normal cable
        return type == BusSupport.CABLE;
    }

    @Override
    public boolean canConnectRedstone()
    {
        return false;
    }

    @Override
    public IGridNode getActionableNode()
    {
        return this.node;
    }

    @Override
    public abstract void getBoxes( IPartCollisionHelper helper );

    @SideOnly(Side.CLIENT)
    @Override
    public abstract IIcon getBreakingTexture();

    @Override
    public AECableType getCableConnectionType( final ForgeDirection dir )
    {
        return AECableType.SMART;
    }



    @Override
    public void getDrops( final List<ItemStack> drops, final boolean wrenched )
    {
    }

    @Override
    public final IGridNode getExternalFacingNode()
    {
        return null;
    }

    public AEPartGridBlock getGridBlock()
    {
        return this.gridBlock;
    }

    @Override
    public IGridNode getGridNode()
    {
        return this.node;
    }

    @Override
    public IGridNode getGridNode( final ForgeDirection direction )
    {
        return getGridNode();
    }

    public final IPartHost getHost()
    {
        return this.host;
    }


    public final TileEntity getHostTile()
    {
        return this.hostTile;
    }
   
    public abstract double getIdlePowerUsage();

    @Override
    public ItemStack getItemStack( final PartItemStack type )
    {
        // Get the itemstack
        ItemStack itemStack = this.associatedItem.copy();

        // Save NBT data if the part was wrenched
        if( type == PartItemStack.Wrench )
        {
            // Create the item tag
            NBTTagCompound itemNBT = new NBTTagCompound();

            // Write the data
            this.writeToNBT( itemNBT, PartItemStack.Wrench );

            // Set the tag
            if( !itemNBT.hasNoTags() )
            {
                itemStack.setTagCompound( itemNBT );
            }
        }

        return itemStack;
    }
   
   


    public final DimensionalCoord getLocation()
    {
        return new DimensionalCoord( this.hostTile.getWorldObj(), this.hostTile.xCoord, this.hostTile.yCoord, this.hostTile.zCoord );
    }
    public Object getClientGuiElement( final EntityPlayer player ) {return null; }
    public Object getServerGuiElement( final EntityPlayer player ) { return null; }


    public ForgeDirection getSide()
    {
        return this.cableSide;
    }

   
    public String getUnlocalizedName()
    {
        return this.associatedItem.getUnlocalizedName() + ".name";
    }


    @Override
    public boolean isActive()
    {
        // Are we server side?
        if( EffectiveSide.isServerSide() )
        {
            // Do we have a node?
            if( this.node != null )
            {
                // Get it's activity
                this.isActive = this.node.isActive();
            }
            else
            {
                this.isActive = false;
            }
        }

        return this.isActive;
    }

    @Override
    public boolean isLadder( final EntityLivingBase entity )
    {
        return false;
    }
   
    @Override
    public abstract int getLightLevel();
    public final boolean isPartUseableByPlayer( final EntityPlayer player )
    {
        if( EffectiveSide.isClientSide() )
        {
            return false;
        }

        // Null check host
        if( ( this.hostTile == null ) || ( this.host == null ) )
        {
            return false;
        }

        // Does the host still exist in the world and the player in range of it?
        if( !QuEUtils.canPlayerInteractWith( player, this.hostTile ) )
        {
            return false;
        }

        // Is the part still attached?
        if( this.host.getPart( this.cableSide ) != this )
        {
            return false;
        }

        // Are there any permissions to check?
        if( this.interactionPermissions != null )
        {
            // Get the security grid
            ISecurityGrid sGrid = this.gridBlock.getSecurityGrid();
            if( sGrid == null )
            {
                // Security grid was unaccessible.
                return false;
            }

            // Check each permission
            for( SecurityPermissions perm : this.interactionPermissions )
            {
                if( !sGrid.hasPermission( player, perm ) )
                {
                    return false;
                }
            }
        }

        return true;
    }

    @Override
    public boolean isPowered()
    {
        try
        {
            // Server side?
            if( EffectiveSide.isServerSide() && ( this.gridBlock != null ) )
            {
                // Get the energy grid
                IEnergyGrid eGrid = this.gridBlock.getEnergyGrid();
                if( eGrid != null )
                {
                    this.isPowered = eGrid.isNetworkPowered();
                }
                else
                {
                    this.isPowered = false;
                }
            }
        }
        catch( Exception e )
        {
            // Network unavailable, return cached value.
        }

        return this.isPowered;
    }

   


    public boolean isReceivingRedstonePower()
    {
        if( this.host != null )
        {
            // Get redstone state
            return this.host.hasRedstone( this.cableSide );
        }
        return false;
    }

    @Override
    public boolean isSolid()
    {
        return false;
    }


    public final void markForSave()
    {
        // Ensure there is a host
        if( this.host != null )
        {
            // Mark
            this.host.markForSave();
        }
    }
   
    public final void markForUpdate()
    {
        if( this.host != null )
        {
            this.host.markForUpdate();
        }
    }
    public List<String> getWailaBodey(NBTTagCompound tag, List<String> oldList) {
        return oldList;
    }

    public NBTTagCompound getWailaTag(NBTTagCompound tag) {
        return tag;
    }
    @Override
    public boolean onActivate( final EntityPlayer player, final Vec3 position )
    {
        // Is the player sneaking?
        if( player.isSneaking() )
        {
            return false;
        }

        // Is this server side?
        if( EffectiveSide.isServerSide() )
        {
            // Launch the gui
            AppliedIntegrations.launchGui( this, player, this.hostTile.getWorldObj(), this.hostTile.xCoord, this.hostTile.yCoord, this.hostTile.zCoord );
        }
        return true;
    }

    @Override
    public void onEntityCollision( final Entity entity )
    {
    }

    @Override
    public void onNeighborChanged()
    {
    }

    @Override
    public final void onPlacement( final EntityPlayer player, final ItemStack held, final ForgeDirection side )
    {
        // Set the owner
        this.ownerID = AEApi.instance().registries().players().getID( player.getGameProfile() );
    }

    @Override
    public boolean onShiftActivate( final EntityPlayer player, final Vec3 position )
    {
        return false;
    }
    @Override
public void randomDisplayTick(World world, int x, int y, int z, Random r) {}

    @Override
    public void readFromNBT( final NBTTagCompound data )
    {
        // Read the owner
        if( data.hasKey( AIPart.NBT_KEY_OWNER ) )
        {
            this.ownerID = data.getInteger( AIPart.NBT_KEY_OWNER );
        }
    }

    @SideOnly(Side.CLIENT)
    @Override
    public boolean readFromStream( final ByteBuf stream ) throws IOException
    {
        // Cache old values
        boolean oldActive = this.isActive;
        boolean oldPowered = this.isPowered;

        // Read the new values
        this.isActive = stream.readBoolean();
        this.isPowered = stream.readBoolean();

        // Redraw if they don't match.
        return( ( oldActive != this.isActive ) || ( oldPowered != this.isPowered ) );
    }

    @Override
    public void removeFromWorld()
    {
        if( this.node != null )
        {
            this.node.destroy();
        }
    }

    @SideOnly(Side.CLIENT)
    @Override
    public void renderDynamic( final double x, final double y, final double z, final IPartRenderHelper helper, final RenderBlocks renderer )
    {
        // Ignored
    }

    @SideOnly(Side.CLIENT)
    @Override
    public abstract void renderInventory( IPartRenderHelper helper, RenderBlocks renderer );

    @SideOnly(Side.CLIENT)
    public void renderInventoryBusLights( final IPartRenderHelper helper, final RenderBlocks renderer )
    {
        // Set color to white
        helper.setInvColor( 0xFFFFFF );

        IIcon busColorTexture = TextureManager.BUS_COLOR.getTextures()[0];

        IIcon sideTexture = TextureManager.BUS_COLOR.getTextures()[2];

        helper.setTexture( busColorTexture, busColorTexture, sideTexture, sideTexture, busColorTexture, busColorTexture );

        // Rend the box
        helper.renderInventoryBox( renderer );

        // Set the brightness
        Tessellator.instance.setBrightness( 0xD000D0 );

        helper.setInvColor( AEColor.Transparent.blackVariant );

        IIcon lightTexture = TextureManager.BUS_COLOR.getTextures()[1];

        // Render the lights
        helper.renderInventoryFace( lightTexture, ForgeDirection.UP, renderer );
        helper.renderInventoryFace( lightTexture, ForgeDirection.DOWN, renderer );
        helper.renderInventoryFace( lightTexture, ForgeDirection.NORTH, renderer );
        helper.renderInventoryFace( lightTexture, ForgeDirection.EAST, renderer );
        helper.renderInventoryFace( lightTexture, ForgeDirection.SOUTH, renderer );
        helper.renderInventoryFace( lightTexture, ForgeDirection.WEST, renderer );
    }
    @Override
    public int isProvidingStrongPower()
    {
        return 0;
    }

    @Override
    public int isProvidingWeakPower()
    {
        return 0;
    }
    @SideOnly(Side.CLIENT)
    @Override
    public abstract void renderStatic( int x, int y, int z, IPartRenderHelper helper, RenderBlocks renderer );

    @SideOnly(Side.CLIENT)
    public void renderStaticBusLights( final int x, final int y, final int z, final IPartRenderHelper helper, final RenderBlocks renderer )
    {
        IIcon busColorTexture = TextureManager.BUS_COLOR.getTextures()[0];

        IIcon sideTexture = TextureManager.BUS_COLOR.getTextures()[2];

        helper.setTexture( busColorTexture, busColorTexture, sideTexture, sideTexture, busColorTexture, busColorTexture );

        // Render the box
        helper.renderBlock( x, y, z, renderer );

        // Are we active?
        if( this.isActive() )
        {
            // Set the brightness
            Tessellator.instance.setBrightness( 0xD000D0 );

            // Set the color to match the cable
            Tessellator.instance.setColorOpaque_I( this.host.getColor().blackVariant );
        }
        else
        {
            // Set the color to black
            Tessellator.instance.setColorOpaque_I( 0 );
        }

        IIcon lightTexture = TextureManager.BUS_COLOR.getTextures()[1];

        // Render the lights
        helper.renderFace( x, y, z, lightTexture, ForgeDirection.UP, renderer );
        helper.renderFace( x, y, z, lightTexture, ForgeDirection.DOWN, renderer );
        helper.renderFace( x, y, z, lightTexture, ForgeDirection.NORTH, renderer );
        helper.renderFace( x, y, z, lightTexture, ForgeDirection.EAST, renderer );
        helper.renderFace( x, y, z, lightTexture, ForgeDirection.SOUTH, renderer );
        helper.renderFace( x, y, z, lightTexture, ForgeDirection.WEST, renderer );
    }

    @Override
    public boolean requireDynamicRender()
    {
        return false;
    }

    @Override
    public void securityBreak()
    {
        List<ItemStack> drops = new ArrayList<ItemStack>();

        // Get this item
        drops.add( this.getItemStack( PartItemStack.Break ) );

        // Get the drops for this part
        this.getDrops( drops, false );



        // Remove the part
        this.host.removePart( this.cableSide, false );

    }

    @Override
    public final void setPartHostInfo( final ForgeDirection side, final IPartHost host, final TileEntity tile )
    {
        this.cableSide = side;
        this.host = host;
        this.hostTile = tile;

    }

    @MENetworkEventSubscribe
    public final void setPower( final MENetworkPowerStatusChange event )
    {
        this.updateStatus();
    }

    /**
     * Setup the part based on the passed item.
     *
     * @param itemPart
     */
    public void setupPartFromItem( final ItemStack itemPart )
    {
        if( itemPart.hasTagCompound() )
        {
            this.readFromNBT( itemPart.getTagCompound() );
        }
    }

    @MENetworkEventSubscribe
    public void updateChannels( final MENetworkChannelsChanged event )
    {
        this.updateStatus();
    }

    /**
     * General call to WriteNBT, assumes a world save. DO NOT call this from a
     * subclass's writeToNBT method.
     */
    @Override
    public void writeToNBT( final NBTTagCompound data )
    {
        // Assume world saving.
        this.writeToNBT( data, PartItemStack.World );
    }

    /**
     * Saves NBT data specific to the save type.
     *
     * @param data
     * @param saveType
     */
    public void writeToNBT( final NBTTagCompound data, final PartItemStack saveType )
    {
        if( saveType == PartItemStack.World )
        {
            // Set the owner ID
            data.setInteger( AIPart.NBT_KEY_OWNER, this.ownerID );
        }

    }

    @Override
    public void writeToStream( final ByteBuf stream ) throws IOException
    {
        // Write active
        stream.writeBoolean( this.isActive() );

        // Write powered
        stream.writeBoolean( this.isPowered() );
    }

    public IMEMonitor<IAEFluidStack> getEnergyProvidingInventory() {
        IGridNode n = getGridNode();
        if (n == null)
            return null;
        IGrid g = n.getGrid();
        if (g == null)
            return null;
        IStorageGrid storage = g.getCache(IStorageGrid.class);
        if (storage == null)
            return null;
        IMEMonitor<IAEFluidStack> energyStorage = storage.getFluidInventory();
        if (energyStorage == null)
            return null;
        return energyStorage;
    }
}
Вообще этот класс не особо важен, так как проблема связана с устройством самих пакетов и механики SideOnly, но всё таки пусть будет, вдруг я что-то упустил.

Буду ждать вашего ответа, если нужна дополнительная инфа, пишите.
 
Последнее редактирование:
3,005
192
592
Попробуй дебажить fromBytes, toBytes, один из основных моментов.
Ну и желательно скинуть сам класс AIPacket.
 
3,005
192
592
public LiquidAIEnergy energy;
public int index;
public AIPart part;
Смотри, у тебя есть LiquidAIEnergy и AIPart.
А пакеты у тебя не могут такое обработать.
Вот, что у тебя обрабатывается:
Код:
Byte.TYPE
Short.TYPE
Integer.TYPE
Long.TYPE
Float.TYPE
Double.TYPE
Boolean.TYPE
Character.TYPE
String.class
NBTTagCompound.class
ItemStack.class
P.S. Было просмотрено в декомпиле, актуально на 2.5 версию AI.
P.S.S. А зачем тебе столько АПИ хранить в моде? Ну и еще какой-то QuantumEnergistics.
 
Это старое название, незнаю где ты его нашёл, ах да: я взял класс пакета у Vazkii, и добавил 8 методов, как раз для обработки этого всёго, вот такая стата:
Byte.TYPE
Short.TYPE
Integer.TYPE
Long.TYPE
Float.TYPE
Double.TYPE
Boolean.TYPE
Character.TYPE
String.class
NBTTagCompound.class
ItemStack.class
Как я понял также взята из папки bin?
Вот актуальный класс:
Java:
public abstract class AIPacket<REQ extends AIPacket> implements Serializable, IMessage, IMessageHandler<REQ, IMessage> {

    private static final HashMap<Class, Pair<Reader, Writer>> handlers = new HashMap();
    private static final HashMap<Class, Field[]> fieldCache = new HashMap();

    static {
        putInMap(byte.class, AIPacket::readByte, AIPacket::writeByte);
        putInMap(short.class, AIPacket::readShort, AIPacket::writeShort);
        putInMap(int.class, AIPacket::readInt, AIPacket::writeInt);
        putInMap(long.class, AIPacket::readLong, AIPacket::writeLong);
        putInMap(float.class, AIPacket::readFloat, AIPacket::writeFloat);
        putInMap(double.class, AIPacket::readDouble, AIPacket::writeDouble);
        putInMap(boolean.class, AIPacket::readBoolean, AIPacket::writeBoolean);
        putInMap(char.class, AIPacket::readChar, AIPacket::writeChar);
        putInMap(String.class, AIPacket::readString, AIPacket::writeString);
        putInMap(NBTTagCompound.class, AIPacket::readNBT, AIPacket::writeNBT);
        putInMap(ItemStack.class, AIPacket::readItemStack, AIPacket::writeItemStack);

        // Base parts, Energy, World and tiles
        putInMap(LiquidAIEnergy.class, AIPacket::readEnergy, AIPacket::writeEnergy);
        // parts
        putInMap(AIPart.class,AIPacket::readPart,AIPacket::writePart);
        putInMap(World.class,AIPacket::readWorld,AIPacket::writeWorld);
        putInMap(ForgeDirection.class, AIPacket::readDirection,AIPacket::writeDirection);

    }




    @Override
    public final IMessage onMessage(REQ message, MessageContext context){
        return HandleMessage(context);
    }
    public abstract IMessage HandleMessage(MessageContext ctx);

    @Override
    public final void fromBytes(ByteBuf buf) {
        try {
            Class<?> clazz = getClass();
            Field[] clFields = getClassFields(clazz);
            for(Field f : clFields) {
                Class<?> type = f.getType();
                if(acceptField(f, type))
                    readField(f, type, buf);
            }
        } catch(Exception e) {
            throw new RuntimeException("Error at reading packet " + this, e);
        }
    }

    @Override
    public final void toBytes(ByteBuf buf) {
        try {
            Class<?> clazz = getClass();
            Field[] clFields = getClassFields(clazz);
            for(Field f : clFields) {
                Class<?> type = f.getType();
                if(acceptField(f, type))
                    writeField(f, type, buf);
            }
        } catch(Exception e) {
            throw new RuntimeException("Error at writing packet " + this, e);
        }
    }

    protected static Field[] getClassFields(Class<?> clazz) {
        if(fieldCache.containsValue(clazz))
            return fieldCache.get(clazz);
        else {
            Field[] fields = clazz.getFields();
            Arrays.sort(fields, (Field f1, Field f2) -> {
                return f1.getName().compareTo(f2.getName());
            });
            fieldCache.put(clazz, fields);
            return fields;
        }
    }

    protected final void writeField(Field f, Class clazz, ByteBuf buf) throws IllegalArgumentException, IllegalAccessException {
        Pair<Reader, Writer> handler = getHandler(clazz);
        handler.getRight().write(f.get(this), buf);

    }

    protected final void readField(Field f, Class clazz, ByteBuf buf) throws IllegalArgumentException, IllegalAccessException {
        Pair<Reader, Writer> handler = getHandler(clazz);
        f.set(this, handler.getLeft().read(buf));
    }

    protected static Pair<Reader, Writer> getHandler(Class<?> clazz) {
        Pair<Reader, Writer> pair = handlers.get(clazz);
        if(pair == null)
            throw new RuntimeException("No R/W handler for  " + clazz);
        return pair;
    }

    protected static boolean acceptField(Field f, Class<?> type) {
        int mods = f.getModifiers();
        if(Modifier.isFinal(mods) || Modifier.isStatic(mods) || Modifier.isTransient(mods))
            return false;
        if(f.isAnnotationPresent(Overlook.class))
            return false;
        return handlers.containsKey(type);
    }

    protected static <T extends Object>void putInMap(Class<T> type, Reader<T> reader, Writer<T> writer) {
        handlers.put(type, Pair.of(reader, writer));
    }

    protected static byte readByte(ByteBuf buf) {
        return buf.readByte();
    }

    protected static void writeByte(byte b, ByteBuf buf) {
        buf.writeByte(b);
    }

    protected static short readShort(ByteBuf buf) {
        return buf.readShort();
    }

    protected static void writeShort(short s, ByteBuf buf) {
        buf.writeShort(s);
    }

    protected static int readInt(ByteBuf buf) {
        return buf.readInt();
    }

    protected static void writeInt(int i, ByteBuf buf) {
        buf.writeInt(i);
    }

    protected static long readLong(ByteBuf buf) {
        return buf.readLong();
    }

    protected static void writeLong(long l, ByteBuf buf) {
        buf.writeLong(l);
    }

    protected static float readFloat(ByteBuf buf) {
        return buf.readFloat();
    }

    protected static void writeFloat(float f, ByteBuf buf) {
        buf.writeFloat(f);
    }

    protected static double readDouble(ByteBuf buf) {
        return buf.readDouble();
    }

    protected static void writeDouble(double d, ByteBuf buf) {
        buf.writeDouble(d);
    }

    protected static boolean readBoolean(ByteBuf buf) {
        return buf.readBoolean();
    }

    protected static void writeBoolean(boolean b, ByteBuf buf) {
        buf.writeBoolean(b);
    }

    protected static char readChar(ByteBuf buf) {
        return buf.readChar();
    }

    protected static void writeChar(char c, ByteBuf buf) {
        buf.writeChar(c);
    }

    protected static String readString(ByteBuf buf) {
        return ByteBufUtils.readUTF8String(buf);
    }

    protected static void writeString(String s, ByteBuf buf) {
        ByteBufUtils.writeUTF8String(buf, s);
    }

    protected static NBTTagCompound readNBT(ByteBuf buf) {
        return ByteBufUtils.readTag(buf);
    }

    protected static void writeNBT(NBTTagCompound cmp, ByteBuf buf) {
        ByteBufUtils.writeTag(buf, cmp);
    }

    protected static ItemStack readItemStack(ByteBuf buf) {
        return ByteBufUtils.readItemStack(buf);
    }

    protected static void writeItemStack(ItemStack stack, ByteBuf buf) {
        ByteBufUtils.writeItemStack(buf, stack);
    }


    // Applied Integrations
    protected static void writeEnergy( LiquidAIEnergy energy,ByteBuf buf){
        if(energy != null)
            ByteBufUtils.writeUTF8String(buf,energy.getTag());
        else
            ByteBufUtils.writeUTF8String(buf,"null");
    }
    protected static LiquidAIEnergy readEnergy(ByteBuf buf){
        String read = ByteBufUtils.readUTF8String(buf);
        if(read != "null")
            return LiquidAIEnergy.getEnergy(read);
        else
            return null;
    }
    // parts
    protected static AIPart readPart(ByteBuf buf){
        try {
            World world = readWorld(buf);
            TileEntity entity = world.getTileEntity(buf.readInt(), buf.readInt(), buf.readInt());
            ForgeDirection side = ForgeDirection.getOrientation(buf.readInt());

            return (AIPart) (((IPartHost) entity).getPart(side));
        }catch (Exception e){}
        return null;
    }
    protected static void writePart(AIPart part, ByteBuf buf){
        try {
            TileEntity tile = part.getHostTile();
            buf.writeInt(tile.getWorldObj().provider.dimensionId);
            buf.writeInt(tile.xCoord);
            buf.writeInt(tile.yCoord);
            buf.writeInt(tile.zCoord);

            buf.writeInt(part.getSide().ordinal());
        }catch (Exception e){
        }
    }
    private static World readWorld(ByteBuf buf) {
        World world = DimensionManager.getWorld(buf.readInt());

        if (FMLCommonHandler.instance().getSide() == Side.CLIENT) {
            if (world == null) {
                world = Minecraft.getMinecraft().theWorld;
            }
        }

        return world;
    }
    private static void writeWorld(World w, ByteBuf buf){

        try{
            buf.writeInt(w.provider.dimensionId);
        }catch (NullPointerException e){
            buf.writeInt(DimensionManager.getNextFreeDimId());
        }
    }

    private static void writeDirection(ForgeDirection forgeDirection, ByteBuf byteBuf) {
        byteBuf.writeByte((byte)forgeDirection.ordinal());
    }

    private static ForgeDirection readDirection(ByteBuf buf){
        return ForgeDirection.getOrientation(buf.readByte());
    }

    public interface Writer<T extends Object> {
        void write(T t, ByteBuf buf);
    }

    public interface Reader<T extends Object> {
        T read(ByteBuf buf);
    }

}
 
Как видишь тут есть методы readPart, writePart... И да проблема вовсе не в toBytes, fromBytes, так как параметры part'а не могу получить даже в конструкторе:
AILog.chatLog(part.toString); Выдаст ссылку на part
AILog.chatLog(part.getLocation().x+""); Выдаст ноль.. При этом проблема НЕ в getLocation, точно также с getHostTile().xCoord; и т.п.
 
3,005
192
592
Ну, раз в конструкторе даже все в нулле, то ...
А! Стоп, на клиенте ты не сможешь нормально посмотреть то, что лежит в чем-то другом..
Короче говоря.
Отсылай не парт и Energy, а просто BlockPos.
Потом бери мир с серверного игрока (с пакета, не вручную) а после через BlockPos получай тайл и делай что хочешь.
Ты ж на клиенте все сохраняешь, а там тайла нету.
P.S. BlockPos -> x y z.
 
3,005
192
592
Есть дс?
Напиши в лс.
Там войс + демка лучше будет..
Чем ответы без обновления и оповещения.
 
Ладно, вроде бы сам разобрался, короче getSide не отправлял данные в клиент, поэтому я просто сделал переменную, которую он возвращает публичной, вроде готово.. Спасибо за помощь
 
Последнее редактирование:
Сверху