Jump to content

Recommended Posts

Posted

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

Posted

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

Posted

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

 

 

Posted

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

Posted

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

 

 

 

 

 

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

    • Please read the FAQ and post logs as described there.
    • Upon starting the server I get; [main/ERROR] [minecraft/Main]: Failed to start the minecraft server net.minecraftforge.fml.LoadingFailedException: Loading errors encountered: [     Framework (framework) has failed to load correctly §7java.lang.NoClassDefFoundError: net/minecraft/client/gui/components/toasts/Toast ] I suspect there is a (possibly a few) client-only mods installed on my server. Any help would be appreciated! (Yes I know there are a lot of mods...) Here is the crash log:   https://paste.ee/p/pRz5mhMl#s=0
    • That's basically what the failure does, my apologies for failing to specify.  It just tries again on the next tick until it detects the entities for that chunk are loaded, and then tries to load the entity.  From there it gets into different failure states depending on what goes wrong, but in short, if the entity fails to load once the entity list becomes available, the request is cleared and must be resubmitted by the end user.  There should be few cases where that actually happens. Yes, that is my understanding of forceloading.  That's why on a successful summon, it removes the forceload.  Otherwise it does just leave the chunks loaded long term. Thank you for your help, any knowledge is useful!  I don't often mess with forceloading and my prior experience is 1.16 so I'm also a bit out of my depth haha.
    • I will have to do more research about 1.18 chunk loading. You were unclear about how your code manages with the entity load failure. If you simply used a loop, I suggest submitting a tick task to the next tick which does the same thing, checking if the entities are loaded and if so teleporting the right one else submitting another tick task etc. Also I think forceloading permanently force loads the chunk, and it only starts to unload when you make a subsequent call to mark the chunk as not forceloaded. I may be completely wrong, I dont know much about 1.18, most of my experience is 1.20. Good luck I hope you figure it out after all this time 😅
    • i managed to fix it by reinstalling the modpack and re-add all the extra mods I've had previously.
  • Topics

  • Who's Online (See full list)

    • There are no registered users currently online
×
×
  • Create New...

Important Information

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