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.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I'm using Modrinth as a launcher for a forge modpack on 1.20.1, and can't diagnose the issue on the crash log myself. Have tried repairing the Minecraft instillation as well as removing a few mods that have been problematic for me in the past to no avail. Crash log is below, if any further information is necessary let me know. Thank you! https://paste.ee/p/k6xnS
    • Hey folks. I am working on a custom "Mecha" entity (extended from LivingEntity) that the player builds up from blocks that should get modular stats depending on the used blocks. e.g. depending on what will be used for the legs, the entity will have a different jump strength. However, something unexpected is happening when trying to override a few of LivingEntity's functions and using my new own "Mecha" specific fields: instead of their actual instance-specific value, the default value is used (0f for a float, null for an object...) This is especially strange as when executing with the same entity from a point in the code specific to the mecha entity, the correct value is used. Here are some code snippets to better illustrate what I mean: /* The main Mecha class, cut down for brevity */ public class Mecha extends LivingEntity { protected float jumpMultiplier; //somewhere later during the code when spawning the entity, jumpMultiplier is set to something like 1.5f //changing the access to public didn't help @Override //Overridden from LivingEntity, this function is only used in the jumpFromGround() function, used in the aiStep() function, used in the LivingEntity tick() function protected float getJumpPower() { //something is wrong with this function //for some reason I can't correctly access the fields and methods from the instanciated entity when I am in one of those overridden protected functions. this is very annoying LogUtils.getLogger().info(String.valueOf(this.jumpMultiplier))) //will print 0f return this.jumpMultiplier * super.getJumpPower(); } //The code above does not operate properly. Written as is, the entity will not jump, and adding debug logs shows that when executing the code, the value of this.jumpMultiplier is 0f //in contrast, it will be the correct value when done here: @Override public void tick() { super.tick(); //inherited LivingEntity logic //Custom logic LogUtils.getLogger().info(String.valueOf(this.jumpMultiplier))) //will print 1.5f } } My actual code is slightly different, as the jumpMuliplier is stored in another object (so I am calling "this.legModule.getJumpPower()" instead of the float), but even using a simple float exactly like in the code above didn't help. When running my usual code, the object I try to use is found to be null instead, leading to a crash from a nullPointerException. Here is the stacktrace of said crash: The full code can be viewed here. I have found a workaround in the case of jump strength, but have already found the same problem for another parameter I want to do, and I do not understand why the code is behaving as such, and I would very much like to be able to override those methods as intended - they seemed to work just fine like that for vanilla mobs... Any clues as to what may be happening here?
    • Please delete post. Had not noticed the newest edition for 1.20.6 which resolves the issue.
    • https://paste.ee/p/GTgAV Here's my debug log, I'm on 1.18.2 with forge 40.2.4 and I just want to get it to work!! I cant find any mod names in the error part and I would like some help from the pros!! I have 203 mods at the moment.
  • Topics

×
×
  • Create New...

Important Information

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