Jump to content

[Solved] Creating seamless music loop from a tile entity: is it possible?


サムエル

Recommended Posts

So I'm working on a mod that generates a huge (32 x 32 x 32) maze and I want it to have custom background music for added atmosphere. I have achieved this by creating a block at the entrance that plays the pre-loop part when a player touches its bounds and then the tileEntity it creates handles the looped portion from there on. The problem is that there is a short but clear seam between each playSound and it ruins the atmosphere. I thought of making playSound() happen before the previous one ends but I don't know how that can be done considering the sound is not synchronized with the amount of times the update() method is fired in the tileEntity. Is there another way to play background music where I can get a consistent amount of ticks or something else that allows the music to always line up seamlessly? On top of that, I have no idea how to keep the default Minecraft music from starting in the middle of my custom music but I'll leave that for another thread unless someone wants to tell me here.

 

Here is my code: (I'm aware there's no code yet to stop the music but I might as well leave it for when I actually know if this is possible)

 

BlockChaosLabyrinthEntrance.java

 

package com.samuel.chaosblock;

 

import java.util.List;

 

import com.samuel.chaosblock.entities.EntityBlockChaosPrimed;

import com.samuel.chaosblock.tileentities.TileEntityChaosLabyrinthEntrance;

 

import net.minecraft.block.Block;

import net.minecraft.block.BlockContainer;

import net.minecraft.block.material.Material;

import net.minecraft.block.properties.PropertyBool;

import net.minecraft.block.state.IBlockState;

import net.minecraft.client.Minecraft;

import net.minecraft.client.audio.PositionedSoundRecord;

import net.minecraft.client.audio.SoundHandler;

import net.minecraft.creativetab.CreativeTabs;

import net.minecraft.entity.Entity;

import net.minecraft.entity.EntityLivingBase;

import net.minecraft.entity.item.EntityTNTPrimed;

import net.minecraft.item.ItemStack;

import net.minecraft.tileentity.TileEntity;

import net.minecraft.util.AxisAlignedBB;

import net.minecraft.util.BlockPos;

import net.minecraft.util.DamageSource;

import net.minecraft.util.ResourceLocation;

import net.minecraft.world.Explosion;

import net.minecraft.world.IBlockAccess;

import net.minecraft.world.World;

import net.minecraftforge.fml.common.registry.GameRegistry;

 

public class BlockChaosLabyrinthEntrance extends BlockContainer {

   

    public static final String name = "unbreakable_chaos_block";

    public static boolean tileEntityActivated = false;

    public static TileEntityChaosLabyrinthEntrance tileEntity;

   

    public BlockChaosLabyrinthEntrance(String unlocalizedName, Material material, float hardness, float resistance) {

        super(material);

        this.setUnlocalizedName(unlocalizedName);

        this.setCreativeTab(CreativeTabs.tabBlock);

        this.setHardness(hardness);

        this.setResistance(resistance);

        this.setLightLevel(14F);

        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.0625F, 1.0F);

    }

   

    public BlockChaosLabyrinthEntrance(String unlocalizedName, float hardness, float resistance) {

        this(unlocalizedName, Material.rock, hardness, resistance);

    }

 

    public BlockChaosLabyrinthEntrance(String unlocalizedName) {

        this(unlocalizedName, -1.0f, 18000000.0f);

    }

   

    public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int i, int j, int k)

    {

        float f = 0.0625F;

        return AxisAlignedBB.fromBounds((float)i + f, j, (float)k + f, (float)(i + 1) - f, (float)(j + 1) - f, (float)(k + 1) - f);

    }

   

    public void onEntityCollidedWithBlock(World worldIn, BlockPos pos, IBlockState state, Entity entityIn)

    {

    if (!this.tileEntityActivated && !tileEntity.sh.isSoundPlaying(ChaosBlock.bgm)

    && !tileEntity.sh.isSoundPlaying(ChaosBlock.bgm_preloop)) {

    tileEntity.sh.stopSounds();

    tileEntity.sh.playSound(ChaosBlock.bgm_preloop);

    this.tileEntityActivated = true;

    }

    }

   

    public String getName() {

        return name;

    }

 

@Override

public TileEntity createNewTileEntity(World worldIn, int meta) {

return tileEntity = new TileEntityChaosLabyrinthEntrance(this);

}

}

 

 

TileEntityChaosLabyrinthEntrance.java

 

package com.samuel.chaosblock.tileentities;

 

import com.samuel.chaosblock.BlockChaosLabyrinthEntrance;

import com.samuel.chaosblock.ChaosBlock;

 

import net.minecraft.client.Minecraft;

import net.minecraft.client.audio.PositionedSoundRecord;

import net.minecraft.client.audio.SoundHandler;

import net.minecraft.server.gui.IUpdatePlayerListBox;

import net.minecraft.tileentity.TileEntity;

import net.minecraft.util.ChatComponentText;

import net.minecraft.util.ResourceLocation;

import net.minecraft.world.World;

 

public class TileEntityChaosLabyrinthEntrance extends TileEntity implements IUpdatePlayerListBox {

 

public BlockChaosLabyrinthEntrance block = null;

public SoundHandler sh = Minecraft.getMinecraft().getSoundHandler();

 

public TileEntityChaosLabyrinthEntrance(BlockChaosLabyrinthEntrance block) {

this.block = block;

}

 

@Override

public void update() {

if (block.tileEntityActivated && !this.worldObj.isRemote) {

if (!sh.isSoundPlaying(ChaosBlock.bgm) && !sh.isSoundPlaying(ChaosBlock.bgm_preloop)) {

sh.stopSounds();

sh.playSound(ChaosBlock.bgm);

}

}

}

}

 

Link to comment
Share on other sites

So I replaced the tile entity with a movingsound and I can't get anything to play. I'm also not sure how to get the preloop to work with this without a seam but for now I just want to be able to get it to play the looped portion. Can anyone see what I did wrong here? I couldn't find anything online about registering movingsounds so if they actually do need to be registered then that's likely part of my problem if not the whole problem.

 

MovingSoundChaosLabyrinthBGM.java

 

package com.samuel.chaosblock.movingsounds;

 

import com.samuel.chaosblock.BlockChaosLabyrinthEntrance;

 

import net.minecraft.client.audio.ISound;

import net.minecraft.client.audio.MovingSound;

import net.minecraft.entity.Entity;

import net.minecraft.entity.player.EntityPlayer;

import net.minecraft.util.ResourceLocation;

 

public class MovingSoundChaosLabyrinthBGM extends MovingSound {

    private final EntityPlayer player;

    private final BlockChaosLabyrinthEntrance block;

 

    public MovingSoundChaosLabyrinthBGM(Entity entityIn, BlockChaosLabyrinthEntrance block)

    {

        super(new ResourceLocation("dark_halls"));

        this.player = (EntityPlayer) entityIn;

        this.block = block;

        this.attenuationType = ISound.AttenuationType.NONE;

        this.repeat = true;

        this.repeatDelay = 0;

    }

 

    /**

    * Updates the JList with a new model.

    */

    public void update()

    {

        if (block.bgmActivated)

            this.volume = 1.0F;

        else

            this.donePlaying = true;

    }

}

 

Link to comment
Share on other sites

I might be wrong but PositionedSound seems to only play sounds from a location where I want it to play for a player regardless of location. If you actually just meant MovingSound then it would make more sense since you suggested MovingSound in the first place. If you did mean PositionedSound, how do I get it to follow the player?

Link to comment
Share on other sites

What I have tried is this:

 

MovingSoundChaosLabyrinthBGM.java

 

package com.samuel.chaosblock.movingsounds;

 

import com.samuel.chaosblock.BlockChaosLabyrinthEntrance;

import com.samuel.chaosblock.ChaosBlock;

 

import net.minecraft.client.audio.ISound;

import net.minecraft.client.audio.MovingSound;

import net.minecraft.entity.Entity;

import net.minecraft.entity.player.EntityPlayer;

import net.minecraft.util.ResourceLocation;

 

public class MovingSoundChaosLabyrinthBGM extends MovingSound {

    private final BlockChaosLabyrinthEntrance block;

    public boolean bgmActivated = false;

    public EntityPlayer thePlayer;

    protected boolean repeat = true;

    protected int repeatDelay = 0;

    protected float pitch;

 

    public MovingSoundChaosLabyrinthBGM(Entity entityIn, BlockChaosLabyrinthEntrance block)

    {

        super(ChaosBlock.bgmRes);

        this.block = block;

        this.repeat = true;

        this.volume = 0.8f;

        this.pitch = 1.0F;

    }

 

    public void setDonePlaying()

    {

        this.repeat = false;

        this.donePlaying = true;

        this.repeatDelay = 0;

    }

 

    @Override

    public boolean isDonePlaying()

    {

        return this.donePlaying;

    }

 

    @Override

    public void update()

    {

      byte status = 0;

      if(thePlayer == null || thePlayer.worldObj == null)

        {

            setDonePlaying();

        }

        if (bgmActivated) {

            xPosF = (float)thePlayer.posX;

            yPosF = (float)thePlayer.posY;

            zPosF = (float)thePlayer.posZ;

        } else {

        setDonePlaying();

        }

    }

 

    @Override

    public boolean canRepeat()

    {

        return this.repeat;

    }

 

    @Override

    public float getVolume()

    {

        return this.volume;

    }

 

    @Override

    public float getPitch()

    {

        return this.pitch;

    }

 

    @Override

    public int getRepeatDelay(){ return this.repeatDelay; }

 

    @Override

    public AttenuationType getAttenuationType()

    {

        return AttenuationType.LINEAR;

    }

}

 

 

I've never really worked with packets and I'm not sure how I would apply your tutorial to a sound.

Link to comment
Share on other sites

Unless you just mean calling SoundHandler.playSound() from the tile entity, I still don't know how I would apply the method in your tutorial to this. I'm also confused about whether I even need the tile entity when I have the moving sound. If I just have to call playSound() from the tile entity then do I just call the moving sound like I would a non-tickable sound?

Link to comment
Share on other sites

I tried the playSound with the tile entity and it's still not working. When you're talking about using packets, I can't tell if you're referring to how everything works internally or if you're saying I need to do what it's in your tutorial. If the latter, it's not obvious to me what needs to be changed in that code for it to work with a sound instead of a message and I can't seem to find any other examples for it.

Link to comment
Share on other sites

Nevermind, I had two versions of the same boolean and I only had it enabled in one of them. It seems to work now and loops as well even though there's a minor click in between. So my next question is how can I play the preloop part of the music and then switch to the looped part without a seam?

Link to comment
Share on other sites

Alright, here's my TE code:

 

TileEntityChaosLabyrinthEntrance.java

 

package com.samuel.chaosblock.tileentities;

 

import com.samuel.chaosblock.BlockChaosLabyrinthEntrance;

import com.samuel.chaosblock.ChaosBlock;

 

import net.minecraft.client.Minecraft;

import net.minecraft.client.audio.PositionedSoundRecord;

import net.minecraft.client.audio.SoundHandler;

import net.minecraft.server.gui.IUpdatePlayerListBox;

import net.minecraft.tileentity.TileEntity;

import net.minecraft.util.ChatComponentText;

import net.minecraft.util.ResourceLocation;

import net.minecraft.world.World;

 

public class TileEntityChaosLabyrinthEntrance extends TileEntity implements IUpdatePlayerListBox {

 

  public SoundHandler sh = Minecraft.getMinecraft().getSoundHandler();

 

  public TileEntityChaosLabyrinthEntrance(BlockChaosLabyrinthEntrance block) {

  }

 

  @Override

  public void update() {

      if (ChaosBlock.BGMActivated && !this.worldObj.isRemote) {

        if (!sh.isSoundPlaying(ChaosBlock.movingSoundBGM) && !sh.isSoundPlaying(ChaosBlock.bgm_preloop)) {

        sh.playSound(ChaosBlock.movingSoundBGM);

        }

      }

  }

}

 

 

I found out before you posted that the audio file was actually the problem with the looped click and I've since fixed it. I want to know here if I can play the preloop and transition to the looped portion without a seam but if not I can just fade in the looped portion. ChaosBlock is the main mod class in case you might think it's a block.

Link to comment
Share on other sites

If that's the case, how do I play the sound without accessing the SoundHandler (Edit: I found out I can probably just use "this.worldObj" but if I can just play it on the player's client then I'd like to know how to do that)? Also, to tell if the song is playing (so as to not play another copy over itself if the block collision is triggered twice), do I just use the BGMActivated boolean alone?

Link to comment
Share on other sites

Alright, so if I want to send a packet to the player, do I just put a second constructor in the tile entity to take the triggering player as an argument and send the packet to that player? I don't know if it will matter if that variable is overwritten by a second triggering player and that's why I'm asking.

Link to comment
Share on other sites

The following code is in the block's collision code:

 

 

if (ChaosBlock.movingSoundBGM == null || !ChaosBlock.BGMActivated) {

    ChaosBlock.BGMActivated = true;

    ChaosBlock.movingSoundBGM = new MovingSoundChaosLabyrinthBGM(entityIn);

    if (worldIn.isRemote)

  Minecraft.getMinecraft().getSoundHandler().playSound(ChaosBlock.movingSoundBGM);

    else

    ChaosBlock.network.sendTo(new bgmPacket("Start"), (EntityPlayerMP) entityIn);

  }

 

 

It seems to work in SP (obviously because it's doing what I did before) but I haven't tried MP yet. Does this look correct given the following class?

 

bgmPacket.java

 

package com.samuel.chaosblock;

 

import io.netty.buffer.ByteBuf;

import net.minecraft.client.Minecraft;

import net.minecraft.util.IThreadListener;

import net.minecraft.world.WorldServer;

import net.minecraftforge.fml.common.network.ByteBufUtils;

import net.minecraftforge.fml.common.network.simpleimpl.IMessage;

import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;

import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;

 

public class bgmPacket implements IMessage {

   

    private String text;

 

    public bgmPacket() { }

 

    public bgmPacket(String text) {

        this.text = text;

    }

 

    @Override

    public void fromBytes(ByteBuf buf) {

        text = ByteBufUtils.readUTF8String(buf); // this class is very useful in general for writing more complex objects

    }

 

    @Override

    public void toBytes(ByteBuf buf) {

        ByteBufUtils.writeUTF8String(buf, text);

    }

 

    public static class Handler implements IMessageHandler<bgmPacket, IMessage> {

        @Override

        public IMessage onMessage(final bgmPacket message, MessageContext ctx) {

            IThreadListener mainThread = (WorldServer) ctx.getServerHandler().playerEntity.worldObj; // or Minecraft.getMinecraft() on the client

            mainThread.addScheduledTask(new Runnable() {

                @Override

                public void run() {

                if (message.text == "start")

                Minecraft.getMinecraft().getSoundHandler().playSound(ChaosBlock.movingSoundBGM);

                }

            });

            return null; // no response in this case

        }

    }

}

 

 

If so, thanks a lot and I'd like to know more about using "SoundSourceEvent" to stop the regular background music because I couldn't find any information regarding that.

Link to comment
Share on other sites

The == thing was just out of habit because I don't use Java nearly as much as Javascript and other web-based languages.

 

If I do nothing on the client, where does playSound even execute in single player? If I try to send the packet in single player it tells me EntityPlayerSP can't be cast to EntityPlayerMP.

 

Also, what are you saying shouldn't be static? Are you referring to the MovingSound? I made it static because I don't know how I would be able to access it from the packet handler otherwise.

Link to comment
Share on other sites

It sounds like you want me to put the method in the common proxy but I don't know of any way to separate client and server from within the common proxy. Am I supposed to put the method in the client proxy and if not, could you show me how I can only affect the client proxy from within the common proxy?

Link to comment
Share on other sites

Well I have three proxies with the third being ServerProxy. I got that from a tutorial when I was starting the mod, should I only have the two?

 

I think I misunderstood something because nothing is happening when I send the packet.

 

bgmPacket.java

 

package com.samuel.chaosblock;

 

import java.lang.reflect.Proxy;

 

import com.samuel.chaosblock.movingsounds.MovingSoundChaosLabyrinthBGM;

import com.samuel.chaosblock.proxy.ClientProxy;

 

import io.netty.buffer.ByteBuf;

import net.minecraft.client.Minecraft;

import net.minecraft.util.ChatComponentText;

import net.minecraft.util.IThreadListener;

import net.minecraft.world.WorldServer;

import net.minecraftforge.fml.common.network.ByteBufUtils;

import net.minecraftforge.fml.common.network.simpleimpl.IMessage;

import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;

import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;

 

public class bgmPacket implements IMessage {

   

    private String text;

 

    public bgmPacket() { }

 

    public bgmPacket(String text) {

        this.text = text;

    }

 

    @Override

    public void fromBytes(ByteBuf buf) {

        text = ByteBufUtils.readUTF8String(buf); // this class is very useful in general for writing more complex objects

    }

 

    @Override

    public void toBytes(ByteBuf buf) {

        ByteBufUtils.writeUTF8String(buf, text);

    }

 

    public static class Handler implements IMessageHandler<bgmPacket, IMessage> {

        @Override

        public IMessage onMessage(final bgmPacket message, final MessageContext ctx) {

            IThreadListener mainThread = (WorldServer) ctx.getServerHandler().playerEntity.worldObj; // or Minecraft.getMinecraft() on the client

            mainThread.addScheduledTask(new Runnable() {

                @Override

                public void run() {

                if (message.text.equals("start"))

                ChaosBlock.proxy.playBGM(ctx.getServerHandler().playerEntity);

                ctx.getServerHandler().playerEntity.addChatMessage(new ChatComponentText(message.text));

                }

            });

            return null; // no response in this case

        }

    }

}

 

 

ClientProxy.java

 

package com.samuel.chaosblock.proxy;

 

import com.samuel.chaosblock.ChaosBlock;

import com.samuel.chaosblock.client.render.blocks.BlockRenderRegister;

import com.samuel.chaosblock.client.render.entities.RenderBlockChaosPrimed;

import com.samuel.chaosblock.entities.EntityBlockChaosPrimed;

import com.samuel.chaosblock.movingsounds.MovingSoundChaosLabyrinthBGM;

 

import net.minecraft.client.Minecraft;

import net.minecraft.entity.player.EntityPlayer;

import net.minecraftforge.fml.client.registry.RenderingRegistry;

import net.minecraftforge.fml.common.event.FMLInitializationEvent;

import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;

import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

 

public class ClientProxy extends CommonProxy {

 

public MovingSoundChaosLabyrinthBGM movingSoundBGM = null;

 

@Override

public void preInit(FMLPreInitializationEvent e) {

super.preInit(e);

}

 

@Override

public void init(FMLInitializationEvent e) {

super.init(e);

BlockRenderRegister.registerBlockRenderer();

RenderingRegistry.registerEntityRenderingHandler(EntityBlockChaosPrimed.class, new RenderBlockChaosPrimed(Minecraft.getMinecraft().getRenderManager()));

}

 

@Override

public void postInit(FMLPostInitializationEvent e) {

super.postInit(e);

}

 

@Override

public void playBGM(EntityPlayer player) {

movingSoundBGM = new MovingSoundChaosLabyrinthBGM(player);

Minecraft.getMinecraft().getSoundHandler().playSound(movingSoundBGM);

}

}

 

 

CommonProxy (server proxy) has the method public void playBGM(EntityPlayer player) except blank. Can you see what I did wrong?

Link to comment
Share on other sites

Alright, I finally figured out what you meant. Apparently I didn't read your code comments well enough to see that I was supposed to use EntityPlayerSP thePlayer from Minecraft.getMinecraft() and not the EntityPlayerMP from the server. I see that you were saying that the whole time, I just didn't understand until now. I'd like to get the default background music to stop but I suppose that's for another thread.

Link to comment
Share on other sites

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I have done this now but have got the error:   'food(net.minecraft.world.food.FoodProperties)' in 'net.minecraft.world.item.Item.Properties' cannot be applied to                '(net.minecraftforge.registries.RegistryObject<net.minecraft.world.item.Item>)' public static final RegistryObject<Item> LEMON_JUICE = ITEMS.register( "lemon_juice", () -> new Item( new HoneyBottleItem.Properties().stacksTo(1).food( (new FoodProperties.Builder()) .nutrition(3) .saturationMod(0.25F) .effect(() -> new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 1500), 0.01f ) .build() ) )); The code above is from the ModFoods class, the one below from the ModItems class. public static final RegistryObject<Item> LEMON_JUICE = ITEMS.register("lemon_juice", () -> new Item(new Item.Properties().food(ModFoods.LEMON_JUICE)));   I shall keep going between them to try and figure out the cause. I am sorry if this is too much for you to help with, though I thank you greatly for your patience and all the effort you have put in to help me.
    • I have been following these exact tutorials for quite a while, I must agree that they are amazing and easy to follow. I have registered the item in the ModFoods class, I tried to do it in ModItems (Where all the items should be registered) but got errors, I think I may need to revert this and figure it out from there. Once again, thank you for your help! 👍 Just looking back, I have noticed in your code you added ITEMS.register, which I am guessing means that they are being registered in ModFoods, I shall go through the process of trial and error to figure this out.
    • ♈+2349027025197ஜ Are you a pastor, business man or woman, politician, civil engineer, civil servant, security officer, entrepreneur, Job seeker, poor or rich Seeking how to join a brotherhood for protection and wealth here’s is your opportunity, but you should know there’s no ritual without repercussions but with the right guidance and support from this great temple your destiny is certain to be changed for the better and equally protected depending if you’re destined for greatness Call now for enquiry +2349027025197☎+2349027025197₩™ I want to join ILLUMINATI occult without human sacrificeGREATORLDRADO BROTHERHOOD OCCULT , Is The Club of the Riches and Famous; is the world oldest and largest fraternity made up of 3 Millions Members. We are one Family under one father who is the Supreme Being. In Greatorldrado BROTHERHOOD we believe that we were born in paradise and no member should struggle in this world. Hence all our new members are given Money Rewards once they join in order to upgrade their lifestyle.; interested viewers should contact us; on. +2349027025197 ۝ஐℰ+2349027025197 ₩Greatorldrado BROTHERHOOD OCCULT IS A SACRED FRATERNITY WITH A GRAND LODGE TEMPLE SITUATED IN G.R.A PHASE 1 PORT HARCOURT NIGERIA, OUR NUMBER ONE OBLIGATION IS TO MAKE EVERY INITIATE MEMBER HERE RICH AND FAMOUS IN OTHER RISE THE POWERS OF GUARDIANS OF AGE+. +2349027025197   SEARCHING ON HOW TO JOIN THE Greatorldrado BROTHERHOOD MONEY RITUAL OCCULT IS NOT THE PROBLEM BUT MAKE SURE YOU'VE THOUGHT ABOUT IT VERY WELL BEFORE REACHING US HERE BECAUSE NOT EVERYONE HAS THE HEART TO DO WHAT IT TAKES TO BECOME ONE OF US HERE, BUT IF YOU THINK YOU'RE SERIOUS MINDED AND READY TO RUN THE SPIRITUAL RACE OF LIFE IN OTHER TO ACQUIRE ALL YOU NEED HERE ON EARTH CONTACT SPIRITUAL GRANDMASTER NOW FOR INQUIRY +2349027025197   +2349027025197 Are you a pastor, business man or woman, politician, civil engineer, civil servant, security officer, entrepreneur, Job seeker, poor or rich Seeking how to join
    • Hi, I'm trying to use datagen to create json files in my own mod. This is my ModRecipeProvider class. public class ModRecipeProvider extends RecipeProvider implements IConditionBuilder { public ModRecipeProvider(PackOutput pOutput) { super(pOutput); } @Override protected void buildRecipes(Consumer<FinishedRecipe> pWriter) { ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModBlocks.COMPRESSED_DIAMOND_BLOCK.get()) .pattern("SSS") .pattern("SSS") .pattern("SSS") .define('S', ModItems.COMPRESSED_DIAMOND.get()) .unlockedBy(getHasName(ModItems.COMPRESSED_DIAMOND.get()), has(ModItems.COMPRESSED_DIAMOND.get())) .save(pWriter); ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItems.COMPRESSED_DIAMOND.get(),9) .requires(ModBlocks.COMPRESSED_DIAMOND_BLOCK.get()) .unlockedBy(getHasName(ModBlocks.COMPRESSED_DIAMOND_BLOCK.get()), has(ModBlocks.COMPRESSED_DIAMOND_BLOCK.get())) .save(pWriter); ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModItems.COMPRESSED_DIAMOND.get()) .pattern("SSS") .pattern("SSS") .pattern("SSS") .define('S', Blocks.DIAMOND_BLOCK) .unlockedBy(getHasName(ModItems.COMPRESSED_DIAMOND.get()), has(ModItems.COMPRESSED_DIAMOND.get())) .save(pWriter); } } When I try to run the runData client, it shows an error:  Caused by: java.lang.IllegalStateException: Duplicate recipe compressed:compressed_diamond I know that it's caused by the fact that there are two recipes for the ModItems.COMPRESSED_DIAMOND. But I need both of these recipes, because I need a way to craft ModItems.COMPRESSED_DIAMOND_BLOCK and restore 9 diamond blocks from ModItems.COMPRESSED_DIAMOND. Is there a way to solve this?
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.