Jump to content

Recommended Posts

Posted (edited)

Hello, I have tried creating guns with different firemodes, but I have noticed some problems:

1) For Single firemode I have to right click the weapon twice for it to shoot (So far it looks like problem with maxItemUseDuration + onUsingTick methods)

2) For Auto firemode as soon as I start shooting I can't stop it until I switch the items in hands

 

The code for the methods is here: (Also it might be a bit messy since I was trying to quickly fix it)

Spoiler

	@Override
	public void onUsingTick(ItemStack stack, EntityLivingBase entity, int count)
	{
		if(ConfigHandler.enableGuns)
		{
			EntityPlayer player = (EntityPlayer)entity;
			
			if(this.getFiremode() == Firemode.AUTO && stack.getItemDamage() < stack.getMaxDamage() || player.capabilities.isCreativeMode)
			{
				CooldownTracker tracker = player.getCooldownTracker();
				
				if(!tracker.hasCooldown(stack.getItem()))
				{
					tracker.setCooldown(stack.getItem(), getFireRate());
					shoot(player.world, player, stack);
				}
			}
			
			else
			{
				return;
			}
		}
	}
	
	@Override
	public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn)
	{
		ItemStack stack = playerIn.getHeldItem(handIn);
		
		if(ConfigHandler.enableGuns)
		{
			if(!playerIn.getDataManager().get(ServerSideEvents.RELOADING))
			{	
				if(hasAmmo(playerIn, stack) || playerIn.capabilities.isCreativeMode)
				{	
					CooldownTracker tracker = playerIn.getCooldownTracker();
					if(playerIn.isHandActive())
					{
						return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack);
					}
					if(!tracker.hasCooldown(stack.getItem()))
					{
						playerIn.setActiveHand(handIn);
						tracker.setCooldown(stack.getItem(), getFireRate());
						shoot(worldIn, playerIn, stack);
						return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack);
					}
				}
				else
				{
					worldIn.playSound(playerIn, playerIn.posX, playerIn.posY, playerIn.posZ, SoundEvents.BLOCK_DISPENSER_FAIL, SoundCategory.BLOCKS, 2.0f, 0.0f);
				}
			}
			
			else
			{
				if(hasAmmo(playerIn, stack))
				{
					if(playerIn.isHandActive())
					{
						return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack);
					}
					
					playerIn.getDataManager().set(ServerSideEvents.RELOADING, false);
					PacketHandler.INSTANCE.sendToServer(new PacketReload(false));
				}
			}
		}
		
		else
		{
			if(!worldIn.isRemote)
			{
				playerIn.sendMessage(new TextComponentString(TextFormatting.RED + "Weapons are disabled! You have to enable them in pubgmc.cfg in your minecraft config folder!"));
			}
		}
		
		return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack);
	}

 

Max item use duration is set to 7200

 

The rest of the class is here just in case:

Spoiler

	public enum Firemode
	{
		SINGLE, BURST, AUTO;
	}
	
	public enum ReloadType
	{
		MAGAZINE, SINGLE, KAR98K;
	}
	
	public enum GunType
	{
		PISTOL, SHOTGUN, SMG, AR, LMG, DMR, SR;
	}
	
/** ====================================================================[Basic gun functions]================================================================================== **/
	
	@Override
	public int getMaxItemUseDuration(ItemStack stack)
	{
		return 7200;
	}
	
	@Override
	public boolean onEntitySwing(EntityLivingBase entityLiving, ItemStack stack)
	{
		EntityPlayer player = (EntityPlayer)entityLiving;
		if(player.world.isRemote)
		{
			if(!player.getDataManager().get(ServerSideEvents.AIMING) && !player.getDataManager().get(ServerSideEvents.RELOADING))
			{
				player.getDataManager().set(ServerSideEvents.AIMING, true);
				PacketHandler.INSTANCE.sendToServer(new PacketAim(true));
			}
			
			else
			{
				player.getDataManager().set(ServerSideEvents.AIMING, false);
				PacketHandler.INSTANCE.sendToServer(new PacketAim(false));
			}
		}
		return true;
	}
	
	@Override
	public void onUsingTick(ItemStack stack, EntityLivingBase entity, int count)
	{
		if(ConfigHandler.enableGuns)
		{
			EntityPlayer player = (EntityPlayer)entity;
			
			if(this.getFiremode() == Firemode.AUTO && stack.getItemDamage() < stack.getMaxDamage() || player.capabilities.isCreativeMode)
			{
				CooldownTracker tracker = player.getCooldownTracker();
				
				if(!tracker.hasCooldown(stack.getItem()))
				{
					tracker.setCooldown(stack.getItem(), getFireRate());
					shoot(player.world, player, stack);
				}
			}
			
			else
			{
				return;
			}
		}
	}
	
	@Override
	public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn)
	{
		ItemStack stack = playerIn.getHeldItem(handIn);
		
		if(ConfigHandler.enableGuns)
		{
			if(!playerIn.getDataManager().get(ServerSideEvents.RELOADING))
			{	
				if(hasAmmo(playerIn, stack) || playerIn.capabilities.isCreativeMode)
				{	
					CooldownTracker tracker = playerIn.getCooldownTracker();
					if(playerIn.isHandActive())
					{
						return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack);
					}
					if(!tracker.hasCooldown(stack.getItem()))
					{
						playerIn.setActiveHand(handIn);
						tracker.setCooldown(stack.getItem(), getFireRate());
						shoot(worldIn, playerIn, stack);
						return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack);
					}
				}
				else
				{
					worldIn.playSound(playerIn, playerIn.posX, playerIn.posY, playerIn.posZ, SoundEvents.BLOCK_DISPENSER_FAIL, SoundCategory.BLOCKS, 2.0f, 0.0f);
				}
			}
			
			else
			{
				if(hasAmmo(playerIn, stack))
				{
					if(playerIn.isHandActive())
					{
						return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack);
					}
					
					playerIn.getDataManager().set(ServerSideEvents.RELOADING, false);
					PacketHandler.INSTANCE.sendToServer(new PacketReload(false));
				}
			}
		}
		
		else
		{
			if(!worldIn.isRemote)
			{
				playerIn.sendMessage(new TextComponentString(TextFormatting.RED + "Weapons are disabled! You have to enable them in pubgmc.cfg in your minecraft config folder!"));
			}
		}
		
		return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack);
	}
	
	/**
	 * Used to spawn bullet entity
	 * 
	 * @param world
	 * @param player
	 * @param stack
	 */
	public void shoot(World world, EntityPlayer player, ItemStack stack)
	{
        if(this.hasAmmo(player, stack) || player.capabilities.isCreativeMode && !player.getDataManager().get(ServerSideEvents.RELOADING))
        {
        	if(!world.isRemote)
        	{
                EntityBullet bullet = new EntityBullet(world, player, this);
                world.spawnEntity(bullet);
                if(!player.capabilities.isCreativeMode)
                {
                    stack.damageItem(1, player);
                }
        	}
        	
        	applyRecoil(player);
            world.playSound(player.posX, player.posY, player.posZ, SoundEvents.ENTITY_GHAST_SHOOT, SoundCategory.HOSTILE, 50.0f, 0.0f, true);
        }
        	
        if(stack.getItemDamage() == maxAmmo && !player.getDataManager().get(ServerSideEvents.RELOADING) && !player.capabilities.isCreativeMode)
        {	
        	if(world.isRemote)
        	{
        		
        	}
        }
	}
	
	/**
	 * Call only client side!
	 * @param gun
	 * @param playerIn
	 */
	public void applyRecoil(EntityPlayer playerIn)
	{
		Random rand = new Random();
		//check server side TODO
		//Set horizontal recoil based on if player is sneaking or not
		if(playerIn.isSneaking())
		{
			playerIn.rotationPitch = playerIn.rotationPitch - ((getVerticalRecoil() * (float)rand.nextDouble() * 1.5f) * 0.9f);
		}
		else
		{
			playerIn.rotationPitch = playerIn.rotationPitch - (getVerticalRecoil() * (float)rand.nextDouble() * 1.5f);
		}
		
		//set horizontal recoil (50% to go right and 50% to go left)
		if(Math.random() * 100 <= 50)
		{
			playerIn.rotationYaw = playerIn.rotationYaw - (getHorizontalRecoil() * (float)rand.nextDouble() * 1.5f);
		}
		
		else
		{
			playerIn.rotationYaw = playerIn.rotationYaw + (getHorizontalRecoil() * (float)rand.nextDouble() * 1.5f);
		}
	}
	
	@Override
	public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) 
	{
		return false;
	}
	
	public Firemode getNextFiremode(EntityPlayer player)
	{
		switch(this.getFiremode())
		{
			case SINGLE: 
			{
				if(canGunBurstFire())
				{
					return setFiremode(Firemode.BURST);
				}
				
				else
				{
					return setFiremode(Firemode.AUTO);
				}
			}
			
			case BURST:
			{
				if(canGunAutofire())
				{
					return setFiremode(Firemode.AUTO);
				}
				
				else
				{
					return setFiremode(Firemode.SINGLE);
				}
			}
			
			case AUTO: return setFiremode(Firemode.SINGLE);
		}
		PacketHandler.INSTANCE.sendToServer(new PacketFiremode(firemode));
		return firemode;
	}
	
	public boolean hasAmmo(EntityPlayer player, ItemStack itemStack)
	{
		return itemStack.getItemDamage() < maxAmmo;
	}
	
	public String descAmmoType()
	{
		switch(this.getAmmoType())
		{
			case AMMO9MM: return I18n.format("ammo.9mm");
			case AMMO12G: return I18n.format("ammo.12g");
			case AMMO45ACP: return I18n.format("ammo.45acp");
			case AMMO556: return I18n.format("ammo.556mm");
			case AMMO762: return I18n.format("ammo.762mm");
			case AMMO100M: return I18n.format("ammo.100m");
			case FLARE: return I18n.format("ammo.flare");
			default: return "Unknown ammo";
		}
	}
	
	public String getFiremodeTranslation()
	{
		switch(this.getFiremode())
		{
			case SINGLE: return I18n.format("gun.firemode.single");
			case BURST: return I18n.format("gun.firemode.burst");
			case AUTO: return I18n.format("gun.firemode.auto");
			default: return "";
		}
	}
	
	@Override
	public void addInformation(ItemStack stack, World worldIn, List<String> tooltip, ITooltipFlag flagIn) 
	{
		ammo = maxAmmo - stack.getItemDamage();
		
		tooltip.add(TextFormatting.BOLD + I18n.format("gun.desc.ammo") + ": " + TextFormatting.RESET + "" + TextFormatting.RED + this.ammo);
		tooltip.add(TextFormatting.BOLD + I18n.format("gun.desc.firemode") + ": " + TextFormatting.RESET + "" + TextFormatting.GRAY + getFiremodeTranslation());
		
		if(GuiScreen.isShiftKeyDown())
		{
			DecimalFormat f = new DecimalFormat("###.##");
			DecimalFormat g = new DecimalFormat("###.###");
			tooltip.add(TextFormatting.BOLD + I18n.format("gun.desc.damage") + ": " + TextFormatting.RESET + "" + TextFormatting.DARK_RED + this.getDamage());
			tooltip.add(TextFormatting.BOLD + I18n.format("gun.desc.reloadtime") + ": " + TextFormatting.RESET + "" + TextFormatting.GREEN + reloadTime / 20 + " " + I18n.format("gun.reloadtime.info"));
			tooltip.add(TextFormatting.BOLD + I18n.format("gun.desc.velocity") + ": " + TextFormatting.RESET + "" + TextFormatting.BLUE + f.format(velocity * 5.5) + " " + I18n.format("gun.velocity.info"));
			tooltip.add(TextFormatting.BOLD + I18n.format("gun.desc.gravity") + ": " + TextFormatting.RESET + "" + TextFormatting.BLUE + f.format(gravity * 20) + " " + I18n.format("gun.gravity.info"));
			tooltip.add(TextFormatting.BOLD + I18n.format("gun.desc.firerate") + ": " + TextFormatting.RESET + "" + TextFormatting.AQUA + g.format(20.00 / this.getFireRate()) + " " + I18n.format("gun.firerate.info"));
			tooltip.add(TextFormatting.BOLD + I18n.format("gun.desc.ammotype") + ": " + TextFormatting.BLUE + descAmmoType());
			tooltip.add(TextFormatting.BOLD + I18n.format("gun.desc.maxammo") + ": " + TextFormatting.RESET + "" + TextFormatting.RED + maxAmmo);
		}
		
		else tooltip.add(TextFormatting.YELLOW + I18n.format("gun.desc.moreinfo"));
	}
	
/*	For attachments
	@Override
	public NBTTagCompound serializeNBT() 
	{
		NBTTagCompound c = new NBTTagCompound();
		return c;
	}
	
	@Override
	public void deserializeNBT(NBTTagCompound nbt)
	{
		
	}
*/
}

The rest are just setters and getters

 

 

I have also noticed that the onUsingTick method is sometimes called more than once on each side, so that might be a problem too

I've tried looking into ItemBow class, but that didn't tell me much since it's using only onStoppedUsing method

Edited by Toma™
Marked thread as solved
Posted

Multiple people have had this problem (ill link threads in a sec).

I believe that the problem is due to modifying the item's NBT (this includes saving capabilities) while using it (which causes a sync, which causes the ItemStack client side to be replaced by a new one from the sync NBT, so the firing is force stopped on the client, while the server is unaware that you stopped shooting). This is just my hypothesis though.

There are some partial solutions to the problem:

- Only saving (and therefore syncing) NBT in the onUseFinish method (this allows the player to keep shooting clientside but could cause desyncs)

- Overriding shouldCauseReequipAnimation (doesn't solve the problem, only makes any visual glitches go away)

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Posted

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

  • 4 weeks later...
Posted

Okay, since I haven't seen anywhere exact solution for this I will write my solution I have found here just in case someone has the same problem.

OnUsingTick as it has been explained above and in the other threads is quite bad for doing this NBT related stuff, but you can subscribe to the ClientTickEvent and detect from here using the Minecraft GameSettings if your key (keyBindingAttack/UseItem - for different mouse buttons) is being held and run the code from here. But keep in mind you will have to sync some stuff with server in order to work properly.

I'm not saying that this is how it should be done, this is just how it works fine for me. 

  • Like 1
Posted

Can you please explain in a bit more detail? And post your code for people in the future?

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Posted
12 minutes ago, Cadiboo said:

Can you please explain in a bit more detail? And post your code for people in the future?

I think he has explained it quite well.

  1. Subscribe to the ClientTickEvent
  2. Check to see if the right click button is down(or whatever button you want)
  3. Check if it is your item
  4. Handle firing logic from there(You may need packets to sync a few things/spawn bullets).

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

Oh, that makes sense, if your handling syncing manually why not just put the firing code in the item, and the sync code in the ClientTickEvent?

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Posted
9 minutes ago, Cadiboo said:

Oh, that makes sense, if your handling syncing manually why not just put the firing code in the item, and the sync code in the ClientTickEvent?

It might still have the same issues because it would still become a new ItemStack.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
15 minutes ago, Animefan8888 said:

It might still have the same issues because it would still become a new ItemStack.

Only when you finish shooting, I see your point though

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

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.