Jump to content

Recommended Posts

Posted

I am currently working on a mod that needs to use the right click as a keybind as well. I was wondering if there was a way to do this and still retain the vanilla keybind for right click. At the moment mine is taking priority and the vanilla no longer works. Note that this has to be done with a custom keybind instead of onItemRightClick due to a few issues. Thanks to everyone who reads and even more to replies!

Posted

Well if I pull it directly from vanilla then there are limitations on it such as how fast the key is fired which will not work for me. I need the key to fire every time the server ticks and the key is held which is the way it is set up now.

Posted

Use MouseEvent - it is fired every time a mouse button is clicked, but keep in mind that keys are all handled only on the client side; you cannot check if a key is pressed on the server without sending a packet. Also note that if you need the key to be keyBindUseItem and not just right click, if the player changes the keybinding then MouseEvent may not be the perfect solution.

 

If you just want to know if the key is held down, you can use KeyBinding#pressed or KeyBinding#isPressed() at any time (on the CLIENT, checking for KeyBinding Minecraft.getMinecraft().gameSettings.keyBindUseItem).

 

pressed returns true only when the key is actually held down; isPressed() can return true for a number of ticks after it is released.

Posted

Hi

 

This link might help a bit

http://greyminecraftcoder.blogspot.com/2013/10/user-input.html

 

You have to be careful with isPressed(), it is poorly named. 

.isPressed() which returns true if the key has been pressed.  It should really be called retrieveKeyPress() or similar:  KeyBinding counts the number of times that user pushes a key, i.e. pressing and holding for 2 seconds still only counts as a single push.  Each time isPressed is called, it decreases this count by one.  (A better name for  .pressTime would be .pressCount, similarly.onTick() would better be called incrementPressCount() ).

 

just read .pressed instead (is true if this key is being held down)

 

Perhaps you could describe in more detail what you're trying to do.  It is possible to get more control over right clicking, but it is complicated and a bit of a hack, and might not be necessary for you.

 

-TGG

Posted

You guys don't seem to understand what I am saying for some reason so let me try again.

I need my keybind to work with the vanilla keybind. They BOTH need to be right click. At the moment mine overrides the vanilla one and the vanilla right click no longer works.

I have to have my own keybind because minecraft has a limit on how many times the key is fired.

Posted

Use MouseEvent - it is fired every time a mouse button is clicked, but keep in mind that keys are all handled only on the client side; you cannot check if a key is pressed on the server without sending a packet. Also note that if you need the key to be keyBindUseItem and not just right click, if the player changes the keybinding then MouseEvent may not be the perfect solution.

 

If you just want to know if the key is held down, you can use KeyBinding#pressed or KeyBinding#isPressed() at any time (on the CLIENT, checking for KeyBinding Minecraft.getMinecraft().gameSettings.keyBindUseItem).

 

pressed returns true only when the key is actually held down; isPressed() can return true for a number of ticks after it is released.

 

Nevermind everyone, I fixed it! Thanks you tons coolAlias! This has solved my problem and has done exactly what I needed it to do!

Posted

You can't spawn entities from a keybind without sending a packet. Keys (and mouse) events ONLY happen on the client; EntityPlayerMP is the server version of the player, but you can't get it on the client. Packets packets packets.

 

Btw, you mentioned you are still using a key binding? You shouldn't need to have a custom keybinding - you can simply check if the vanilla keyBindUseItem (i.e. right mouse button) is pressed. It's already a keybinding.

Posted

You can't spawn entities from a keybind without sending a packet. Keys (and mouse) events ONLY happen on the client; EntityPlayerMP is the server version of the player, but you can't get it on the client. Packets packets packets.

 

Btw, you mentioned you are still using a key binding? You shouldn't need to have a custom keybinding - you can simply check if the vanilla keyBindUseItem (i.e. right mouse button) is pressed. It's already a keybinding.

 

Not anymore, I am now using the vanilla keybind. Could you help me out on how to handle it for the server however? I currently have it set up to send a packet to my packet handler which then goes into my ItemGun class, in there I have a method that spawns the entity. It works perfectly client side but not server side. Here is some code to help you understand what i'm talking about.

 

 public static void shootBullet(EntityPlayerMP player, boolean explosion, float explosiondamage, int speed, boolean flare
	    		, double damage, int knockback, boolean singleShot, String shot){
	    	
			    	World world = player.worldObj;
			    	
	            	Random rand = new Random();
	            	int i = rand.nextInt(100) + 1;
	            	
	            	boolean b;
	            	if(i < 3){
	            		b = true;
	            		world.spawnParticle("smoke", player.posX, player.posY, player.posZ, 0, 0.1, 0);
	            	}else{
	            		b = false;
	            	}
			    	
			    	if(!hasFired){
				    	EntityBullet bullet = new EntityBullet(world, player, speed * 2.0F);{
							bullet.explosion = explosion;
							bullet.ExplosionDamage = explosiondamage;
							bullet.speed = speed;
							bullet.setFlare = flare;
							bullet.canBePickedUp = 0;
							bullet.damage = damage;
							bullet.setKnockbackStrength(knockback);
							world.spawnEntityInWorld(bullet);
							if(singleShot){
								hasFired = true;
							}
							player.getCurrentEquippedItem().damageItem(1, player);
							gunTick = ClientTickHandler.tick;
						}	
	    		}
	    }

 

Posted

Can you post your packet class?

 

A few notes:

1. It's usually better to use a more generic class in your method parameters, such as EntityPlayer - EntityPlayerMP is only for the server, but is still an instance of EntityPlayer

2. Particles will not spawn on the server; you need the method to run on both sides, reinforcing point 1

3. Why not just use the regular Item#onItemRightClick method? For example, in your packet class:

// or whatever method you use, but it should only be handled server side
handleServerSide(EntityPlayer player) {
ItemStack stack = player.getHeldItem();
if (stack != null && stack.getItem() instanceof YourGunItem) {
((YourGunItem) stack.getItem()).onItemRightClick(stack, player, player.worldObj);
}
}

Be sure to call the onItemRightClick method on the client side from the mouse click as well. Then you can move all your code to the non-static Item method, and use "if (world.isRemote)" to determine which side you are on:

if (world.isRemote) {
// spawn particles
} else {
// spawn bullet
}

Posted

Here is my packet handler class. Like I have said above, I cannot use onItemRightClick because they limit the amount of times that it is fired, the way that I have mine set up it will fire 100 times a second which is the exact amount needed.

 

package com.Cyphereion.CyphereionsRetribution.Packet;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;

import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet250CustomPayload;

import com.Cyphereion.CyphereionsRetribution.Item.ItemGun;

import cpw.mods.fml.common.network.IPacketHandler;
import cpw.mods.fml.common.network.Player;

public class PacketHandler implements IPacketHandler {

        @Override
        public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player playerEntity) {
        	if(packet.channel.equals("C.R.")){
        		EntityPlayerMP player = (EntityPlayerMP)playerEntity;
        		handlePacket(packet, player);
        	}
        }
        
        private void handlePacket(Packet250CustomPayload packet, EntityPlayerMP player) {
        	DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data));
            int data = 0;
            int id = 0;
            
            try{
            	data = inputStream.readInt();
            	id = inputStream.readInt();
            }catch(IOException e){
            	e.printStackTrace();
            }
            
            if(id == 0){
            	ItemGun.reload(player, data);
            }
            if(id == 1){
            	ItemGun.secondaryFire(player, data);
            }
            if(id == 2){
            	ItemGun.shoot(player, data);
            }
        }
}

Posted

100 times per second!  Yikes!

 

Perhaps you should rethink your approach, there is no way you can accurately send 100 packets per second over a network. 

Luckily there's no need!  All you need to tell the server is when the stream of bullets starts, and when it finishes (i.e. when the user clicks down, and when they click up).  No need to send a packet for each one.

Likewise, no human will notice the difference between a mouse click that lasts for 0.10 seconds and 0.11 seconds.  Will it really affect affect your gameplay if you "only" check for mouse click / keypresses 20 times per second instead of 100?

 

I also think that creating 100 entities per second is going to create ridiculous lag - imagine a single server with (say) 4 players firing at the same time - that's 400 entities per second, each sent to 4 clients, a total of 1600 entity updates over the network every time they move.

 

What I'd suggest instead is that you forget entirely about creating bullets as entities.  Let each client render the bullets as "fake" entities (similar to particle effects), and all the server needs to do is tell each client where the stream of bullets starts and when it finishes.  The server does some basic hit calculations based on the straight line path of each bullet, and applies the appropriate damage.  The client does the same calculations for the purposes of rendering the bullets and any hit effects (like ricochet sounds or puffs of dust or whatever).

 

-TGG

 

Posted

Exactly what TGG said, not to mention that every entity, when hurt, becomes temporarily resistant to damage for roughly one second (or maybe 1/2, can't recall exactly). Anyway, the point being that the vast majority of your machine gun bullets would be wasted even if you could manage to do it exactly how you wanted, which is not a good idea. Try what TGG suggests.

Posted

Exactly what TGG said, not to mention that every entity, when hurt, becomes temporarily resistant to damage for roughly one second (or maybe 1/2, can't recall exactly). Anyway, the point being that the vast majority of your machine gun bullets would be wasted even if you could manage to do it exactly how you wanted, which is not a good idea. Try what TGG suggests.

 

It does not fire every 100 times a second, I meant the keybind will be fired every fired 100 times a second. I am using this as a limiter to how often the bullets can be shot.

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.