Jump to content

[SOLVED] [1.15.2] Text in GUI not updating


Novârch

Recommended Posts

I'm trying to make a simple GUI that I'm eventually going to turn into a countdown timer, but the text in it doesn't update when it should, I suspect it isn't synced.

Here's the code for the GUI's class:

Spoiler

public class GUICounter extends AbstractGui
{
   public static final Minecraft mc = Minecraft.getInstance();

   public void render()
   {
       if(mc == null)
           return;
       LazyOptional<IStand> power = mc.player.getCapability(JojoProvider.STAND, null);
       IStand props = power.orElse(new IStandCapability());
       EntityStandBase stand = JojoLibs.getStand(props.getStandID(), mc.world);
       String text = "String";
       if(props.getStandID() == JojoLibs.StandID.madeInHeaven)
           text = String.valueOf(((EntityMadeInHeaven)stand).getHeaventickr());
       drawString(mc.fontRenderer, text, 4, 4, 0xFFFFFF);
   }
}

 

I call the render method in RenderGameOverlayEvent.Post in my main class. For more context here's the mod's git repo.

It's sad how much time mods spend saying "x is no longer supported on this forum. Please update to a modern version of Minecraft to receive support".

Link to comment
Share on other sites

Problem seems to be in how I'm getting the capability, tried printing out the same value as I should be displaying and it was just 0. Can someone explain to me why with this code the capability doesn't update? 

Spoiler

LazyOptional<IStand> power = Minecraft.getInstance().player.getCapability(JojoProvider.STAND, null);
IStand props = power.orElse(new IStandCapability());

 

 

It's sad how much time mods spend saying "x is no longer supported on this forum. Please update to a modern version of Minecraft to receive support".

Link to comment
Share on other sites

Capabilities aren't synced automatically, you need to sync them yourself. It doesn't look like you're doing this.

 

3 hours ago, Novârch said:

LazyOptional<IStand> power = Minecraft.getInstance().player.getCapability(JojoProvider.STAND, null);
IStand props = power.orElse(new IStandCapability());

 

You probably don't want to use LazyOptional#orElse like that, if the capability isn't present you should either do nothing (if it's expected to not be present sometimes); or throw an error (if it should always be present). You generally don't want to carry on performing the action on a new instance that's not stored anywhere or used by anything.

 

Use LazyOptional#ifPresent to run code only when the capability is present, or LazyOptional#orElseThrow to throw an error when it's not present.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

14 hours ago, Choonster said:

You probably don't want to use LazyOptional#orElse like that, if the capability isn't present you should either do nothing (if it's expected to not be present sometimes); or throw an error (if it should always be present). You generally don't want to carry on performing the action on a new instance that's not stored anywhere or used by anything.

 

Use LazyOptional#ifPresent to run code only when the capability is present, or LazyOptional#orElseThrow to throw an error when it's not present.

Thanks! I've switched to this:

Spoiler

LazyOptional<IStand> power = Minecraft.getInstance().player.getCapability(JojoProvider.STAND, null);
IStand props = power.orElseThrow(() -> new IllegalArgumentException("Capability cannot be empty!"));

 

 

14 hours ago, Choonster said:

Capabilities aren't synced automatically, you need to sync them yourself. It doesn't look like you're doing this.

I've created two packets, an update packet and an update request packet, this is their code:

Spoiler

Update packet:


public class SyncStandCapability
{
    private INBT data;

    public SyncStandCapability() {}

    public SyncStandCapability(IStand props)
    {
        this.data = new CompoundNBT();
        this.data = JojoProvider.STAND.getStorage().writeNBT(JojoProvider.STAND, props, null);
    }

    public void encode(PacketBuffer buffer)
    {
        buffer.writeCompoundTag((CompoundNBT) data);
    }

    public static SyncStandCapability decode(PacketBuffer buffer)
    {
        SyncStandCapability msg = new SyncStandCapability();
        msg.data = buffer.readCompoundTag();
        return msg;
    }

    public static void handle(SyncStandCapability message, Supplier<NetworkEvent.Context> ctx)
    {
        if(ctx.get().getDirection() == NetworkDirection.PLAY_TO_CLIENT)
        {
            ctx.get().enqueueWork(() ->
            {
                PlayerEntity player = StevesBizarreSurvival.PROXY.getPlayer();
                assert player != null;
                IStand props = JojoProvider.get(player);
                assert props != null;
                JojoProvider.STAND.getStorage().readNBT(JojoProvider.STAND, props, null, message.data);
            });
        }
        ctx.get().setPacketHandled(true);
    }
}
Spoiler

Request update packet:



public class RequestSyncStandCapability
{
    private int entityId = 0;
    private INBT data;

    public RequestSyncStandCapability() {}

    public void encode(PacketBuffer buffer) {}

    public static RequestSyncStandCapability decode(PacketBuffer buffer)
    {
        RequestSyncStandCapability msg = new RequestSyncStandCapability();
        return msg;
    }

    public static void handle(RequestSyncStandCapability message, final Supplier<NetworkEvent.Context> ctx)
    {
        if(ctx.get().getDirection() == NetworkDirection.PLAY_TO_SERVER)
        {
            ctx.get().enqueueWork(() ->
            {
                PlayerEntity player = ctx.get().getSender();
                assert player != null;
                IStand props = JojoProvider.get(player);
                assert props != null;
                StevesBizarreSurvival.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), new SyncStandCapability(props));
            });
        }
        ctx.get().setPacketHandled(true);
    }
}

 

 

I've tried sending them before and after declaring the value of props(the capability), but it does nothing. What am I doing wrong?

It's sad how much time mods spend saying "x is no longer supported on this forum. Please update to a modern version of Minecraft to receive support".

Link to comment
Share on other sites

The server should be handling all of the game logic, including when to send packets to the clients. The client shouldn't be requesting a sync, it should mostly just be responsible for notifying the server of player input and displaying/rendering the data that the server tells it to.

 

The capability handler class (IStandCapability) should send the sync packet to the client whenever its data changes, and probably when the player logs in as well. This is assuming that the player that the capability is attached to is the only one who needs this data on the client.

 

Don't just write your capability to NBT and send that in the packet, only send the data that the client needs for display purposes.

 

I don't know exactly why your current implementation doesn't work, but if you do things properly it should be easier to figure out what (if anything) still isn't working.

 

On a related note, IStandCapability isn't a good class name; the I prefix is usually reserved for interfaces. If you have an interface IFoo with a single default implementation, it's common to name that class Foo.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

1 hour ago, Choonster said:

On a related note, IStandCapability isn't a good class name; the I prefix is usually reserved for interfaces. If you have an interface IFoo with a single default implementation, it's common to name that class Foo.

You're right, that name was horrible, I changed it to StandCapability.

1 hour ago, Choonster said:

and probably when the player logs in as well.

Figured that one out, code looks like this:

Spoiler

    @SubscribeEvent
    public void playerJoinWorld(EntityJoinWorldEvent event)
    {
        if(event.getEntity() instanceof PlayerEntity)
        {
            PlayerEntity player = (PlayerEntity) event.getEntity();
            IStand props = JojoProvider.get(player);
            if(!player.world.isRemote)
            {
                INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), new SyncStandCapability(props));
            }
        }
    }

 

 

1 hour ago, Choonster said:

The capability handler class (IStandCapability) should send the sync packet to the client whenever its data changes

I've run into a problem here , as you can see above I'm sending the update packet using this method: INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), new SyncStandCapability(props)) , but I run into some trouble using that in the class you're referring to as I can't get the player, using Minecraft#player would give me the client player, which I can't use, what PacketTarget would be most suitable for use in this class?

It's sad how much time mods spend saying "x is no longer supported on this forum. Please update to a modern version of Minecraft to receive support".

Link to comment
Share on other sites

1 hour ago, Novârch said:

I've run into a problem here , as you can see above I'm sending the update packet using this method: INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), new SyncStandCapability(props)) , but I run into some trouble using that in the class you're referring to as I can't get the player, using Minecraft#player would give me the client player, which I can't use, what PacketTarget would be most suitable for use in this class?

 

Store a reference to the player in the StandCapability class, then send to that player (on the server).

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

  • Novârch changed the title to [SOLVED] [1.15.2] Text in GUI not updating

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.

Announcements



×
×
  • Create New...

Important Information

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