It seems I have been trying to solve this problem for ages. I have a kind of machine gun, and I want it to fire every tick if the right mouse button is down.
I thought I would use .setItemInUse() and check if the item is in use every tick, or use the onUsingItemTick method, wich works well with one or more people on the server (LAN), but this makes the player slow down when firing the gun, like when eating food, using bow etc. And I don't wan that.
So I looked into the minecraft classes and tried methods like:
This worked fine with one player, but with more, strange things happen like when the owner of the server right clicks, everyone else does too, and the other players can't shoot at all.
There seem to be client and server problems here, but I just can't figure out what I should use to detect the player right clicking that will work with multiple players. Here is my onUpdate code:
public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5)
{
Minecraft mc = Minecraft.getMinecraft();
GameSettings settings = mc.gameSettings;
if (par3Entity instanceof EntityPlayer)
{
EntityPlayer player = (EntityPlayer) par3Entity;
if (settings.keyBindUseItem.isPressed() && player.inventory.getCurrentItem() == par1ItemStack && mc.inGameHasFocus)
{
this.shoot(par1ItemStack, par2World, player); // what the gun does when fired
}
}
}
Please help, I have spent hours looking around the web for answers, but I can't find any.
EDIT: onItemRightClick() is fired every 4 ticks, so it is too slow for what I want.
Create server-side TickHandler and use the tickStart method, which fires every tick. However, you will crash unless you you run a check to ensure that you are actually in-game. To do this, enclose all the code in this:
I did that but it doesn't fix my problem. The gun is still not working properly on multiplayer (same behaviour as before). How exactly should I check if the right mouse button is down, and is that my problem?
public class GunTickHandler implements ITickHandler
{
public void tickStart(EnumSet<TickType> type, Object... tickData)
{
if (FMLClientHandler.instance().getClient().currentScreen == null)
{
World world = (World) tickData[0];
Minecraft mc = Minecraft.getMinecraft();
GameSettings settings = mc.gameSettings;
List allPlayers = world.playerEntities;
for (Object playerObj : allPlayers)
{
EntityPlayerMP player = (EntityPlayerMP) playerObj;
ItemStack itemStack = player.inventory.getCurrentItem();
Item item = null;
if (itemStack != null) item = itemStack.getItem();
if (mc.gameSettings.keyBindUseItem.pressed && item instanceof ItemGun && mc.inGameHasFocus)
{
ItemGun itemGun = (ItemGun) item;
itemGun.onGunFired(itemStack, world, player);
}
}
}
}
public void tickEnd(EnumSet<TickType> type, Object... tickData)
{
}
public EnumSet<TickType> ticks()
{
return EnumSet.of(TickType.WORLD);
}
public String getLabel()
{
return "Gun Tick Handler";
}
}
public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer)
{
try{
par1ItemStack.stackTagCompound.getBoolean("using");
}
catch(NullPointerException e)
{
par1ItemStack.stackTagCompound = new NBTTagCompound();
par1ItemStack.stackTagCompound.setBoolean("using", false);
}
if(!par1ItemStack.stackTagCompound.getBoolean("using"))
{
par1ItemStack.stackTagCompound.setBoolean("using", true);
}
else
{
par1ItemStack.stackTagCompound.setBoolean("using", false);
}
}
public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5)
{
if(!par2World.isRemote)
{
if(par1ItemStack.stackTagCompound.getBoolean("using"))
{
this.shoot(par1ItemStack, par2World, player);
}
}
}
That makes it fire constantly every 4 ticks, and then not fire at all for the next 4 ticks. I think I might just have to live with the gun being the itemInUse, and slowing you down. Thanks for the help anyway guys!
I guess you could send a packet once the button is pressed and a new button once it's released.
Making the packets act as start and stop fire triggers?
Thanks to all your help I solved this a couple of days ago. I will put my solution here for anyone else who has the same problem. I made a key handler as an easy way to detect right clicks, and sends packets which cause the gun to shoot. Here is my code:
package mod.elementalguns;
import java.io.IOException;
import mod.elementalguns.item.ItemGun;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet250CustomPayload;
import net.minecraft.world.World;
import cpw.mods.fml.common.network.IPacketHandler;
import cpw.mods.fml.common.network.PacketDispatcher;
import cpw.mods.fml.common.network.Player;
public class GunPacketHandler implements IPacketHandler
{
@Override
public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player)
{
if (packet.channel.equals("GunShoot"))
{
handlePacketKeyPress(packet, (EntityPlayer) player);
}
}
private void handlePacketKeyPress(Packet250CustomPayload packet, EntityPlayer player)
{
if (player.getHeldItem() == null)
{
return;
}
if (player.getHeldItem().getItem() instanceof ItemGun)
{
ItemStack gunStack = player.getHeldItem();
ItemGun gun = (ItemGun) player.getHeldItem().getItem();
World world = player.worldObj;
gun.onGunFired(gunStack, world, player);
}
}
}
Registering the key handler in ClientProxy (Note: it is registered as a tick handler, not a key handler, so that right click is NOT added as a new key binding, which would cause a duplicate right click key binding)
I thought I would use .setItemInUse() and check if the item is in use every tick, or use the onUsingItemTick method, wich works well with one or more people on the server (LAN), but this makes the player slow down when firing the gun, like when eating food, using bow etc. And I don't wan that.
So I looked into the minecraft classes and tried methods like:
This worked fine with one player, but with more, strange things happen like when the owner of the server right clicks, everyone else does too, and the other players can't shoot at all.
There seem to be client and server problems here, but I just can't figure out what I should use to detect the player right clicking that will work with multiple players. Here is my onUpdate code:
Please help, I have spent hours looking around the web for answers, but I can't find any.
EDIT: onItemRightClick() is fired every 4 ticks, so it is too slow for what I want.
and then whatever is in that function should happen when you press or hold right click.
that fires every 4 ticks. I need something that will fire every tick
If you have trouble finding a way to get the Player when changing your code, if memory serves me correct this should be the code to do so:
For the rest of the parameters I am sure you can find their equivalents on your own.
That makes it fire constantly every 4 ticks, and then not fire at all for the next 4 ticks. I think I might just have to live with the gun being the itemInUse, and slowing you down. Thanks for the help anyway guys!
Making the packets act as start and stop fire triggers?
GunKeyHandler.java
GunPacketHandler.java
Registering the key handler in ClientProxy (Note: it is registered as a tick handler, not a key handler, so that right click is NOT added as a new key binding, which would cause a duplicate right click key binding)
And finally, registering the packet handler in your main mod class
This method works perfectly with one or more players, and I hope it helps!