Jump to content

LK1905

Members
  • Posts

    46
  • Joined

  • Last visited

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

LK1905's Achievements

Tree Puncher

Tree Puncher (2/8)

0

Reputation

  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?
×
×
  • Create New...

Important Information

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