• Recently Browsing

    No registered users viewing this page.

  • Posts

    • Since playing arbitrary sounds isn't a normally supported feature, there's quite a lot of work to do to make things behave properly.   All those "func_######" methods are obfuscated, so the best way to learn what they are is to understand what is being put into them. For example, SoundSource#func_216422_a(float) doesn't have any clear purpose, but by looking at its usages in vanilla code I can find out that it sets the pitch of the sound source.   Here's a rough explanation of how sounds are played, based on what you're trying to do: Something creates an instance of an ISound. Most things use an instance of SimpleSound since it contains all sorts of useful properties. This ISound instance is then passed into SoundHandler#play(ISound), which is then passed SoundEngine#play(ISound). This is where the sounds get played. A whole bunch of stuff happens here. Forge runs some event hooks, a few values are validated, subtitles get activated, etc. You can ditch most of this for your system, but I recommend keeping all of it and working around it in order to keep things as close to vanilla as possible. Now, in the else part of the if(sound == SoundHandler.MISSING_SOUND) branch, this is where things get interesting, and confusing. From here, variables and methods are mostly obfuscated and arbitrary, which makes things hard to read. When reverse engineering this process, you may want to copy the code elsewhere and change the variable names as you go to make things easier to understand. Adding comments to obfuscated method calls can help remind you what those methods do when you figure them out. Now here's the biggest hurdle to get over: channelmanager$entry. As you can see, channelmanager$entry is a channel created by the ChannelManager in SoundEngine. In order to play your own arbitrary sounds, you're going to need this ChannelManager instance. Trouble is, the field is private. You have two major options here. Use reflection to make the ChannelManager field in SoundEngine accessible. This isn't too hard, but you should have a very good understanding of how reflection works in Java before doing this since reflection can be dangerous. Use an access transformer to make the field accessible through Forge. I think this is the best solution of the two. Like reflection, you should learn how these work yourself to make sure you fully understand what you're doing, since this tool can also be dangerous. After channelmanager$entry has been configured from data in the ISound and its Sound (confusing, I know) about pitch, location, etc, it's time to actually play the sound! It has to do slightly different things if the sound is being streamed or not. Because we're working with a FileInputStream, I'm going to assume the sound will be streamed. First, AudioStreamManager#func_217917_b(ResourceLocation) is run. This supplies an IAudioStream by turning a ResourceLocation into an OggAudioStream. You can create an OggAudioStream from any InputStream, so try doing that with your FileInputStream! Will it work? No idea! I haven't tested it myself. Then, it plays the IAudioStream through the configured channelmanager$entry. Congratulations, if you did everything right, you will have just played a sound from a file! This is about as close as I can get without directly spoon-feeding code or teaching basic Java. If people who are more experienced than me would like to improve any part of my explanation (or get rid of it, if it's too much hand-holding), it would be much appreciated.
    • I'm attempting to create a custom brewing stand and ran into an interesting problem.  I'm trying to spawn particles when the custom brewing stand is actually brewing, but getting mixed results.  Note, my custom object right now is pretty much a copy of the original!!   To doi this I am calling a method spawnProcessingParticle inside the ChuProcessorTileEntity.tick() method...   I posted the tick method below along with two places I am trying to call spawnProcessingParticle() .... I have the placements in BOLD. Placement #1 Logs (Interesting because it calls the render): [03Apr2020 22:25:28.606] [Server thread/INFO] [weible.rupeehunt.RupeeHuntMod/]: Spawning World Particle at (-71.6,65.7,-204.6), BT(0) [03Apr2020 22:25:28.678] [Server thread/INFO] [weible.rupeehunt.RupeeHuntMod/]: Spawning World Particle at (-71.6,65.7,-204.6), BT(0) [03Apr2020 22:25:28.687] [Render thread/INFO] [weible.rupeehunt.RupeeHuntMod/]: Spawning World Particle at (-71.6,65.7,-204.6), BT(0) [03Apr2020 22:25:28.710] [Render thread/INFO] [weible.rupeehunt.RupeeHuntMod/]: Spawning World Particle at (-71.6,65.7,-204.6), BT(0)   Placement #2 Logs (Doesn't call the render): [03Apr2020 22:43:57.059] [Server thread/INFO] [weible.rupeehunt.RupeeHuntMod/]: Spawning World Particle at (-71.6,65.7,-204.6), BT(398) [03Apr2020 22:43:57.103] [Server thread/INFO] [weible.rupeehunt.RupeeHuntMod/]: Spawning World Particle at (-71.6,65.7,-204.6), BT(397) [03Apr2020 22:43:57.155] [Server thread/INFO] [weible.rupeehunt.RupeeHuntMod/]: Spawning World Particle at (-71.6,65.7,-204.6), BT(396) [03Apr2020 22:43:57.202] [Server thread/INFO] [weible.rupeehunt.RupeeHuntMod/]: Spawning World Particle at (-71.6,65.7,-204.6), BT(395)        public void spawnProcessingParticle()    {            double d0 = (double)this.getPos().getX() + 0.4D;            double d1 = (double)this.getPos().getY() + 0.7D;            double d2 = (double)this.getPos().getZ() + 0.4D;            RupeeHuntMod.LOGGER.log(Level.INFO, "Spawning World Particle at ("+d0+","+d1+","+d2+"), BT("+this.brewTime+")");                        for(int i = 0; i<100;i++)            {                this.world.addParticle(ParticleTypes.HAPPY_VILLAGER, d0, d1, d2, 0.0D, 0.0D, 0.0D);            }    }   -----------------      public void tick()     {       ItemStack itemstack = this.brewingItemStacks.get(4);       if (this.fuel <= 0 && itemstack.getItem() == Items.BLAZE_POWDER)        {          this.fuel = 20;          itemstack.shrink(1);          this.markDirty();       }              /*           PLACEMENT NUMBER 1) THIS WORKS AND SPAWNS PARTICLES, BUT DOESN'T MEET THE DESIRE             spawnProcessingParticle();                 */         boolean flag = this.canBrew();       boolean flag1 = this.brewTime > 0;       ItemStack itemstack1 = this.brewingItemStacks.get(3);              if (flag1)        {          --this.brewTime;                    boolean flag2 = this.brewTime == 0;          if (flag2 && flag)           {             this.brewPotions();             this.markDirty();                       /*           PLACEMENT NUMBER 2) THIS MEETS THE DESIRES BY CALLING THE METHOD, BUT PARTICLES NEVER RENDER            spawnProcessingParticle();                   */          }           else if (!flag)           {             this.brewTime = 0;             this.markDirty();                      }           else if (this.ingredientID != itemstack1.getItem())           {             this.brewTime = 0;             this.markDirty();          }       }        else if (flag && this.fuel > 0)        {          --this.fuel;          this.brewTime = 400;          this.isBrewing = true;          this.ingredientID = itemstack1.getItem();          this.markDirty();       }       if (!this.world.isRemote)        {          boolean[] aboolean = this.createFilledSlotsArray();          if (!Arrays.equals(aboolean, this.filledSlots)) {             this.filledSlots = aboolean;             BlockState blockstate = this.world.getBlockState(this.getPos());             if (!(blockstate.getBlock() instanceof ChuProcessorBlock)) {                return;             }             for(int i = 0; i < ChuProcessorBlock.HAS_BOTTLE.length; ++i) {                blockstate = blockstate.with(ChuProcessorBlock.HAS_BOTTLE, Boolean.valueOf(aboolean));             }          }       }    }   Anyway, curious on ideas, or why this is only Rendering at certain points in the code ..... I'm a little new to TileEntities .... so hopefully I'm not doing something completely not right ... any help would be appreciated!    
    • I am currently thinking of two options for rendering my entity. The one is with the SpriteRenderer, which is used by vanilla to render items like snowballs. When I use this one, the game spawns a PigEntity when right clicking with my custom item and the error message as shown here: The other option I thought of was to extend SpriteRenderer to override the getEntityTexture method with a ResourceLocation to my texture for the ProjectileItemEntity. But then the error as shown here appears: Where only the first error is relevant.   So overall my problem is that I don't know how to make the entity have the texture of my custom item.
    • package drachenbauer32.yellowredstonemod.blocks; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.RedstoneOreBlock; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.particles.RedstoneParticleData; import net.minecraft.util.ActionResultType; import net.minecraft.util.Direction; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.world.ITickList; import net.minecraft.world.World; public class YellowRedstoneOreBlock extends RedstoneOreBlock { public YellowRedstoneOreBlock(Properties properties) { super(properties); } public void onBlockClicked(BlockState state, World worldIn, BlockPos pos, PlayerEntity player) { activate(state, worldIn, pos); } @Override public void onEntityWalk(World worldIn, BlockPos pos, Entity entityIn) { activate(worldIn.getBlockState(pos), worldIn, pos); } @Override public ActionResultType onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { activate(state, world, pos); if (world.isRemote) { return ActionResultType.SUCCESS; } else { return ActionResultType.PASS; } } private static void activate(BlockState state, World world, BlockPos pos) { spawnParticles(world, pos); ITickList<Block> tickList = world.getPendingBlockTicks(); tickList.scheduleTick(pos, state.getBlock(), 80); if (!state.get(LIT)) { world.setBlockState(pos, state.with(LIT, Boolean.valueOf(true)), 3); } } @Override public void animateTick(BlockState state, World world, BlockPos pos, Random rand) { if(state.get(LIT)) { spawnParticles(world, pos); } } private static void spawnParticles(World world, BlockPos pos) { Random random = world.rand; for(Direction direction : Direction.values()) { BlockPos blockpos = pos.offset(direction); if (!world.getBlockState(blockpos).isOpaqueCube(world, blockpos)) { Direction.Axis direction$axis = direction.getAxis(); double d1 = direction$axis == Direction.Axis.X ? 0.5D + 0.5625D * (double)direction.getXOffset() : (double)random.nextFloat(); double d2 = direction$axis == Direction.Axis.Y ? 0.5D + 0.5625D * (double)direction.getYOffset() : (double)random.nextFloat(); double d3 = direction$axis == Direction.Axis.Z ? 0.5D + 0.5625D * (double)direction.getZOffset() : (double)random.nextFloat(); world.addParticle(new RedstoneParticleData(1.0F, 0.875F, 0.0F, 1.0F), (double)pos.getX() + d1, (double)pos.getY() + d2, (double)pos.getZ() + d3, 0.0D, 0.0D, 0.0D); } } } }   And how can i make it activate, if i run into it, or leftclick it with a sword or other tool?
  • Topics

  • Who's Online (See full list)