Jump to content

[1.7.10] PlayerInteractEvent limitations?


VapourDrive

Recommended Posts

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 :)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 :P #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.

Link to comment
Share on other sites

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;
		}
	}
    }

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

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