Jump to content

[SOLVED] [1.12.2] GUI for showing custom player capabilities not updating


FlashHUN

Recommended Posts

I am making a mod where I need to show a GUI on the player's screen showing their current mana/max mana. The problem is, even if the values update, the GUI doesn't, it just shows the default values. I'm new to 1.12.2 modding, so I don't really know what might be causing it. Help would be greatly appreciated.

 

GUI class:

Spoiler

public class GuiManaBar extends Gui
{   

    private Minecraft mc;

    public GuiManaBar(Minecraft mc) {
        super();
        this.mc = mc;
    }

    @SubscribeEvent(priority=EventPriority.NORMAL)
    public void onRenderExperienceBar(RenderGameOverlayEvent.Post event) {
        if (event.getType() != ElementType.EXPERIENCE) {
            return;
        }

        IMana mana = mc.player.getCapability(CapabilityMana.MANA_CAPABILITY, null);
        if (mana == null || mana.getMaxMana() == 0) {
            return;
        }

        int xPos = 2;
        int yPos = 2;
        GlStateManager.pushAttrib();
        GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
        GlStateManager.disableLighting();
        GlStateManager.enableAlpha();
        GlStateManager.enableBlend();
        String s = "Mana: " + mana.getMana() + "/" + mana.getMaxMana();
        this.mc.fontRenderer.drawString(s, xPos + 1, yPos, 0);
        this.mc.fontRenderer.drawString(s, xPos - 1, yPos, 0);
        this.mc.fontRenderer.drawString(s, xPos, yPos + 1, 0);
        this.mc.fontRenderer.drawString(s, xPos, yPos - 1, 0);
        this.mc.fontRenderer.drawString(s, xPos, yPos, 8453920);
        GlStateManager.popAttrib();
    }

}

 

 

Mana class:

Spoiler

public class Mana implements IMana{
    private int mana;
    private int maxmana;
    private int manatimer;

    public Mana() {
        mana = 250;
        maxmana = 250;
        manatimer = 160;
    }

    @Override
    public void consumeMana(int points) {
        mana -= points;

        if (this.mana < 0) this.mana = 0;
    }

    @Override
    public void fillMana(int points) {
        mana += points;

        if (this.mana > this.maxmana) this.mana = this.maxmana;
    }

    @Override
    public void setMaxMana(int points) {
        maxmana = points;
    }

    @Override
    public void setManaTimer(int points) {
        manatimer = points;
    }

    @Override
    public void setMana(int points) {
        mana = points;

    }

    @Override
    public int getMaxMana() {
        return maxmana;
    }

    @Override
    public int getMana() {
        return mana;
    }

    @Override
    public int getManaTimer() {
        return manatimer;
    }
}

 

 

IMana interface:

Spoiler

public interface IMana {
    void consumeMana(int cost);
    void fillMana(int points);
    void setMaxMana(int points);
    void setMana(int points);
    void setManaTimer(int points);
    int getMaxMana();
    int getMana();
    int getManaTimer();
}

 

 

CapabilityMana class:

Spoiler

public class CapabilityMana {

    @CapabilityInject(IMana.class)
    public static final Capability<IMana> MANA_CAPABILITY = null;

    public static final EnumFacing DEFAULT_FACING = null;

    public static final ResourceLocation ID = new ResourceLocation(References.mod_id, "Mana");

    public static void register(){
        CapabilityManager.INSTANCE.register(IMana.class, new Capability.IStorage<IMana>() {
            @Override
            public NBTBase writeNBT(Capability<IMana> capability, IMana instance, EnumFacing side) {
                NBTTagCompound nbt = new NBTTagCompound();
                nbt.setInteger("mana", instance.getMana());
                nbt.setInteger("maxmana", instance.getMaxMana());
                nbt.setInteger("manatimer", instance.getManaTimer());
                return nbt;
            }

            @Override
            public void readNBT(Capability<IMana> capability, IMana instance, EnumFacing side, NBTBase nbt) {
                instance.setMana(((NBTTagCompound) nbt).getInteger("mana"));
                instance.setMaxMana(((NBTTagCompound) nbt).getInteger("maxmana"));
                instance.setManaTimer(((NBTTagCompound) nbt).getInteger("manatimer"));
            }
        }, () -> new Mana());
    }

    @Nullable
    public static IMana getMana(final EntityLivingBase entity){
        return CapabilityUtils.getCapability(entity, MANA_CAPABILITY, DEFAULT_FACING);

    }

    public static ICapabilityProvider createProvider(final IMana mana){
        return new CapabilityProviderSerializable<>(MANA_CAPABILITY, DEFAULT_FACING, mana);
    }

    @Mod.EventBusSubscriber(modid = References.mod_id)
    private static class EventHandler {
        @SubscribeEvent
        public static void attachCapabilities(final AttachCapabilitiesEvent<Entity> event) {
            if (event.getObject() instanceof EntityPlayer) {
                final Mana mana = new Mana();
                event.addCapability(ID, createProvider(mana));
            }
        }

        @SubscribeEvent
        public static void playerClone(final PlayerEvent.Clone event) {
            final IMana oldMana = getMana(event.getOriginal());
            final IMana newMana = getMana(event.getEntityPlayer());

            if (newMana != null && oldMana != null) {
                newMana.setMaxMana(oldMana.getMaxMana());
                newMana.setMana(oldMana.getMana());
            }
        }
        
        @SubscribeEvent
        public static void onUpdate(final PlayerTickEvent event) {
            final IMana mana = getMana(event.player);
            
            if (mana.getManaTimer() > 0) {
                mana.setManaTimer(mana.getManaTimer() - 1);
            }
            if (mana != null && mana.getManaTimer() == 0 && mana.getMana() < mana.getMaxMana()) {
                mana.fillMana(1);
                mana.setManaTimer(160);
                event.player.sendMessage(new TextComponentString("Mana: " + mana.getMana()));
            }
        }
        
    }
}

 

 

CapabilityProviderSerializable class:

Spoiler

public class CapabilityProviderSerializable<HANDLER> extends CapabilityProviderSimple<HANDLER> implements INBTSerializable<NBTBase> {
    public CapabilityProviderSerializable(final Capability<HANDLER> capability, @Nullable final EnumFacing facing) {
        this(capability, facing, capability.getDefaultInstance());
    }
    public CapabilityProviderSerializable(final Capability<HANDLER> capability, @Nullable final EnumFacing facing, @Nullable final HANDLER instance) {
        super(instance, capability, facing);
    }

    @Nullable
    @Override
    public NBTBase serializeNBT() {
        return getCapability().writeNBT(getInstance(), getFacing());
    }

    @Override
    public void deserializeNBT(final NBTBase nbt) {
        getCapability().readNBT(getInstance(), getFacing(), nbt);
    }

}

 

 

CapabilityProviderSimple class:

Spoiler

public class CapabilityProviderSimple<HANDLER> implements ICapabilityProvider {
    protected final Capability<HANDLER> capability;
    protected final EnumFacing facing;
    protected final HANDLER instance;

    public CapabilityProviderSimple(@Nullable final HANDLER instance, final Capability<HANDLER> capability, @Nullable final EnumFacing facing) {
        this.instance = instance;
        this.capability = capability;
        this.facing = facing;
    }
    @Override
    public boolean hasCapability(final Capability<?> capability, @Nullable final EnumFacing facing) {
        return capability == getCapability();
    }
    @Override
    @Nullable
    public <T> T getCapability(final Capability<T> capability, @Nullable final EnumFacing facing) {
        if (capability == getCapability()) {
            return getCapability().cast(getInstance());
        }

        return null;
    }
    public final Capability<HANDLER> getCapability() {
        return capability;
    }
    @Nullable
    public EnumFacing getFacing() {
        return facing;
    }
    @Nullable
    public final HANDLER getInstance() {
        return instance;
    }
}

 

 

CapabilityUtils class:

Spoiler

public class CapabilityUtils {
    @Nullable
    public static <T> T getCapability(@Nullable final ICapabilityProvider provider, final Capability<T> capability, @Nullable final EnumFacing facing) {
        return provider != null && provider.hasCapability(capability, facing) ? provider.getCapability(capability, facing) : null;
    }
}

 

 

InjectionUtils class:

Spoiler

public class InjectionUtil {
    @SuppressWarnings({"ConstantConditions", "SameReturnValue"})
    public static <T> T Null() {
        return null;
    }
}

 

 

Edited by FlashHUN
marked as solved
Link to comment
Share on other sites

1 hour ago, diesieben07 said:
  • For the future, please use code blocks for posting your code. It's almost unreadable otherwise.
  • Your CapabilityUtils.getCapability method is useless. Just call getCapability. There is no point in calling hasCapability beforehand to check.
  • You are most likely updating the values on the server side, as you should. But then you are not notifying the client of these changes.
    You have to send a packet updating the client capability under the following circumstances:
    • PlayerLoggedInEvent
    • PlayerChangedDimensionEvent
    • PlayerRespawnEvent
    • Whenever the data changes
  • If you do not plan on exposing your capability as an API for other mods, there is no point writing an interface for it. You can just use your implementation class and avoid the indirection and extra code.
  • PlayerTickEvent fires twice per tick. Check TickEvent#phase.

 

I understand what I need to do and the basics of how I need to do it, but I cannot make it work. How can I make a packet that gets data from the

CapabilityMana

class (I'm guessing?) and sends it to the client through the PacketHandler? I know how to set up a PacketHandler, I just never really worked with packets and player nbt before and this is what's getting me stuck.

Also, is there any way to detect the data changing automatically instead of having to flood classes that change a lot of things with sending packets when changing?

Link to comment
Share on other sites

4 hours ago, diesieben07 said:

Not sure where you got NBT from. NBT is usually used for saving to disk. You have to write the data in your capability to the buffer provided to you in your IMessage.

Like I said, I haven't really worked with the newer versions, but thanks for clarifying. I cannot seem to figure out what is wrong though. I haven't found any examples that I could learn how to do it from and I don't seem to be capable of doing it without one. I never really worked with packets before and it just seems like a lot at first.

 

 

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.