Posted December 16, 201410 yr I have been looking through the events that forge and fml add and I noticed an event that gets called every tick that the player is using an item but I didn't find one that gets called every tick the player is attempting to break a block. If you subscribe to PlayerInteractEvent it gets called once at the initial interaction. I also tried cancelling the interaction so that the player fails at attempting to harvest the block right away. If anyone has any ideas for how-else I would damage the player if he tries to harvest a block without a tool in his hand? code: @SubscribeEvent(priority = EventPriority.HIGHEST) public void playerBlockPunch(PlayerInteractEvent event) { if (event.action == PlayerInteractEvent.Action.LEFT_CLICK_BLOCK) { System.out.println("check"); EntityPlayer player = event.entityPlayer; int x = event.x; int y = event.y; int z = event.z; Block block = event.world.getBlock(x, y, z); Material material = block.getMaterial(); ItemStack itemstack = player.getCurrentEquippedItem(); if (itemstack == null || itemstack.getItem().isItemTool(itemstack)) { if (material == Material.wood || material == Material.anvil || material == Material.rock || material == Material.iron) { player.attackEntityFrom(DamageSource.magic, 2.0F); } } } } Also I apologize if I didn't follow any proper convention, first post
December 16, 201410 yr Author Currently the player takes the damage specified once at the beginning of attempting to harvest the block. If you continue to hold the mouse button you can continue to harvest the block with no further negative effects. I figured out that there are harvest events in the playerevent class that I could subscribe to that would produce the same end goal however I still think continuous damage while punching a block with a bare hand would be the most realistic.
December 16, 201410 yr I'd recommend that using BreakEvent, you deal damage to the player when the block breaks. Also, create your own damage source. Maker of the Craft++ mod.
December 16, 201410 yr He wants to deal damage over time (during hitting), not on start or break - that would be easy. And here is the problem - there are no (I belive so) events that support this kind of actions. From docs: /** * PlayerInteractEvent is fired when a player interacts in some way. * <br> * This event is fired whenever a player interacts in * Minecraft#func_147121_ag(), * NetHandlerPlayServer#processPlayerBlockPlacement(C08PacketPlayerBlockPlacement), * ItemInWorldManager#activateBlockOrUseItem(EntityPlayer, World, ItemStack, int, int, int, int, float, float, float), * ItemInWorldManager#onBlockClicked(int, int, int, int). <br> * <br> * This event is fired via the {@link ForgeEventFactory#onPlayerInteract(EntityPlayer, Action, int, int, int, int)}. * <br> * {@link #action} contains the Action the player performed durin this interaction. <br> * {@link #x} contains the x-coordinate of where this event occurred. <br> * {@link #y} contains the y-coordinate of where this event occurred. <br> * {@link #z} contains the z-coordinate of where this event occurred. <br> * {@link #face} contains the face of the block that was interacted with. <br> * {@link #world} contains the world in which this event is occurring. <br> * <br> * This event is {@link Cancelable}.<br> * If this event is canceled, the player does not interact.<br> * <br> * This event does not have a result. {@link HasResult}<br> * <br> * This event is fired on the {@link MinecraftForge#EVENT_BUS}. **/ The Minecraft#func_147121_ag() is responsible for sending updatePacket, sadly this is a one-time action, so there is no way to make something like you want. I've been trying to figure out some other way - If you can track start, you just need to track stop to know when to deal damage, but then again - there is no event (couldn't find) that tells you that the action has been halted - the PlayerInteractEvent is sent from client to server, and client doesn't get any feedback regarding what happens with certain action next. It's being handled by code that has no event hooks. This is probably possible (somehow), at this moment I am thinking of 2 tickers - one server side, one client side, both start with interactionEvent. Server side deals damage over ticks, problem is you will have to stop this ticker - that would require you to know when player stops hitting particular block. Idk if server knows if you stopped hitting, but client certainly does: PlayerControllerMP.isHittingBlock; It's private so you will have to unlock it with reflection. So the ticker on client side would be checking (client-side) if this field is still true, if not, it woudl send packet to server that player stopped hitting and therefore the server-side ticker could be stopped. This is literally ridiculus (might be buggy, would need some checks and is unsafe), but should work. HOPEFULLY there is other way around that i don't know #ForgeMastersAssemble (diesieben probably knows better answer- always does, I am just idea-dropper) P.S - As I am reading code, this idea (above) looks almost exacly like the thing mc itself is doing, notice: PlayerControllerMP#clickBlock() Edit: Again, digging deeper: (looks kinda useful, I am just pointing random stuff to help searching) /** * Processes the player initiating/stopping digging on a particular spot, as well as a player dropping items?. (0: * initiated, 1: reinitiated, 2? , 3-4 drop item (respectively without or with player control), 5: stopped; x,y,z, * side clicked on;) */ void processPlayerDigging(C07PacketPlayerDigging p_147345_1_); 1.7.10 is no longer supported by forge, you are on your own.
December 16, 201410 yr Author Thanks very much for your help Ernio. I will readily admit that I am incapable of modding at very advanced levels so the client-server ticker would be beyond me. I did manage to get it to work though. I tested other ways I could go about just preventing the block from dropping and came across the BreakSpeed event in PlayerEvent. Not only can I make the player punch much slower but it also continuously fires as well as gives me access to EntityPlayer. I haven't really touched the logic yet but here is the event: @SubscribeEvent(priority = EventPriority.HIGHEST) public void playerBlockDropCheck(PlayerEvent.BreakSpeed event) { EntityPlayer player = event.entityPlayer; Block block = event.block; Material material = block.getMaterial(); ItemStack itemstack = player.getCurrentEquippedItem(); if (itemstack == null || !itemstack.getItem().isItemTool(itemstack)) { if (material == Material.wood || material == Material.anvil || material == Material.rock || material == Material.iron) { player.attackEntityFrom(DamageSource.magic, 2.0F); event.newSpeed = 0.1F; } } }
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.