Jump to content

[1.10] GUI doesn't update


ErnstLustig

Recommended Posts

So, I'm still having troubles figuring out the syncing between server and client. I added a block with a tank and to try it out I added the funcionality to right click a bucket to add/get fluids to/from the tank. I adapted the code mostly from TiCo. And it works. Now I tried EnderIO Fluid conduits and if fluids get added or removed the GUI doesn't get updated. But the fluid is in there as I can still get it out with a bucket. I'm guessing because this only done server-side and I have to tell the client something has changed. Not sure how to do that though. Do I have to use packets for that? Here the most relevant code:

 

public class BlockSqueezer extends BlockFaeries implements ITileEntityProvider {

    @Override
    public boolean onBlockActivated( World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ ){
        TileEntity te = world.getTileEntity( pos );
        if ( !( te instanceof TileEntitySqueezer ) ) {
            return false;
        }
        if( te.hasCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side ) ){
            IFluidHandler fluidHandler = te.getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side );
            boolean success = FluidUtil.interactWithFluidHandler( heldItem, fluidHandler, player );
            if( success ){ return true; }
        }
        if( !world.isRemote ){
            player.openGui( Faeries.instance, GUI_ID, world, pos.getX(), pos.getY(), pos.getZ() );
        }
       return true;
    }
}

 

public class TileEntitySqueezer extends TileEntity implements ITickable {
     
private FluidTank tank = new FluidTank( CAPACITY ) {
        @Override
        protected void onContentsChanged(){ TileEntitySqueezer.this.markDirty(); }
    };

    @Override
    public void readFromNBT( NBTTagCompound compound ){
        super.readFromNBT( compound );
        if( compound.hasKey( "input" ) ){
            inputStack.deserializeNBT( (NBTTagCompound) compound.getTag( "input" ) );
        }
        tank.readFromNBT( compound );
    }

    public NBTTagCompound getUpdateTag() {
        return this.writeToNBT( new NBTTagCompound() );
    }

    @Override
    public NBTTagCompound writeToNBT( NBTTagCompound compound ){
        super.writeToNBT( compound );
        compound.setTag( "input", inputStack.serializeNBT() );
        tank.writeToNBT( compound );
        return compound;
    }

    @Override
    public boolean hasCapability( Capability<?> capability, EnumFacing facing ){
        if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ){
            return true;
        }
        return super.hasCapability( capability, facing );
    }

    @Override
    public <T> T getCapability( Capability<T> capability, EnumFacing facing ){
        if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ){
            if( facing == null ){ return (T) inputStack; }
            return (T) new InsertItemStackHandler( inputStack );
        }
        if( capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ){
            return (T) tank;
        }
        return super.getCapability( capability, facing );
    }

    public FluidTank getFluidTank(){ return tank; }
}

 

public class GuiSqueezer extends GuiContainer {

    public static final int WIDTH = 180;
    public static final int HEIGHT = 152;
    private final TileEntitySqueezer te;

    private static final ResourceLocation background = new ResourceLocation( Reference.MOD_ID, "textures/gui/guisqueezer.png" );

    public GuiSqueezer( TileEntitySqueezer tileEntity, ContainerSqueezer container ){
        super( container );

        xSize = WIDTH;
        ySize = HEIGHT;
        te = tileEntity;
    }

    @Override
    protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY ){
        mc.getTextureManager().bindTexture( background );
        drawTexturedModalRect( guiLeft, guiTop, 0, 0, xSize, ySize );
        FluidStack fluid = te.getFluidTank().getFluid();
        if( fluid != null && fluid.amount != 0 ) {
            ResourceLocation location = te.getFluidTank().getFluid().getFluid().getStill();
            TextureAtlasSprite sprite = mc.getTextureMapBlocks().getAtlasSprite( location.toString() );
            mc.renderEngine.bindTexture( TextureMap.LOCATION_BLOCKS_TEXTURE );
            float filllevel = (float)fluid.amount * 48 / te.CAPACITY;
            drawTexturedModalRect( guiLeft + 82, guiTop + 54 - Math.round( filllevel ), sprite, 16, Math.round( filllevel ) );
        }
    }
    
}

Link to comment
Share on other sites

Look at how ContainerFurnace and GuiFurnace sync data as it does not happen automagically.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Well, I looked into it and I'm not sure how this should help me. In my TEs ItemStacks get updated correctly no matter if input manually or with Hoppers or Item Conduits, also the progress bars I implemented in my machines work fine even without adding listeners (beside that I don't understand the code in ContainerFurnace, the listeners basically update local variable copies for the progress bar, but GuiFurnace accesses the variables from the TE directly not from the Container, not sure what the Container variables are even there for). So ItemStacks and progress bars works fine for, only the FluidStack doesn't get synced correctly. I'm not really understanding.

Link to comment
Share on other sites

Well, I looked into it and I'm not sure how this should help me. In my TEs ItemStacks get updated correctly no matter if input manually or with Hoppers or Item Conduits, also the progress bars I implemented in my machines work fine even without adding listeners (beside that I don't understand the code in ContainerFurnace, the listeners basically update local variable copies for the progress bar, but GuiFurnace accesses the variables from the TE directly not from the Container, not sure what the Container variables are even there for). So ItemStacks and progress bars works fine for, only the FluidStack doesn't get synced correctly. I'm not really understanding.

The way it works to my understanding is that there are two containers open. You have the one on the client and the one on the server. The server should handle all the data meaning you should only update data on the server in your TE. Using a GuiHandler automstically syncs the ItemStacks, but all other data should be synced through packets or the listeners. The variables inside of the container are used to compare last to current. So to some it up you need to sync what type of fluid it is and the amount of fluid and other dynamic data.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Yeah, but what is the advantage of that? If you look in the GuiFurnace code, it accesses as I said the fields directly from the TileEntity, not from the container. Why two containers and sync the data of them there when they are never used (or I at least can't find the use)? Also it works in my code just fine without those, only the fluidstack is giving me problems. Before I blindly try to implement listeners and such, I like to understand first what they are useful for as I don't see the use for them now. Also not sure what you mean with GuiHandler as I can't find a mention of that in the code.

Link to comment
Share on other sites

How do you open your gui handler? Say you are playing on a server and the server experiences a lag spike the tps goes down. This doesnt happen on the client, therefore your gui gets desynced.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Ah, I named it GuiProxy, forgot that it implements GuiHandler.

 

@Override
public Object getServerGuiElement( int ID, EntityPlayer player, World world, int x, int y, int z ){
        BlockPos pos = new BlockPos( x, y, z );
        TileEntity te = world.getTileEntity( pos );
        //other stuff
        if( te instanceof TileEntitySqueezer ){
            return new ContainerSqueezer( player.inventory, (TileEntitySqueezer) te );
        }
}

@Override
public Object getClientGuiElement( int ID, EntityPlayer player, World world, int x, int y, int z ){
        BlockPos pos = new BlockPos( x, y, z );
        TileEntity te = world.getTileEntity( pos );
        //other stuff
        if( te instanceof TileEntitySqueezer ){
            TileEntitySqueezer containerTileEntity = (TileEntitySqueezer) te;
            return new GuiSqueezer( containerTileEntity, new ContainerSqueezer( player.inventory, containerTileEntity ) );
        }
}

 

Link to comment
Share on other sites

I just only saw your edit. Makes sense. But where is the code actually used. As the GuiFurnace doesn't actually use it, that's my question.

It syncs the data between the containers then modifies it in the addListeners method i believe it is called.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Man, I'm not sure. I get what you are saying, but I have a hard time believing this is needed to implement it like that. I just tried to look at the EnderIO Tank code which also renders the tank content in the GUI and I couldn't find any code like that in there. It just accesses the TE's FluidStack directly and renders it, just like I did it (at least it looks like it). I must be missing something totally terribly.

 

Link to comment
Share on other sites

Man, I'm not sure. I get what you are saying, but I have a hard time believing this is needed to implement it like that. I just tried to look at the EnderIO Tank code which also renders the tank content in the GUI and I couldn't find any code like that in there. It just accesses the TE's FluidStack directly and renders it, just like I did it (at least it looks like it). I must be missing something totally terribly.

Try looking for a packet.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

I wanted to look into packets now, but before that I wondered if this is even a client and server sync issue. Because I open the GUI only on the server side, right? But it still doesn't recognize the fluids correctly. Is this how this works? Is there maybe a command to force a block to synchronize with server and client, just to check if this is even the problem? Or what would be the best way to debug that?

Link to comment
Share on other sites

I wanted to look into packets now, but before that I wondered if this is even a client and server sync issue. Because I open the GUI only on the server side, right? But it still doesn't recognize the fluids correctly. Is this how this works? Is there maybe a command to force a block to synchronize with server and client, just to check if this is even the problem? Or what would be the best way to debug that?

No you do not open the Gui on the server it only exists on the client. What happens is you tell the server this players is opening this container and then open this gui so there is a display. Packets are what you use to do this though you may be able to override getUpdateTag and handleUpdateTag but remember to call markDirty whenever the fluid changes. I am not sure if this will be a sync.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Man, I'm not sure. I get what you are saying, but I have a hard time believing this is needed to implement it like that. I just tried to look at the EnderIO Tank code which also renders the tank content in the GUI and I couldn't find any code like that in there. It just accesses the TE's FluidStack directly and renders it, just like I did it (at least it looks like it). I must be missing something totally terribly.

Try looking for a packet.

 

I added packets and it solved the problem. Thanks.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.