Jump to content

[1.6.4] Handling click events


FBalazs

Recommended Posts

Hi,

 

I'm one of the modders of the Crafting Pillars mod and I'm working on a better interraction handling system.

My problem is that the client side doesn't call the onClick method with LEFT_CLICK_BLOCK event. I want to cancel that event and send a custom packet to the server.

 

My event handler:

@ForgeSubscribe
public void onClick(PlayerInteractEvent event)
{
if(event.entityPlayer.worldObj.isRemote)
{
	if(event.action == Action.LEFT_CLICK_BLOCK) // Never true
	{
		if(doClick(0, event))
			event.setCanceled(true);
	}
	else if(event.action == Action.RIGHT_CLICK_BLOCK) // Works perfectly
	{
		if(doClick(2, event))
			event.setCanceled(true);
	}
	else if(event.action == Action.RIGHT_CLICK_AIR) // Works perfectly
	{
		if(doClick(2, event))
			event.setCanceled(true);
	}
}
}

 

Thanks for your help!

Sorry for my bad English!

FBalazs

Link to comment
Share on other sites

How are you using this? With a tick handler?

Am I right?

protected void copyClickInfoFromOriginal()
  {
    this.pressTime += interceptedKeyBinding.pressTime;
    this.interceptedPressTime += interceptedKeyBinding.pressTime;
    interceptedKeyBinding.pressTime = 0; // this line clears the data from the original binding if I don't do that LEFT_CLICK_BLOCK will be called else it won't be called
    this.pressed = interceptedKeyBinding.pressed;
  }

Sorry for my bad English!

FBalazs

Link to comment
Share on other sites

Hi

 

Yes that's right, I was using this class to capture the left & right clicks when a certain item is being held, and the tick handler was checking the intercepted keyhandler once per tick using .retrieveClick

 

But just to be clear, your code doesn't need to call copyClickInfoFromOriginal itself.  Is is called by the vanilla code (the vanilla code calls isPressed(), which calls copyClickInfoFromOriginal)

 

I'm not sure that the comment you've added in the code is correct.  The vanilla code never sees interceptedKeyBinding.pressTime because the GameSettings.keyBindAttack is pointing to the KeyBindingInterceptor.  To stop the code from receiving left clicks, turn interception on and check for the clicks in your tickhandler using retrieveClick.  When you turn interception off, the clicks go through to the vanilla code again.

 

-TGG

 

 

Link to comment
Share on other sites

Hi

 

I can't get your code to work. I don't think it can clear any key presses.

 

Here's the code. The commented lines are my try.

package me.dawars.CraftingPillars.handlers;

import java.util.EnumSet;

import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;

import me.dawars.CraftingPillars.CraftingPillars;
import me.dawars.CraftingPillars.blocks.BasePillar;
import me.dawars.CraftingPillars.client.KeyBindingInterceptor;
import me.dawars.CraftingPillars.network.packets.PacketClick;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityClientPlayerMP;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
import cpw.mods.fml.common.ITickHandler;
import cpw.mods.fml.common.TickType;

public class TickHandler implements ITickHandler
{
public boolean doClick(int button)
{
	World world = Minecraft.getMinecraft().theWorld;
	EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer;
	for(int x = (int)player.posX-5; x <= (int)player.posX+5; x++)
		for(int y = (int)player.posY-5; y <= (int)player.posY+5; y++)
			for(int z = (int)player.posZ-5; z <= (int)player.posZ+5; z++)
				if(Block.blocksList[world.getBlockId(x, y, z)] instanceof BasePillar)
				{
					int id = ((BasePillar)Block.blocksList[world.getBlockId(x, y, z)]).getClickedButtonId(world, x, y, z, button, player);
					if(id > -1)
					{
						//System.out.println("Packet sent! "+button+" "+id+" "+x+" "+y+" "+z);
						CraftingPillars.proxy.sendToServer(new PacketClick(button, id, x, y, z).pack());
						return true;
					}
				}
	return false;
}

boolean pleft, pright;
GameSettings gs;
KeyBindingInterceptor intLeft, intRight;

public TickHandler()
{
	gs = Minecraft.getMinecraft().gameSettings;
	intLeft = new KeyBindingInterceptor(gs.keyBindAttack);
	intRight = new KeyBindingInterceptor(gs.keyBindUseItem);
	intLeft.setInterceptionActive(true);
	intRight.setInterceptionActive(true);
}

@Override
public void tickStart(EnumSet<TickType> type, Object... tickData)
{
	// This code doesn't clear any presses
	if(intLeft.isKeyDown())
	{
		if(!pleft)
		{
			if(doClick(0))
				pleft = true;
		}

		if(pleft)
			intLeft.retrieveClick();
	}
	else
		pleft = false;

	if(intRight.isKeyDown())
	{
		if(!pright)
		{
			if(doClick(2))
				pright = true;
		}

		if(pright)
			intRight.retrieveClick();
	}
	else
		pright = false;

	// This is my code, it works fine expect the first tick of click
	/*if(gs.keyBindAttack.pressed)
	{
		if(!pleft && doClick(0))
		{
			pleft = true;
			gs.keyBindAttack.pressed = false;
		}
	}
	else
	{
		pleft = false;
	}

	if(gs.keyBindUseItem.pressed)
	{
		System.out.println("right");
		if(!pright && doClick(2))
		{
			pright = true;
			gs.keyBindUseItem.pressed = false;
		}
	}
	else
	{
		pright = false;
	}*/
}

@Override
public void tickEnd(EnumSet<TickType> type, Object... tickData)
{

}

@Override
public EnumSet<TickType> ticks()
{
	return EnumSet.of(TickType.CLIENT);
}

@Override
public String getLabel()
{
	return CraftingPillars.name+" TickHandler";
}
}

 

I want to clear the keypress when i can handle it so no vanilla click packets will be send to the server. In my code it is done but the first tick. What am i doing wrong?

Sorry for my bad English!

FBalazs

Link to comment
Share on other sites

Hi

 

Try this....

 

	public TickHandler()
{
	gs = Minecraft.getMinecraft().gameSettings;
	intLeft = new KeyBindingInterceptor(gs.keyBindAttack);
	intRight = new KeyBindingInterceptor(gs.keyBindUseItem);
gs.keyBindAttack = intLeft;
gs.keyBindUseItem = intRight;

	intLeft.setInterceptionActive(true);
	intRight.setInterceptionActive(true);
}

 

This replaces the vanilla key bindings with the interceptor, which will stop the vanilla code from receiving any keypresses while the interception is active, and will also keep the intLeft and intRight updated with the latest keypresses.

 

If you're just interested in clicks (rather than the user holding the button down), then all you need is

if (intLeft.retrieveClick()) {  // left was clicked

you don't need to use isKeyDown().

 

But just to be clear - do you need to stop the vanilla code from receiving the clicks?  or do you just want to tell when the user has clicked so you can do something extra?

 

-TGG

 

 

 

 

 

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



×
×
  • Create New...

Important Information

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