Jump to content

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


Recommended Posts

Posted (edited)

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
Posted
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?

Posted
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.

 

 

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Sorry for the late response, but the game opened and I made a world but it's stuck at 0% Here's the latest.log https://mclo.gs/peEb1R8 I disabled The Factory Must Grow and soulsweapons
    • Hey everyone! Two of my friends downloaded this modpack and are having an issue with the blocks loading in correctly. Grass looks like bamboo, waystones look like two barrels stacked on eachother, and wheat looks like water and stairs. What is this problem? How can we fix it? Neither of my other friends or myself had this issue. 
    • I removed Yung's cave biome mod and It wasnt in one of those biomes however the log file said the same line (([25Apr2025 21:20:15.500] [Flywheel Task Executor #5/WARN] [Embeddium-MixinTaintDetector/]: Mod(s) [oculus] are modifying Embeddium class me.jellysquid.mods.sodium.client.render.vertex.serializers.VertexSerializerRegistryImpl, which may cause instability.))
    • Note: i had a couple of ideas, but i just don't know how to execute them. The main idea was to make the new block (let's exemplify with a mixer) be essentially a clone of the mechanical mixer (different texture tho) that would have a different recipe type (instead of mixing, advanced_mixing) and i would copy all the create mod recipes and edit the processing time while also adding the tier dependent ones.
    • Hi! Before everything, thank you for even reading. I'm coming here in need of help making a few aspects for a create mod addon. It's an addon that aims to add almost the full periodic table with realistic ways of obtaining all the elements and capability of almost full automation. For what purpose? A techy armor and to go to the moon and rocky planets of the solar system. It'll have 3 different tiers of machines (mixer, millstone, crushing wheels): basic (just the normal create mod machines but renamed), advanced (25% faster and has recipes only possible for this tier and above) end elite (75% faster than basic and recipes only available for this tier). The problem is, I'm not a coder. I know less than the basics. I know how to do everything else but these machine tiers and i need some help if you can.
  • Topics

×
×
  • Create New...

Important Information

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