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.



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I would like to setup a test that makes sure an animation completes, however this animation can be a couple of seconds long. Are there any examples of using a GameTestSequence created from GameTestHelper#startSequence to wait until a certain function in the code is reached or finished?
    • Minecraft java and forge seem to have it out for me, any ideas? I have had issues with exit code 1 while loading forge -fabric was having the same issues, but I seemed to fix it in these repairs? (tried different versions upwards from 1.19 to 1.20.2 for forge, nothing worked and I'm confident older versions wouldn't either) -The launcher itself loads fine, it will load the game within the launcher, and then crash the moment it tries to load outside of the launcher. I have tried the default launcher, legacy launcher, and the curse forge launcher, none have worked! (all have had the same problem) I think this started when I took a break and upgraded to windows 11 and wonder if that changed anything? I have tried the following: uninstalled & reinstalled java, (I have having issues where I download jdk 17 but only 8 would show up (would not show up anywhere but the control panel, not even the official uninstaller, I *think* I got that fixed) tried jarfix uninstalled & reinstalled minecraft tried alternate launchers -forge & legacy, & repaired them too. tried without mods updated game drivers uninstalled and reinstalled forge -including completely wiping it from my system changed java excutable path followed everything in the error code 1 post completely reset my pc I tried to change the launch path but couldn't seem to get it to work -the default launcher wont let me even see properties as an option, i have yet to try with the other two (i did try on legacy but it was being weird) I want to include my debug log; but its over the max size? sorry my brains gone numb from trying to fix this for the past 2 days
    • I personally create registries using DataPackRegistryEvent.NewRegistry. It's pretty powerful as long as you know how to make codecs. In some class, make a registry key like so: public static final ResourceKey<Registry<MyDataType>> MY_REGISTRY = ResourceKey.createRegistryKey(new ResourceLocation(MyMod.MOD_ID, "registry_name")); This will make a registry that holds objects of type "MyDataType". JSON files stored in data/<datapack_namespace>/modid/registryname/ will be parsed and put into this registry. Note that the directory structure has a folder named after your mod inside your datapack directory, so the actual path would look like: data/my_mod/my_mod/registry_name (or if another mod uses your registry: data/their_mod/my_mod/registry_name. To register this registry, subscribe to the DataPackRegistryEvent.NewRegistry event on the MOD event bus and call event.dataPackRegistry() for every registry you have. An example of what I'm doing for my mod (this is in the constructor for the main mod file): IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); bus.addListener((DataPackRegistryEvent.NewRegistry event) -> { event.dataPackRegistry(ModRegistries.INSULATOR_DATA, InsulatorData.CODEC); }); CODEC is a public static field inside the class for the custom data type I am registering. It holds a Codec<InsulatorData> that tells Minecraft how to serialize/deserialize the data. Most of my data so far can be represented by records, so I use RecordCodecBuilder.create() to do this: public static final Codec<InsulatorData> CODEC = RecordCodecBuilder.create(instance -> instance.group( // Yadda yadda ).apply(instance, InsulatorData::new)); What exactly to put here depends on what you're trying to do, so that's up to you. But basically you're just defining a list of codecs that correspond to the parameters of the record (data type). Most primitive data types have records in the Codec class (ex. Codec.INT) that you can use, and other classes like ResourceLocation have their own codecs as a static field (ex. ResourceLocation.CODEC). Hopefully this is what you're looking for, and that this helps.
    • Good days  I finnaly manage to fix and get a working gui from BlockItem and from BlockEntity the next issues i have to fix is this the block Entity model for some reason is moved to the south west  this briefcase model must be centered but is moved to a side, i have nothing weird in the code but this is happening // ########## ########## ########## ########## @Override public RenderShape getRenderShape(BlockState blkstate) {     return RenderShape.MODEL; } the block model is out of place However The hitBox of the block is right in place   ########################################################################################################### This next issue  Mi gui also adds the 5 slots from the player equipment the thing is theres no filter to determine whats can be put in an armor slot and what not      i have this method that draws the slots for the armor, the part i dont get i slike wheres the code that responds when you set an item in a item slot to do checks and allow the item to be set or not  //########## ########## ########## //Draw Player Armor private void addPlayerArmorSlots(Inventory playerInventory) { // 36 this.addSlot(new Slot(playerInventory, 39, 8, 8)); this.addSlot(new Slot(playerInventory, 38, 8, 26)); this.addSlot(new Slot(playerInventory, 37, 8, 44)); this.addSlot(new Slot(playerInventory, 36, 8, 62)); this.addSlot(new Slot(playerInventory, 40, 26, 53)); }   theres must be a method that triggers when you set a itemstack inside an slot and allows to do a check if its a valid item for that slot                                             
    • No like how do I use my new PreperableReloadListener, I know how to set it up now and register it, I just need to know how to use it in other classes.
  • Topics

×
×
  • Create New...

Important Information

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