Jump to content

LK1905

Members
  • Posts

    46
  • Joined

  • Last visited

Everything posted by LK1905

  1. Then don't look at it, and let someone else answer?
  2. Wouldn't that mean that the names/buttons aren't being grabbed once, but every single time I open the screen, which means it should open with the new buttons/names the next time I open it?
  3. Doesn't init run every time you open a screen? Meaning it would check the style of each slot every time you open it?
  4. Hi, I've created a capability that gives the player up to 6 slots of "attack styles", with the first 3 given values by default, and the others empty/null by default. I have an enum which contains different attack styles, and different values for each one. Depending on what Tiered item you wield, each slot can be changed to a different attack style. This is the event handler that runs a LivingEquipmentChangeEvent everytime you change whats in the player's mainhand: package lk1905.gielinorcraft.events; import lk1905.gielinorcraft.Gielinorcraft; import lk1905.gielinorcraft.api.combat.AttackStyles; import lk1905.gielinorcraft.capability.attackstyle.AttackStyleCapability; import lk1905.gielinorcraft.capability.attackstyle.IAttackStyle; import lk1905.gielinorcraft.network.PacketHandler; import lk1905.gielinorcraft.network.StringPacket; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.AxeItem; import net.minecraft.item.BowItem; import net.minecraft.item.CrossbowItem; import net.minecraft.item.HoeItem; import net.minecraft.item.Item; import net.minecraft.item.PickaxeItem; import net.minecraft.item.ShovelItem; import net.minecraft.item.SwordItem; import net.minecraft.item.TieredItem; import net.minecraftforge.event.entity.living.LivingEquipmentChangeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @Mod.EventBusSubscriber(modid = Gielinorcraft.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE) public class EquipmentEventHandler { @SubscribeEvent public static void onWield(LivingEquipmentChangeEvent event) { LivingEntity entity = event.getEntityLiving(); IAttackStyle style = entity.getCapability(AttackStyleCapability.STYLE_CAP).orElse(null); Item to = event.getTo().getItem(); Item from = event.getFrom().getItem(); if(to instanceof TieredItem) { if(event.getSlot() == EquipmentSlotType.OFFHAND && entity instanceof PlayerEntity) { if(entity instanceof ServerPlayerEntity && !(entity.world.isRemote)) { PacketHandler.sendTo(new StringPacket("You cannot wield this item in your offhand."), (ServerPlayerEntity) entity); } } } if(event.getSlot() == EquipmentSlotType.MAINHAND && entity.getHeldItemMainhand().getItem() == to) { if(entity instanceof ServerPlayerEntity && !(entity.world.isRemote)) { for(int i = 0; i < 6; i++) { PacketHandler.sendTo(new StringPacket("Attack Style: " + style.getStyleName(i) + ", " + style.getStyleDescription(i)), (ServerPlayerEntity) entity); } PacketHandler.sendTo(new StringPacket("Active Style: " + style.getActiveStyle().getName() + ", " + style.getActiveStyle().getDescription()), (ServerPlayerEntity) entity); style.sync((ServerPlayerEntity) entity); } if(entity.getHeldItemMainhand().getItem() instanceof SwordItem) { style.setAttackStyle(0, AttackStyles.ACCURATE_STAB); style.setAttackStyle(1, AttackStyles.AGGRESSIVE_STAB); style.setAttackStyle(2, AttackStyles.AGGRESSIVE_SLASH); style.setAttackStyle(3, AttackStyles.DEFENSIVE_STAB); style.setAttackStyle(4, AttackStyles.EMPTY); style.setAttackStyle(5, AttackStyles.EMPTY); }else if(entity.getHeldItemMainhand().getItem() instanceof AxeItem) { style.setAttackStyle(0, AttackStyles.ACCURATE_SLASH); style.setAttackStyle(1, AttackStyles.AGGRESSIVE_SLASH); style.setAttackStyle(2, AttackStyles.AGGRESSIVE_CRUSH); style.setAttackStyle(3, AttackStyles.DEFENSIVE_SLASH); style.setAttackStyle(4, AttackStyles.EMPTY); style.setAttackStyle(5, AttackStyles.EMPTY); }else if(entity.getHeldItemMainhand().getItem() instanceof PickaxeItem) { style.setAttackStyle(0, AttackStyles.ACCURATE_STAB); style.setAttackStyle(1, AttackStyles.AGGRESSIVE_STAB); style.setAttackStyle(2, AttackStyles.AGGRESSIVE_CRUSH); style.setAttackStyle(3, AttackStyles.DEFENSIVE_STAB); style.setAttackStyle(4, AttackStyles.EMPTY); style.setAttackStyle(5, AttackStyles.EMPTY); }else if(entity.getHeldItemMainhand().getItem() instanceof ShovelItem) { style.setAttackStyle(0, AttackStyles.ACCURATE_CRUSH); style.setAttackStyle(1, AttackStyles.AGGRESSIVE_CRUSH); style.setAttackStyle(2, AttackStyles.AGGRESSIVE_SLASH); style.setAttackStyle(3, AttackStyles.DEFENSIVE_CRUSH); style.setAttackStyle(4, AttackStyles.EMPTY); style.setAttackStyle(5, AttackStyles.EMPTY); }else if(entity.getHeldItemMainhand().getItem() instanceof HoeItem) { style.setAttackStyle(0, AttackStyles.ACCURATE_SLASH); style.setAttackStyle(1, AttackStyles.AGGRESSIVE_SLASH); style.setAttackStyle(2, AttackStyles.AGGRESSIVE_STAB); style.setAttackStyle(3, AttackStyles.DEFENSIVE_SLASH); style.setAttackStyle(4, AttackStyles.EMPTY); style.setAttackStyle(5, AttackStyles.EMPTY); }else if(entity.getHeldItemMainhand().getItem() instanceof BowItem || entity.getHeldItemMainhand().getItem() instanceof CrossbowItem) { style.setAttackStyle(0, AttackStyles.RANGED_ACCURATE); style.setAttackStyle(1, AttackStyles.RANGED_RAPID); style.setAttackStyle(2, AttackStyles.RANGED_LONG); style.setAttackStyle(3, AttackStyles.EMPTY); style.setAttackStyle(4, AttackStyles.EMPTY); style.setAttackStyle(5, AttackStyles.EMPTY); }else { style.setAttackStyle(0, AttackStyles.ACCURATE_CRUSH); style.setAttackStyle(1, AttackStyles.AGGRESSIVE_CRUSH); style.setAttackStyle(2, AttackStyles.DEFENSIVE_CRUSH); style.setAttackStyle(3, AttackStyles.EMPTY); style.setAttackStyle(4, AttackStyles.EMPTY); style.setAttackStyle(5, AttackStyles.EMPTY); } } if(from instanceof TieredItem && !(to instanceof TieredItem)) { style.setAttackStyle(0, AttackStyles.ACCURATE_CRUSH); style.setAttackStyle(1, AttackStyles.AGGRESSIVE_CRUSH); style.setAttackStyle(2, AttackStyles.DEFENSIVE_CRUSH); style.setAttackStyle(3, AttackStyles.EMPTY); style.setAttackStyle(4, AttackStyles.EMPTY); style.setAttackStyle(5, AttackStyles.EMPTY); if(entity instanceof ServerPlayerEntity && !(entity.world.isRemote)) { style.sync((ServerPlayerEntity) entity); PacketHandler.sendTo(new StringPacket("Weapon is no longer being wielded."), (ServerPlayerEntity) entity); } } } } Which then sets the Attack style for each slot, done by this capability class: package lk1905.gielinorcraft.capability.attackstyle; import lk1905.gielinorcraft.api.combat.AttackStyles; import lk1905.gielinorcraft.api.combat.IAttackStyles; import lk1905.gielinorcraft.api.events.AttackStyleEvent; import lk1905.gielinorcraft.network.PacketHandler; import lk1905.gielinorcraft.network.attackstyle.AttackStyleCapPacket; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.nbt.CompoundNBT; import net.minecraftforge.common.MinecraftForge; public class AttackStyle implements IAttackStyle{ private final IAttackStyles[] style; private IAttackStyles activeStyle; private final LivingEntity entity; private int activeId; public AttackStyle(LivingEntity entity) { style = new IAttackStyles[6]; this.entity = entity; style[0] = AttackStyles.ACCURATE_CRUSH; style[1] = AttackStyles.AGGRESSIVE_CRUSH; style[2] = AttackStyles.DEFENSIVE_CRUSH; style[3] = AttackStyles.EMPTY; style[4] = AttackStyles.EMPTY; style[5] = AttackStyles.EMPTY; setActiveStyle(0); if(activeStyle == AttackStyles.EMPTY) { setActiveStyle(0); } } @Override public void setAttackStyle(int slot, IAttackStyles style) { if(this.style[slot] != style) { this.style[slot] = style; MinecraftForge.EVENT_BUS.post(new AttackStyleEvent(entity, slot, style)); } } @Override public IAttackStyles getAttackStyle(int slot) { return style[slot]; } @Override public void setActiveStyle(int slot) { activeStyle = style[slot]; activeId = slot; } @Override public IAttackStyles getActiveStyle() { return activeStyle; } @Override public void setStyleName(int slot, String name) { name = style[slot].getName(); } @Override public String getStyleName(int slot) { return style[slot].getName(); } @Override public void setStyleDescription(int slot, String description) { description = style[slot].getDescription(); } @Override public String getStyleDescription(int slot) { return style[slot].getDescription(); } @Override public void setStyleId(int slot, int id) { id = style[slot].getStyleId(); } @Override public int getStyleId(int slot) { return style[slot].getStyleId(); } @Override public int getActiveStyleId() { return activeId; } @Override public LivingEntity getEntity() { return entity; } @Override public CompoundNBT serializeNBT() { CompoundNBT data = new CompoundNBT(); data.putInt("active_style", activeId); return data; } @Override public void deserializeNBT(CompoundNBT data) { setActiveStyle(data.getInt("active_style")); } @Override public void sync(ServerPlayerEntity player) { if(entity instanceof ServerPlayerEntity) { PacketHandler.sendTo(new AttackStyleCapPacket(serializeNBT()), player); } } } Which then runs an AttackStyleEvent (custom event) for each slot: package lk1905.gielinorcraft.api.events; import javax.annotation.Nonnull; import lk1905.gielinorcraft.api.combat.IAttackStyles; import net.minecraft.entity.LivingEntity; import net.minecraftforge.eventbus.api.Event; public class AttackStyleEvent extends Event{ private final LivingEntity entity; private final int slot; private final IAttackStyles style; public AttackStyleEvent(LivingEntity entity, int slot, IAttackStyles style) { this.entity = entity; this.slot = slot; this.style = style; } @Nonnull public LivingEntity getEntity() { return entity; } @Nonnull public int getSlot() { return slot; } public IAttackStyles getStyle() { return style; } } I have an event handler for this event: @SubscribeEvent public static void onAttackStyleChange(AttackStyleEvent event) { if(!event.getEntity().world.isRemote) { PacketHandler.sendTo(new ChangeStylePacket(event.getSlot(), event.getStyle().getStyleId(), event.getStyle().getName(), event.getStyle().getDescription()), (ServerPlayerEntity) event.getEntity()); } } Which runs this packet, which is supposed to sync to the client: package lk1905.gielinorcraft.network.attackstyle; import java.util.function.Supplier; import lk1905.gielinorcraft.capability.attackstyle.AttackStyleCapability; import net.minecraft.client.Minecraft; import net.minecraft.network.PacketBuffer; import net.minecraftforge.fml.network.NetworkEvent; public class ChangeStylePacket { private final int slot; private final int id; private final String name; private final String descript; public ChangeStylePacket(int slot, int id, String name, String descript) { this.slot = slot; this.id = id; this.name = name; this.descript = descript; } public static void encode(ChangeStylePacket msg, PacketBuffer buf) { buf.writeInt(msg.slot); buf.writeInt(msg.id); buf.writeString(msg.name); buf.writeString(msg.descript); } public static ChangeStylePacket decode(PacketBuffer buf) { return new ChangeStylePacket(buf.readInt(), buf.readInt(), buf.readString(), buf.readString()); } public static class Handler{ public static void handle(final ChangeStylePacket msg, Supplier<NetworkEvent.Context> ctx) { ctx.get().enqueueWork(() -> { Minecraft mc = Minecraft.getInstance(); mc.player.getCapability(AttackStyleCapability.STYLE_CAP).ifPresent(cap -> { cap.setStyleId(msg.slot, msg.id); cap.setStyleName(msg.slot, msg.name); cap.setStyleDescription(msg.slot, msg.descript); }); }); ctx.get().setPacketHandled(true); } } } On the client end, I have a gui/screen, that contains buttons for each non-empty slot, which you click to set that slot as "active": package lk1905.gielinorcraft.client.gui.screen; import com.mojang.blaze3d.matrix.MatrixStack; import lk1905.gielinorcraft.Gielinorcraft; import lk1905.gielinorcraft.api.combat.AttackStyles; import lk1905.gielinorcraft.api.skill.ISkills; import lk1905.gielinorcraft.capability.attackstyle.AttackStyleCapability; import lk1905.gielinorcraft.capability.attackstyle.IAttackStyle; import lk1905.gielinorcraft.capability.skill.SkillCapability; import lk1905.gielinorcraft.client.gui.widget.AttackStyleButton; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.StringTextComponent; public class AttackStyleScreen extends Screen{ private Minecraft mc = Minecraft.getInstance(); private final ResourceLocation TEXTURE = new ResourceLocation(Gielinorcraft.MODID, "textures/gui/combat.png"); private AttackStyleButton[] styleButton; private String[] styleName; private PlayerEntity player = mc.player; private ISkills skillCap = player.getCapability(SkillCapability.SKILL_CAP).orElse(null); private IAttackStyle styleCap = player.getCapability(AttackStyleCapability.STYLE_CAP).orElse(null); private final int xSize = 134; private final int ySize = 163; private int guiLeft; private int guiTop; public AttackStyleScreen() { super(new StringTextComponent("Combat styles")); styleButton = new AttackStyleButton[6]; styleName = new String[6]; } @Override public boolean isPauseScreen() { return false; } @Override public void init() { guiLeft = (width - xSize) / 2; guiTop = (height - ySize) / 2; for(int i = 0; i < 6; i++) { if(styleCap.getAttackStyle(i) == AttackStyles.EMPTY) { styleButton[i] = null; styleName[i] = null; }else { styleButton[0] = new AttackStyleButton((width / 2) - 57, height / 2 - 45, 0); styleButton[1] = new AttackStyleButton((width / 2) + 1, height / 2 - 45, 1); styleButton[2] = new AttackStyleButton((width / 2) - 57, height / 2 - 18, 2); styleButton[3] = new AttackStyleButton((width / 2) + 1, height / 2 - 18, 3); styleButton[4] = new AttackStyleButton((width / 2) - 57, height / 2 + 9, 4); styleButton[5] = new AttackStyleButton((width / 2) + 1, height / 2 + 9, 5); styleName[i] = styleCap.getStyleName(i); } if(styleButton[i] != null) { this.addButton(styleButton[i]); } } } @Override public void render(final MatrixStack stack, final int mouseX, final int mouseY, final float partialTicks) { renderBackground(stack); super.render(stack, mouseX, mouseY, partialTicks); stack.push(); stack.scale(1F, 1F, 1F); mc.getTextureManager().bindTexture(TEXTURE); this.blit(stack, guiLeft, guiTop, 0, 0, xSize, ySize); drawCenteredString(stack, font, "Combat level: " + skillCap.getCombatLevel(), width / 2, (height / 2) - 70, 111111); for(int i = 0; i < 6; i++) { if(styleButton[i] != null) { styleButton[i].renderButton(stack, mouseX, mouseY, partialTicks); if(styleButton[i].isHovered()) { this.renderTooltip(stack, new StringTextComponent(styleCap.getStyleDescription(i)), mouseX, mouseY); buttons.clear(); this.init(); } } if(styleName[i] != null) { drawCenteredString(stack, font, styleName[0], width / 2 - 30, height / 2 - 40, 0xFFFFFF); drawCenteredString(stack, font, styleName[1], width / 2 + 29, height / 2 - 40, 0xFFFFFF); drawCenteredString(stack, font, styleName[2], width / 2 - 30, height / 2 - 13, 0xFFFFFF); drawCenteredString(stack, font, styleName[3], width / 2 + 29, height / 2 - 13, 0xFFFFFF); drawCenteredString(stack, font, styleName[4], width / 2 - 30, height / 2 + 14, 0xFFFFFF); drawCenteredString(stack, font, styleName[5], width / 2 + 29, height / 2 + 14, 0xFFFFFF); } } stack.pop(); } } If you need to look at any more classes, my github is here. I know for certain that every thing works server-side, and I know the active slot syncs, as it isn't affected by which style exists in that slot (unless the slot is empty/null, in which it then sets slot 0 as the active slot), but the client-side does not change, the screen's buttons do not update to the new style, it only ever has the default styles set. Is anyone able to see what I'm missing or doing wrong? thanks.
  5. Is there any particular reason why LivingEquipmentChangeEvent is non-cancelable? Like, is it a decision by the Forge devs to make it non-cancelable, or is it to do with how Forge interacts with Minecraft, where some things just can't be cancelled?
  6. I tried that, it made no difference regardless of which line came first.
  7. How do I drop the item without cloning it? I've used Player#dropItem (both methods), and it keeps the original in the offhand slot and drops a copy. I tried using ItemStack#Shrink at the same time, hoping that would destroy the original while still dropping the copy, but that just destroys the original before the copy can be made.
  8. Hi, there are 2 things I want to do: 1. Prevent tiered items from being placed in the offhand slot 2. Prevent armour from being placed in the hotbar How would I go about doing these things?
  9. What exactly do I put in the Button.ITooltip parameter? How do I "give it an Implementation"? I can't find any examples of it actually being used, neither in Vanilla or in other mods.
  10. If I don't have that there, the buttons don't update. Besides, thats not the issue I was asking, the issue is that only the last button hovered over does whats in that statement.
  11. Sorry for the late response, but I found how to make the buttons update. All I had to do was to clear existing buttons and re-run the init, whenever the buttons are hovered over, like this: if(styleButton[i].isHovered()) { this.renderTooltip(stack, new StringTextComponent(styleCap.getStyleDescription(i)), mouseX, mouseY); buttons.clear(); this.init(); } However I still have a problem with that statement, in that it still only works on the last non-null button, and not on any of the previous buttons. Anyone know why the statement would do so? Full class here.
  12. For the "listen to the change" part, there's a mouseClicked method in the Widget class (which the Button class extends from) that I think would do the job, but I'm not sure what the int button parameter does, do you know?
  13. I ended up finding a solution elsewhere for my buttons to display the updated texture on the correct button: package lk1905.gielinorcraft.client.gui.widget; import lk1905.gielinorcraft.Gielinorcraft; import lk1905.gielinorcraft.capability.attackstyle.AttackStyleCapability; import lk1905.gielinorcraft.capability.attackstyle.IAttackStyle; import lk1905.gielinorcraft.network.PacketHandler; import lk1905.gielinorcraft.network.attackstyle.AttackStyleClientPacket; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.widget.button.ImageButton; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.ResourceLocation; public class AttackStyleButton extends ImageButton{ private static int yTex(int slotId) { Minecraft mc = Minecraft.getInstance(); PlayerEntity player = mc.player; IAttackStyle styleCap = player.getCapability(AttackStyleCapability.STYLE_CAP).orElse(null); if(styleCap.getActiveStyleId() == slotId) { return 23; }else { return 0; } } public AttackStyleButton(int xIn, int yIn, int slotId) { super(xIn, yIn, 56, 20, 137, yTex(slotId), 0 , new ResourceLocation(Gielinorcraft.MODID, "textures/gui/combat.png"), (button) -> { PacketHandler.sendToServer(new AttackStyleClientPacket(slotId)); }); } } And yes, the yTex(int slotId) method is static. It doesn't work if not static, and unless you give a specific reason why it shouldn't be static, and a solution that does the above but with a non-static method, its staying static. How do I update the buttons? Is there a method I need to run in the onPress? Or a way to detect a button being pressed in my Screen that can re-render the buttons? Also, my tooltip method still only displays the tooltip for the last button and not any of the previous ones: if(styleButton[i].isHovered()) { this.renderTooltip(stack, new StringTextComponent(styleCap.getStyleDescription(i)), mouseX, mouseY); } I could just hardcode it like this for every button, but I was hoping just the above statement would be able to do it.
  14. Okay, I removed the static from the player and styleCap variables, are you able to help me with the other problems I mentioned?
  15. The screen has 3 buttons, all with a "style id", which, when pressed, sends a packet to set an "active attack style", which is decided by the style id of the button pressed. The buttons are all grey, except for the button with the active style id, which is supposed to turn red, and also make the previously active button grey. The button colours do update, but only if i close/reopen the screen. I would like it to be able to update the colours while the screen is still open. Screen class package lk1905.gielinorcraft.client.gui.screen; import com.mojang.blaze3d.matrix.MatrixStack; import lk1905.gielinorcraft.Gielinorcraft; import lk1905.gielinorcraft.api.combat.AttackStyles; import lk1905.gielinorcraft.api.skill.ISkills; import lk1905.gielinorcraft.capability.attackstyle.AttackStyleCapability; import lk1905.gielinorcraft.capability.attackstyle.IAttackStyle; import lk1905.gielinorcraft.capability.skill.SkillCapability; import lk1905.gielinorcraft.client.gui.widget.AttackStyleButton; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.StringTextComponent; public class AttackStyleScreen extends Screen{ private Minecraft mc = Minecraft.getInstance(); private final ResourceLocation TEXTURE = new ResourceLocation(Gielinorcraft.MODID, "textures/gui/combat.png"); private AttackStyleButton[] styleButton; private String[] styleName; private PlayerEntity player = Minecraft.getInstance().player; private ISkills skillCap = player.getCapability(SkillCapability.SKILL_CAP).orElse(null); private IAttackStyle styleCap = player.getCapability(AttackStyleCapability.STYLE_CAP).orElse(null); private final int xSize = 134; private final int ySize = 163; private int guiLeft; private int guiTop; public AttackStyleScreen() { super(new StringTextComponent("Combat styles")); styleButton = new AttackStyleButton[6]; styleName = new String[6]; } @Override public boolean isPauseScreen() { return false; } @Override public void init() { guiLeft = (width - xSize) / 2; guiTop = (height - ySize) / 2; for(int i = 0; i < 6; i++) { if(styleCap.getAttackStyle(i) == AttackStyles.EMPTY) { styleButton[i] = null; styleName[i] = null; }else { styleButton[0] = new AttackStyleButton((width / 2) - 57, height / 2 - 45, 0); styleButton[1] = new AttackStyleButton((width / 2) + 1, height / 2 - 45, 1); styleButton[2] = new AttackStyleButton((width / 2) - 57, height / 2 - 18, 2); styleButton[3] = new AttackStyleButton((width / 2) + 1, height / 2 - 18, 3); styleButton[4] = new AttackStyleButton((width / 2) - 57, height / 2 + 9, 4); styleButton[5] = new AttackStyleButton((width / 2) + 1, height / 2 + 9, 5); styleName[i] = styleCap.getStyleName(i); } if(styleButton[i] != null) { this.addButton(styleButton[i]); } } } @Override public void render(final MatrixStack stack, final int mouseX, final int mouseY, final float partialTicks) { super.render(stack, mouseX, mouseY, partialTicks); renderBackground(stack); stack.push(); stack.scale(1F, 1F, 1F); mc.getTextureManager().bindTexture(TEXTURE); this.blit(stack, guiLeft, guiTop, 0, 0, xSize, ySize); drawCenteredString(stack, font, "Combat level: " + skillCap.getCombatLevel(), width / 2, (height / 2) - 70, 111111); for(int i = 0; i < 6; i++) { if(styleButton[i] != null) { styleButton[i].renderButton(stack, mouseX, mouseY, partialTicks); if(styleButton[i].isHovered()) { this.renderTooltip(stack, new StringTextComponent(styleCap.getStyleDescription(i)), mouseX, mouseY); } } if(styleName[i] != null) { drawCenteredString(stack, font, styleName[0], width / 2 - 30, height / 2 - 40, Integer.parseInt("FFFFFF", 16)); drawCenteredString(stack, font, styleName[1], width / 2 + 29, height / 2 - 40, Integer.parseInt("FFFFFF", 16)); drawCenteredString(stack, font, styleName[2], width / 2 - 30, height / 2 - 13, Integer.parseInt("FFFFFF", 16)); drawCenteredString(stack, font, styleName[3], width / 2 + 29, height / 2 - 13, Integer.parseInt("FFFFFF", 16)); drawCenteredString(stack, font, styleName[4], width / 2 - 30, height / 2 + 14, Integer.parseInt("FFFFFF", 16)); drawCenteredString(stack, font, styleName[5], width / 2 + 29, height / 2 + 14, Integer.parseInt("FFFFFF", 16)); } } stack.pop(); } } Button class package lk1905.gielinorcraft.client.gui.widget; import lk1905.gielinorcraft.Gielinorcraft; import lk1905.gielinorcraft.capability.attackstyle.AttackStyleCapability; import lk1905.gielinorcraft.capability.attackstyle.IAttackStyle; import lk1905.gielinorcraft.network.AttackStyleClientPacket; import lk1905.gielinorcraft.network.PacketHandler; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.widget.button.ImageButton; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.ResourceLocation; public class AttackStyleButton extends ImageButton{ private static PlayerEntity player = Minecraft.getInstance().player; private static IAttackStyle styleCap = player.getCapability(AttackStyleCapability.STYLE_CAP).orElse(null); private static int yTex = 0; public AttackStyleButton(int xIn, int yIn, int widthIn, int heightIn, int xTexStartIn, int yTexStartIn, int yDiffTextIn, ResourceLocation resourceLocationIn, IPressable onPressIn) { super(xIn, yIn, widthIn, heightIn, xTexStartIn, yTexStartIn, yDiffTextIn, resourceLocationIn, onPressIn); } public AttackStyleButton(int xIn, int yIn, int styleId) { this(xIn, yIn, 56, 20, 137, yTex, 0 , new ResourceLocation(Gielinorcraft.MODID, "textures/gui/combat.png"), (button) -> { PacketHandler.sendToServer(new AttackStyleClientPacket(styleId)); }); if(styleCap.getActiveStyleId() == styleId) { yTex = 23; }else { yTex = 0; } } } I also have another problem which I forgot to mention in the OP, but it actually sets the colour of the next button to red, instead of the button it is supposed to (e.g if button with id 0 is the active id, then button with id 1 is the one thats coloured red, not button 0). Yea, I ended up mostly succeeding at doing this(is in above code in screen class). Although the problem is that only the last button's tooltip gets rendered.
  16. Hi, I have 2 questions: 1. How do i get a gui screen to update instantly? My screens only update when I open/close them, or change the size of the Minecraft window. My in game gui updates instantly, which is what I want my screens to do aswell. 2. I have buttons on this gui that I want to, when hovered over, to display a string/tooltip. There is an ITooltip parameter in the constructor of the Button class, but I'm not sure what to put in there if I just want to display a string. How would I do that? Thanks.
  17. I solved the problem. The problem as that I didn't have the getMaxHealth() method saved within my serializeNBT() method, so the game still thought the value was zero. Saving that value fixed the problem.
  18. I'm trying to modify an entity's max health based on a stat, but either its not working or my client isn't acknowledging the change. The method for the change. Full class here. @Override public void modifyMaxHealth(LivingEntity entity) { if(entity == null) { return; } entity = getEntity(); final float newAmount = getMaxHealth(); final float oldAmount; final UUID MODIFIER_ID = UUID.fromString("d5d0d878-b3c2-469b-ba89-ac01c0635a9c"); final ModifiableAttributeInstance health = entity.getAttribute(Attributes.MAX_HEALTH); final AttributeModifier mod = new AttributeModifier(MODIFIER_ID, "Max Health", newAmount, AttributeModifier.Operation.ADDITION); final AttributeModifier oldMod = health.getModifier(MODIFIER_ID); if(oldMod != null) { health.removeModifier(oldMod); oldAmount = (float) oldMod.getAmount(); }else { oldAmount = 0; } health.applyPersistentModifier(mod); final float amountToHeal = newAmount - oldAmount; if(amountToHeal > 0) { entity.heal(amountToHeal); } } The sync method: @Override public void sync(ServerPlayerEntity player) { if(entity instanceof ServerPlayerEntity) { PacketHandler.sendTo(new SkillsPacket(serializeNBT()), player); if(!player.world.isRemote) { ModifiableAttributeInstance attribute = player.getAttribute(Attributes.MAX_HEALTH); SEntityPropertiesPacket packet = new SEntityPropertiesPacket(player.getEntityId(), Collections.singleton(attribute)); ((ServerWorld) player.getEntityWorld()).getChunkProvider().sendToTrackingAndSelf(player, packet); } } } My player event class: package lk1905.gielinorcraft.events; import lk1905.gielinorcraft.Gielinorcraft; import lk1905.gielinorcraft.api.skill.ISkills; import lk1905.gielinorcraft.capability.skill.SkillCapability; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent.PlayerChangedDimensionEvent; import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; import net.minecraftforge.event.entity.player.PlayerEvent.PlayerRespawnEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @Mod.EventBusSubscriber(modid = Gielinorcraft.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE) public class PlayerEventHandler { @SubscribeEvent public static void onPlayerClone(PlayerEvent.Clone event) { if(!event.isWasDeath()) { return; } ISkills oldSkills = event.getOriginal().getCapability(SkillCapability.SKILL_CAP, null).orElse(null); ISkills newSkills = event.getPlayer().getCapability(SkillCapability.SKILL_CAP, null).orElse(null); if(oldSkills != null) { if(newSkills != null) { for(int i = 0; i < 26; i++) { newSkills.setXp(i, oldSkills.getXp(i)); newSkills.setStaticLevel(i, oldSkills.getStaticLevel(i)); newSkills.setLevel(i, oldSkills.getLevel(i)); } } } } @SubscribeEvent public static void onPlayerChangedDimensionEvent(PlayerChangedDimensionEvent event) { ServerPlayerEntity player = (ServerPlayerEntity) event.getPlayer(); if(!player.world.isRemote) { player.getCapability(SkillCapability.SKILL_CAP).ifPresent(c -> c.sync(player)); player.getCapability(SkillCapability.SKILL_CAP).ifPresent(c -> c.modifyMaxHealth(player)); } } @SubscribeEvent public static void onRespawnEvent(PlayerRespawnEvent event) { ServerPlayerEntity player = (ServerPlayerEntity) event.getPlayer(); if(!player.world.isRemote) { player.getCapability(SkillCapability.SKILL_CAP).ifPresent(c -> c.sync(player)); player.getCapability(SkillCapability.SKILL_CAP).ifPresent(c -> c.modifyMaxHealth(player)); } } @SubscribeEvent public static void onPlayerConnect(PlayerLoggedInEvent event) { ServerPlayerEntity player = (ServerPlayerEntity) event.getPlayer(); if(!player.world.isRemote) { player.getCapability(SkillCapability.SKILL_CAP).ifPresent(c -> c.sync(player)); player.getCapability(SkillCapability.SKILL_CAP).ifPresent(c -> c.modifyMaxHealth(player)); } } } Full repo here, if you need to look at anything else.
  19. I've changed the serializeNBT and deserialize methods so the value of i is in the key: @Override public CompoundNBT serializeNBT() { CompoundNBT data = new CompoundNBT(); for(int i = 0; i < 26; i++) { data.putInt("xp_" + i, (int) xp[i]); data.putInt("dynamic_" + i, dynamicLevels[i]); data.putInt("static_" + i, staticLevels[i]); } return data; } @Override public void deserializeNBT(CompoundNBT data) { for(int i = 0; i < 26; i++) { xp[i] = data.getInt("xp_" + i); dynamicLevels[i] = data.getInt("dynamic_" + i); staticLevels[i] = data.getInt("static_" + i); } } And now it works, thank you! (I think thats what the first person to reply to this post was trying to tell me to do but I didn't understand at the time).
  20. Okay, I believe I've done what you have told me, and my gui does update me gaining xp. However, theres something wrong with my sync method, as whenever it is called, it resets all xp values to zero. So the values in my gui are lost when reloading the world. Heres the sync method in my Skills class: @Override public void sync(ServerPlayerEntity player) { if(entity instanceof ServerPlayerEntity) { PacketHandler.sendTo(new SkillsPacket(serializeNBT()), player); } } Heres my attempt at syncing on login, in my player event handler: @SubscribeEvent public static void onPlayerConnect(PlayerLoggedInEvent event) { ServerPlayerEntity player = (ServerPlayerEntity) event.getPlayer(); if(!player.world.isRemote) { player.getCapability(SkillCapability.SKILL_CAP).ifPresent(c -> c.sync(player)); } } Updated my git repo, here.
  21. Did you mean replace EntityLiving in the Object instanceof part with PlayerEntity? Because I just tried that and it made no difference.
  22. Sorry for the late response. Another stupid question, but how do I set the the entity so that it's not null?
  23. Is that this part? public static void register() { CapabilityManager.INSTANCE.register(ISkills.class, new SkillStorage(), () -> new Skills(null)); } If so, isn't that part supposed to be null? Every other capability I've seen from other people that had an entity/player there had it set to null.
×
×
  • Create New...

Important Information

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