Posted March 18, 20214 yr I’ve made an event so the player can’t damage entities during an attack cooldown, but whenever the player hits during a cooldown, it resets. How can I stop this from happening and make it so the player can’t punch at all?
March 18, 20214 yr Author Here's my code so far: @SubscribeEvent public static void onPlayerHit(final AttackEntityEvent event) { if(event.getPlayer().getCooledAttackStrength(0) < 1.0F) { event.setCanceled(true); } } I want to make it so while on cooldown, the player cannot hit at all. With this code, the player can still hit, but it doesn't do damage to entities. Is there any other event I can use to cancel the left click entirely?
March 19, 20214 yr Author 7 hours ago, diesieben07 said: AttackEntityEvent. However note that if you cancel this, the attack timer will still count on the client. To avoid this, you can additionally cancel InputEvent.ClickInputEvent on the client. That alone is not enough, because it could be easily bypassed using cheating. I tried it, but it doesn't work about half of the time. Is there a way to add some sort of delay between the events so the a value is recorded before onClickEvent is put into action? public static float a = 1; @SubscribeEvent public static void onPlayerHit(final AttackEntityEvent event) { ModClientEvents.a = event.getPlayer().getCooledAttackStrength(0); if(ModClientEvents.a < 1) { event.setCanceled(true); ModClientEvents.a = 1; } } @SubscribeEvent public static void onClickEvent(final InputEvent.ClickInputEvent event) { if(ModClientEvents.a < 1) { event.setCanceled(true); ModClientEvents.a = 1; } } Edited March 19, 20214 yr by BliX5
March 19, 20214 yr Author I tried to fix more of the code, and I got it to work most of the time, but it's still incredibly buggy. ModServerEvents: @Mod.EventBusSubscriber(modid = BotwMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE) public class ModServerEvents { public static float a; @SubscribeEvent public static void onPlayerHit(final AttackEntityEvent event) { ModServerEvents.a = event.getPlayer().getCooledAttackStrength(0); BotwMod.LOGGER.debug(String.valueOf(ModServerEvents.a) + " onPlayerHit"); if(ModServerEvents.a < 1) { event.setCanceled(true); } } @SubscribeEvent public static void onClickEvent(final InputEvent.ClickInputEvent event) { BotwMod.LOGGER.debug(String.valueOf(ModServerEvents.a) + " onClickEvent"); if(ModServerEvents.a < 1) { event.setCanceled(true); } ModServerEvents.a = 1; } } Main Class: MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGHEST, ModServerEvents::onPlayerHit); MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGH, ModServerEvents::onClickEvent);
March 19, 20214 yr Author 7 hours ago, diesieben07 said: You cannot do this. There is more than one player, and this value would be shared between all of them. Additionally, in single player, this value would be shared between client and server thread, without proper synchronization. Additionally, it seems you have not read my message in full. ClickInputEvent is a client-only event. I've moved the ClickInputEvent to my client events and I've fixed the values. The problem now is that the method onClickEvent is running before onPlayerHit, which delays whether the hit is cancelled or not for the next left click, despite how I set the events' priority in my main class.
March 19, 20214 yr Author Main Class: @Mod("botw") public class BotwMod { public static final Logger LOGGER = LogManager.getLogger(); public static final String MOD_ID = "botw"; public BotwMod() { IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); bus.addListener(this::setup); ModBlocks.BLOCKS.register(bus); ModItems.ITEMS.register(bus); ModEntityTypes.ENTITY_TYPES.register(bus); MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGHEST, ModServerEvents::onPlayerHit); MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGH, ModClientEvents::onClickEvent); } private void setup(final FMLCommonSetupEvent event) { DeferredWorkQueue.runLater(() -> { }); } private void doClientStuff(final FMLClientSetupEvent event) { } ModClientEvents: @Mod.EventBusSubscriber(modid = BotwMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT) public class ModClientEvents { public static float a = 1; @SubscribeEvent public static void onClickEvent(InputEvent.ClickInputEvent event) { BotwMod.LOGGER.debug("ModClientEvents"); //used for debugging if(event.isAttack()) { if(ModClientEvents.a < 1) { ModClientEvents.a = 1; event.setCanceled(true); } } } } ModServerEvents: @Mod.EventBusSubscriber(modid = BotwMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE) public class ModServerEvents { @SubscribeEvent public static void onPlayerHit(AttackEntityEvent event) { BotwMod.LOGGER.debug("ModServerEvents"); //used for debugging ModClientEvents.a = event.getPlayer().getCooledAttackStrength(0); } }
March 19, 20214 yr Author I only know the basics of Java, and barely anything about how Forge works. It would be great if you could help me find an alternative instead of listing everything I'm doing wrong.
March 19, 20214 yr Author 20 minutes ago, diesieben07 said: The two events do not need to interact at all. Just cancel both of them when it is relevant. I need the AttackEntityEvent to determine when the player is on attack cooldown or not, unless there is another way to access that.
March 19, 20214 yr Author 15 minutes ago, diesieben07 said: Call getCooledAttackStrength, just like you do in the attack event... How do I call getCooledAttackStrength from the ClickInputEvent?
March 19, 20214 yr Author 2 minutes ago, diesieben07 said: How is the event relevant to how you call a method? Before when I called getCooledAttackStrenght, I was using AttackEntityEvent to call it. @SubscribeEvent public static void onPlayerHit(AttackEntityEvent event) { if(event.getPlayer().getCooledAttackStrength(0) < 1.0F) { event.setCanceled(true); } } I couldn't find a way to call this method again with ClickInputEvent without my game crashing.
March 19, 20214 yr Author 9 minutes ago, diesieben07 said: Show what you tried that crashed the game. @SubscribeEvent public static void onClickEvent(InputEvent.ClickInputEvent event, Entity entityIn) { PlayerEntity player = (PlayerEntity)entityIn; if(event.isAttack()) { if(player.getCooledAttackStrength(0) < 1) { event.setCanceled(true); } } } Pretty sure this doesn't work because events shouldn't have any other parameters, but this is the only way I could think of calling it.
March 19, 20214 yr Author 14 minutes ago, diesieben07 said: ClickInputEvent is a client-side event. The player on the client is Minecraft#player. Would this work? Entity player = Minecraft.getInstance().player;
March 19, 20214 yr Author 4 minutes ago, diesieben07 said: Yes. if(player.getCooledAttackStrength(0) < 1) { event.setCanceled(true); } Doesn't work for me, it doesn't think getCooledAttackStrength exists. What am I missing?
March 19, 20214 yr Author Nevermind, I just needed to replace "Entity" in Entity player = Minecraft.getInstance().player; with PlayerEntity.
March 19, 20214 yr Author Thanks, it works now! Here's my final code: @SubscribeEvent public static void onClickEvent(InputEvent.ClickInputEvent event) { PlayerEntity player = Minecraft.getInstance().player; if(event.isAttack()) { if(player.getCooledAttackStrength(0) < 1) { event.setCanceled(true); } } }
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.