FlashHUN Posted February 28, 2019 Posted February 28, 2019 (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 March 4, 2019 by FlashHUN marked as solved Quote
FlashHUN Posted February 28, 2019 Author Posted February 28, 2019 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? Quote
FlashHUN Posted March 1, 2019 Author Posted March 1, 2019 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. Quote
Recommended Posts
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.