Jump to content

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


サムエル

Recommended Posts

Think of server and client as two different computers that cannot communicate at all except through packets.

A packet is like a small message that you can send from one to the other to tell it to do a specific thing. The packet can contain data which you need to encode into bytes so it can be sent. Then the packet handler (IMessageHandler) determines what happens when the packet arrives.

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

First: in your packet you are comparing Strings using ==. That will not work! Please learn about the difference of == and .equals() in Java.

 

That code in your Block will also not work. First do not handle the client there at all, only send the packet on the server, on the client do nothing.

And all that static state there will not work! You do know what static means, right? If not: Go learn Java.

How you need to keep track of the sound depends: Is there the possibility that one player can hear the sound twice at the same time?

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

You do not need to care about SinglePlayer. SinglePlayer is exactly the same as multiplayer. There is a server and a client and they communicate via packets.

 

If you do nothing on the client playSound will execute when the packet is received. Just like in multiplayer.

 

You do not need to access it from the packet handler. The packet handler is what creates the ISound instance.

And please answer the question I raised at the end of my last post.

Link to comment
Share on other sites

Ok. Then make a field for the ISound in your ClientProxy. In the packet then call a method in your proxy that:

- Does nothing in the ServerProxy.

- In the ClientProxy either creates a new ISound, starts it, and puts it into the field or otherwise gets the sound from the field and stops it.

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

You know how inheritance works, right? ClientProxy extends the CommonProxy (CommonProxy btw. is a stupid name, it is only used on the server).

So you put the method in CommonProxy and override it in Clientproxy.

 

You do not need to separate client and server here, since your packet is only ever received on the client.

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
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.



×
×
  • Create New...

Important Information

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