Jump to content

How to use 3D SoundSystem with Forge 1.7


pingoleon60

Recommended Posts

Hello everyone.

 

I'm having a bit of trouble while coding my mod : I've searched a long time, but I don't see any way to use SoundSystem with Forge to display localised AudioStream like Jukeboxes do. I found some events but they're annoted as deprecated.

 

Anyone can explain or redirect me to a tutorial?

 

Thanks in advance!

Link to comment
Share on other sites

Well...

I'm trying to make the client download an audio file and display it.

 

For now I use this :

 

AudioInputStream audioIn = AudioSystem.getAudioInputStream(new URL(urlToReach));
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();

 

(not exactly, but that's the idea)

 

EDIT : I found where the Paul'sCode SoundSystem was managed, but unfortunatly the soundsystem itself is private.

Link to comment
Share on other sites

Oh! I've never heard about tha Reflection stuff.

 

But, I've never worked with that. I read stuff about it online, tried something :

 

SoundHandler sndHandler = Minecraft.getMinecraft().getSoundHandler();
Field sndManagerField = sndHandler.getClass().getDeclaredField("sndManager");
sndManagerField.setAccessible(true);
SoundManager mcSndManager = (SoundManager) sndManagerField.get(sndHandler);

Field sndSystemField = mcSndManager.getClass().getDeclaredField("sndSystem");
sndSystemField.setAccessible(true);
MusicManager.mcSndSystem = (SoundSystem) sndSystemField.get(mcSndManager);

 

But it seems to not work. That does not crash, but when I call that paulscode function :

 

public void loadSound( URL url, String identifier )
    {
        // Queue a command to load the sound file from a URL:
        CommandQueue( new CommandObject( CommandObject.LOAD_SOUND,
                                         new FilenameURL( url, identifier ) ) );
        // Wake the command thread to process commands:
        commandThread.interrupt();
    }

 

It crashes :

 

java.lang.NullPointerException
at paulscode.sound.SoundSystem.loadSound(SoundSystem.java:383) ~[soundSystem.class:?]
at pingo.minedisc.common.MusicManager.loadMusic(MusicManager.java:57) ~[MusicManager.class:?]
at pingo.minedisc.common.PlayMusicCommand.processCommand(PlayMusicCommand.java:54) ~[PlayMusicCommand.class:?]
at net.minecraft.command.CommandHandler.executeCommand(CommandHandler.java:96) [CommandHandler.class:?]
at net.minecraft.network.NetHandlerPlayServer.handleSlashCommand(NetHandlerPlayServer.java:788) [NetHandlerPlayServer.class:?]
at net.minecraft.network.NetHandlerPlayServer.processChatMessage(NetHandlerPlayServer.java:764) [NetHandlerPlayServer.class:?]
at net.minecraft.network.play.client.C01PacketChatMessage.processPacket(C01PacketChatMessage.java:47) [C01PacketChatMessage.class:?]
at net.minecraft.network.play.client.C01PacketChatMessage.processPacket(C01PacketChatMessage.java:68) [C01PacketChatMessage.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?]
at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:726) [MinecraftServer.class:?]
at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:614) [MinecraftServer.class:?]
at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [integratedServer.class:?]
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:485) [MinecraftServer.class:?]
at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:752) [MinecraftServer$2.class:?]

 

SoundSystem's line 383 is commandThread.interrupt();

I've searched a long time, and I can't find why it does not work.

 

Can you help me?

 

Thanks in advance.

Link to comment
Share on other sites

a) I preload it in order to be able to play it from two different places but using only one memory space.

 

b)

private static Map<String, String> loadedMusics = new HashMap<String, String>();

private final static String[][] acceptedTypes = new String[][] { new String[] { "audio/x-wav", ".wav" } };

 

MusicManager.unloadMusic(urlToReach);
		URL url = new URL(urlToReach);
		String type = url.openConnection().getContentType();
		for (String[] row : MusicManager.acceptedTypes ) {
			System.out.println("Model : " + row[0] + " comparing to " + type);
			if (type.equals(row[0])) {
				String identifier = UUID.randomUUID().toString() + row[1];
				System.out.println("Music loaded as " + identifier);
				MusicManager.mcSndSystem.loadSound(url, identifier);
				MusicManager.loadedMusics.put(urlToReach, identifier);
			}
		}

 

My bad, I should have showed you that part before, because I'm not sure if I'm really doing it ok.

Link to comment
Share on other sites

Oh ok. I called it from a command or from a TileEntity (in fact onNeighborChange from the Block call that function in the TileEntity).

 

public void processCommand(ICommandSender sender, String[] args) {
	if (args.length == 0) {
		sender.addChatMessage(new ChatComponentText("Invalid arguments."));
		return;
    }

	sender.addChatMessage(new ChatComponentText(args[0]));

	ItemStack stack = sender.getEntityWorld().getPlayerEntityByName(sender.getCommandSenderName()).getHeldItem();
	if (stack != null) {
		if (stack.getItem() == MineDisc.wifiCD) {
			if (stack.stackTagCompound == null) stack.stackTagCompound = new NBTTagCompound();
			stack.stackTagCompound.setString("musicURL", args[0]);
		}
	}
}

 

public void onNeighborBlockChange() {
	if (!worldObj.isRemote && worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord) && currentMusicURL != "") {
		if (!wasRunningMusic) {
			if (this.playingSource != null) MusicManager.stopMusic(this.playingSource);
			this.playingSource = "";
			if (MusicManager.isLoaded(this.currentMusicURL)) this.playingSource = MusicManager.playMusic(currentMusicURL, xCoord, yCoord, zCoord, 1);
			else {
				MusicManager.loadMusic(this.currentMusicURL);
				this.playingSource = MusicManager.playMusic(currentMusicURL, xCoord, yCoord, zCoord, 1);
			}
			wasRunningMusic = true;
		}
	} else {
		if (wasRunningMusic) {
			if (this.playingSource != null) MusicManager.stopMusic(this.playingSource);
			this.playingSource = "";
			wasRunningMusic = false;
		}
	}
	worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, MineDisc.CDPlayer);
}

Link to comment
Share on other sites

In fact, I only forgot to delete those SideOnly annotation, because anyway it is never called by the server (only the packet handler and the client proxy interact with MusicManager).

// While Writing Edit : Oh damn it forgot that MusicManager.stopMusic, sorry.

 

Wow. I'm really dumb, indeed. I thought like only one person would be on the server. (please don't throw me to the stake xD)

I should save sources in a map with coordinates, that would be better.

 

I'll follow your tip about cache. I thought it was more efficient, but eh, it seems to not be.

 

 

Anyway, I did all of that (updated on the github), but that's still crashing on the same part of SoundSystem. I investigated, and it looks like SoundSystem shuts down too soon.

Any idea?

 

Thanks a lot for your lot of help ^^

Link to comment
Share on other sites

Thank you very much, it now works!

 

a) I'm quite new at packets, so that was temporal, I made a string conversion only to test it faster because I didn't know methods to treat int when I wrote it x)

b) That's because I'm planning on adding other actions, but thinking of it I could only use an integer.

c) Just forgot to delete that part, sorry.

 

Thanks a lot anyway, you have been super nice in front of my stupidity xD

 

See you!

 

Link to comment
Share on other sites

Oops never mind x)

 

When I call the quickPlay method, the game freeze like 5 seconds and then it works, even if I do it from a parrallel Thread.

 

public class ThreadStartMusic extends Thread {

private String url;
private int x;
private int y;
private int z;
private long volume;

public ThreadStartMusic(String url, int x, int y, int z, long volume) {
	this.url = url;
	this.x = x;
	this.y = y;
	this.z = z;
	this.volume = volume;
}

public void run() {
	MusicManager.playingMusics.put(MusicManager.playMusic(this.url, this.x, this.y, this.z, this.volume), new int[] { this.x, this.y, this.z });
}

}

 

Anby idea?

 

Thanks in advance xD

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.



×
×
  • Create New...

Important Information

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