Jump to content

Recommended Posts

Posted

I have created a simple item tool, that works like a hoe with some extra features. Everything works perfect, but the problem is that even when it till the dirt, it doesn't play the sound that the hoes do.

 

Is there anything I should consider when calling a vanilla sound from inside my mod, or it's just something that can't be done?

 

    public void tillDirt(ItemStack stack, EntityPlayer player, World world, BlockPos pos, IBlockState state)
    {
        world.playSound(player, pos, SoundEvents.item_hoe_till, SoundCategory.BLOCKS, 1.0F, 1.0F);

        if (!world.isRemote)
        {
            world.setBlockState(pos, state, 11);
            stack.damageItem(1, player);
        }
    }

Posted

World#playSound plays a sound only when called on the client side (i.e. when the world IS remote). My guess is that your method is only getting called on the server.

 

Is #tillDirt your own method, or inherited from Item and/or ItemTool? If it's your own method, show the code that calls it. If it's a vanilla method, are you sure it is called on both the client and the server side?

 

If you haven't already, take a closer look at the hoe to see how and where it plays its sound.

Posted

I guess that is the problem. This is the code, I know it can be improved to make it compatible with crops other than the vanilla one, but as for now I kinda "hardcoded" how it works, gonna improve it on future updates.

 

	@Override
@SuppressWarnings("incomplete-switch")
public EnumActionResult onItemUse(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
    {
	if(!world.isRemote)
	{

		//HOE
        if (!player.canPlayerEdit(pos.offset(facing), facing, stack))
        {
            return EnumActionResult.FAIL;
        }
        else
        {
            int hook = net.minecraftforge.event.ForgeEventFactory.onHoeUse(stack, player, world, pos);
            if (hook != 0) return hook > 0 ? EnumActionResult.SUCCESS : EnumActionResult.FAIL;

            IBlockState iblockstate = world.getBlockState(pos);
            Block block = iblockstate.getBlock();

            if (facing != EnumFacing.DOWN && world.isAirBlock(pos.up()))
            {
                if (block == Blocks.grass || block == Blocks.grass_path)
                {
                    this.tillDirt(stack, player, world, pos, Blocks.farmland.getDefaultState());
                    return EnumActionResult.SUCCESS;
                }

                if (block == Blocks.dirt)
                {
                    switch ((BlockDirt.DirtType)iblockstate.getValue(BlockDirt.VARIANT))
                    {
                        case DIRT:
                            this.tillDirt(stack, player, world, pos, Blocks.farmland.getDefaultState());
                            return EnumActionResult.SUCCESS;
                        case COARSE_DIRT:
                            this.tillDirt(stack, player, world, pos, Blocks.dirt.getDefaultState().withProperty(BlockDirt.VARIANT, BlockDirt.DirtType.DIRT));
                            return EnumActionResult.SUCCESS;
                    }
                }
            }

            
        }


		//DONGLE
		IBlockState checkBlockState = world.getBlockState(pos);
		Block checkBlock = checkBlockState.getBlock();

		if(checkBlock!=null)
		{
			if(checkBlock instanceof BlockCarrot)
			{


				int meta = checkBlock.getMetaFromState(checkBlockState);



				if(meta == 7) {

					world.setBlockState(pos, checkBlockState.withProperty(AGE, Integer.valueOf(0)), 3);

					final int reward = (int) ((Math.random() * 3)+1);

					dropX = new ItemStack(Items.carrot,reward,0);
					flag = true;

				}


			}//END CARROT

			if(checkBlock instanceof BlockPotato)
			{
//					System.out.println("It's a potato!");

				int meta = checkBlock.getMetaFromState(checkBlockState);

//					System.out.println("Meta: " + meta);

				if(meta == 7) {

					world.setBlockState(pos, checkBlockState.withProperty(AGE, Integer.valueOf(0)), 3);

					final int reward = (int) ((Math.random() * 3)+1);

					dropX = new ItemStack(Items.potato,reward,0);
					flag = true;

					dropX2 = new ItemStack(Items.poisonous_potato,1,0);
					flag2 = true;

				}


			}//END POTATO

			if(checkBlock instanceof BlockCrops && !(checkBlock instanceof BlockCarrot) && !(checkBlock instanceof BlockPotato) && !(checkBlock instanceof BlockBeetroot))
			{
//					System.out.println("It's wheat!");

				int meta = checkBlock.getMetaFromState(checkBlockState);

//					System.out.println("Meta: " + meta);

				if(meta == 7) {

					world.setBlockState(pos, checkBlockState.withProperty(AGE, Integer.valueOf(0)), 3);

					dropX = new ItemStack(Items.wheat,1,0);
					flag = true;

					dropX3 = new ItemStack(Items.wheat_seeds,1,0);
					flag3 = true;

				}


			}//END WHEAT

			if(checkBlock instanceof BlockBeetroot)
			{
//					System.out.println("It's a beetroot!");

				int meta = checkBlock.getMetaFromState(checkBlockState);

//					System.out.println("Meta: " + meta);

				if(meta == 3) {

					world.setBlockState(pos, checkBlockState.withProperty(BEETROOT_AGE, Integer.valueOf(0)), 3);

					dropX = new ItemStack(Items.beetroot,1,0);
					flag = true;

					dropX3 = new ItemStack(Items.beetroot_seeds,1,0);
					flag3 = true;

				}


			}//END BEETROOT




			if (flag) {
			itemDropX = new EntityItem(world, pos.getX()+.5, pos.getY()+.5, pos.getZ()+.5, dropX);
		   	world.spawnEntityInWorld(itemDropX);
		   	stack.damageItem(1, player);
		   	flag = false;
			}

			if (flag2) {
				int rand = (int) (Math.random() * 10);
				if (rand<1){
				itemDropX2 = new EntityItem(world, pos.getX()+.5, pos.getY()+.5, pos.getZ()+.5, dropX2);
			   	world.spawnEntityInWorld(itemDropX2);
				}
			flag2 = false;
			}

			if (flag3) {
				int rand = (int) (Math.random() * 4);
				if (rand<1){
				itemDropX3 = new EntityItem(world, pos.getX()+.5, pos.getY()+.5, pos.getZ()+.5, dropX3);
			   	world.spawnEntityInWorld(itemDropX3);
				}
			flag3 = false;
			}

		}


	}


        return EnumActionResult.PASS;
    }

 

I guess I should remove that first if(!world.isRemote) I always have problems on knowing when or not to use it...

Thanks for the answer.

 

PS: tillDirt is the same code that is on the hoes from Minecraft, just with a readable name.

 

Posted

As you read more vanilla code, you will see cases of when and when not to use !world.isRemote. Generally, you use it to encapsulate code that changes the world or things within the world, such as modifying a block state, giving a player an item, or spawning an entity. You only need to encapsulate the actual changing code, not necessarily everything around it, though sometimes that is useful to avoid wasting processing power on the client.

 

Anyway, if you model your item after the hoe, then mimic their #onItemUse implementation more closely as I doubt they encapsulate the entire thing in an if (!world.isRemote) statement.

Posted

Thanks coolAlias, yes I just removed it from there, and only use it now surrounding when I drop the items on the floor and when I set the state of the crop back to age 0.

 

Now it looks like this :D

	@Override
@SuppressWarnings("incomplete-switch")
public EnumActionResult onItemUse(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
    {
		//HOE
        if (!player.canPlayerEdit(pos.offset(facing), facing, stack))
        {
            return EnumActionResult.FAIL;
        }
        else
        {
            int hook = net.minecraftforge.event.ForgeEventFactory.onHoeUse(stack, player, world, pos);
            if (hook != 0) return hook > 0 ? EnumActionResult.SUCCESS : EnumActionResult.FAIL;

            IBlockState iblockstate = world.getBlockState(pos);
            Block block = iblockstate.getBlock();

            if (facing != EnumFacing.DOWN && world.isAirBlock(pos.up()))
            {
                if (block == Blocks.grass || block == Blocks.grass_path)
                {
                    this.tillDirt(stack, player, world, pos, Blocks.farmland.getDefaultState());
                    return EnumActionResult.SUCCESS;
                }

                if (block == Blocks.dirt)
                {
                    switch ((BlockDirt.DirtType)iblockstate.getValue(BlockDirt.VARIANT))
                    {
                        case DIRT:
                            this.tillDirt(stack, player, world, pos, Blocks.farmland.getDefaultState());
                            return EnumActionResult.SUCCESS;
                        case COARSE_DIRT:
                            this.tillDirt(stack, player, world, pos, Blocks.dirt.getDefaultState().withProperty(BlockDirt.VARIANT, BlockDirt.DirtType.DIRT));
                            return EnumActionResult.SUCCESS;
                    }
                }
            }

            
        }


		//DONGLE
		IBlockState checkBlockState = world.getBlockState(pos);
		Block checkBlock = checkBlockState.getBlock();

		if(checkBlock!=null)
		{
			if(checkBlock instanceof BlockCarrot)
			{
				int meta = checkBlock.getMetaFromState(checkBlockState);
				if(meta == 7) {
					if (!world.isRemote)
			        {
					world.setBlockState(pos, checkBlockState.withProperty(AGE, Integer.valueOf(0)), 3);
			        }
					final int reward = (int) ((Math.random() * 3)+1);
					dropX = new ItemStack(Items.carrot,reward,0);
					flag = true;
				}

			}//END CARROT

			if(checkBlock instanceof BlockPotato)
			{
				int meta = checkBlock.getMetaFromState(checkBlockState);
				if(meta == 7) {
					if (!world.isRemote)
			        {						
					world.setBlockState(pos, checkBlockState.withProperty(AGE, Integer.valueOf(0)), 3);
			        }
					final int reward = (int) ((Math.random() * 3)+1);
					dropX = new ItemStack(Items.potato,reward,0);
					flag = true;

					dropX2 = new ItemStack(Items.poisonous_potato,1,0);
					flag2 = true;
				}

			}//END POTATO

			if(checkBlock instanceof BlockCrops && !(checkBlock instanceof BlockCarrot) && !(checkBlock instanceof BlockPotato) && !(checkBlock instanceof BlockBeetroot))
			{
				int meta = checkBlock.getMetaFromState(checkBlockState);
				if(meta == 7) {
					if (!world.isRemote)
			        {						
					world.setBlockState(pos, checkBlockState.withProperty(AGE, Integer.valueOf(0)), 3);
			        }
					dropX = new ItemStack(Items.wheat,1,0);
					flag = true;

					dropX3 = new ItemStack(Items.wheat_seeds,1,0);
					flag3 = true;

				}

			}//END WHEAT

			if(checkBlock instanceof BlockBeetroot)
			{
				int meta = checkBlock.getMetaFromState(checkBlockState);
				if(meta == 3) {
					if (!world.isRemote)
			        {						
					world.setBlockState(pos, checkBlockState.withProperty(BEETROOT_AGE, Integer.valueOf(0)), 3);
			        }
					dropX = new ItemStack(Items.beetroot,1,0);
					flag = true;

					dropX3 = new ItemStack(Items.beetroot_seeds,1,0);
					flag3 = true;
				}

			}//END BEETROOT

			if (flag) {
				if (!world.isRemote)
		        {
			itemDropX = new EntityItem(world, pos.getX()+.5, pos.getY()+.5, pos.getZ()+.5, dropX);
		   	world.spawnEntityInWorld(itemDropX);
		   	stack.damageItem(1, player);
		   	flag = false;
		        }
			}

			if (flag2) {
				if (!world.isRemote)
		        {
				int rand = (int) (Math.random() * 10);
				if (rand<1){
				itemDropX2 = new EntityItem(world, pos.getX()+.5, pos.getY()+.5, pos.getZ()+.5, dropX2);
			   	world.spawnEntityInWorld(itemDropX2);
				}
			flag2 = false;
		        }
			}

			if (flag3) {
				if (!world.isRemote)
		        {
				int rand = (int) (Math.random() * 4);
				if (rand<1){
				itemDropX3 = new EntityItem(world, pos.getX()+.5, pos.getY()+.5, pos.getZ()+.5, dropX3);
			   	world.spawnEntityInWorld(itemDropX3);
				}
			flag3 = false;
		        }
			}

		}





        return EnumActionResult.PASS;
    }

 

Next step will actually be getting the drops and not "emulating" them, I think that's a better way to code this tool, but I got confused when trying that, but for sure will try again on the near future, so at some point I may come again to ask some doubts I have on how to achieve that, specially when apparently Beetroots makes things a little bit more complicate that wheats, carrots and potatoes.

 

Thanks once again for the help ;)

Posted

Counter-intuitively, vanilla Minecraft initiates most of its sounds on the server. That's because it wants all (nearby) players to hear the sounds, not just the player performing an action. You'll see calls to World#playSoundEffect. If you trace it, you'll eventually see a packet sent to all clients (World-Accesses) whose players are within earshot. The actual sound is eventually played client-side (of course), but only in response to the packet.

 

Your code usually should not call those client-side methods used to render sound. Instead, your mod should almost always call the server-side sound-effect method and let vanilla handle the distribution to clients. An exception would be, for instance, if you set-up a tile entity to emit a continuous sound, or if you gave a helmet to one player to play sounds in response to objects in his environment.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

@jeffryfisher Or if he doesn't want anyone nearby to hear and figure out that he's using a hoe, which is what I assumed* :P

 

* given that he was wanting to play the sound on the client, but perhaps that was the only way he found? or is that how vanilla tools or just the hoes behave? I don't have an IDE to check right now, but I kinda think that tool sounds are client only - do you actually hear other players chopping and mining? Not that I recall, but it's been ages since I've played.

Posted

Yes, other players' chopping and picking and running etc makes noise that will play for you and all other nearby players. Tools initiate sound effects on the server that are eventually rendered on clients, with each client's rendition attenuated for distance (IIRC, zero-volume sfx are dropped before packets are sent).

 

Therefore, one should normally call the playSoundEffect method. It does its own server-side / client-side check, only doing something on the server (causing packets to be sent).

 

Counter-intuitively, this means that if you call playSoundEffect from inside a client-only method (such as inside a client-proxy), then it won't do diddly. You need to make sure that your call is executing on the server.

 

This actually makes some sense when you figure that the server is the authority on what really happens in the world. The server is also (by definition) responsible for distributing info to multiple players.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

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.