Immersive Vehicles (Formerly Transport Simulator)

Immersive Vehicles (Formerly Transport Simulator)

4M Downloads

Sounds turn off when changing dimensions.

Johni0702 opened this issue ยท 11 comments

commented

Johni0702/BetterPortals#167
BP allows multiple worlds to be loaded and rendered on the client by swapping out mc.world as needed.
This causes MTS's vehicle sounds to be choppy.

The cause appears to be in this piece of code:

/**
* Check for orphaned sounds, and delete them if they are present.
* We do this by verifying there is an entity with the given ID still present.
* This can happen if something changes the entityID of a vehicle mid-game.
* Usually another mod, but could be due to other reasons.
*/
@SubscribeEvent
public static void on(RenderWorldLastEvent event){
Iterator<String> soundIterator = playingSounds.iterator();
while(soundIterator.hasNext()){
String soundID = soundIterator.next();
int entityID = Integer.valueOf(soundID.substring(0, soundID.indexOf('_')));
if(Minecraft.getMinecraft().theWorld.getEntityByID(entityID) == null){
mcSoundSystem.stop(soundID);
soundIterator.remove();
}
}
}

It assumes there to only ever be one world and stops any sounds which do not have corresponding entities in that world (though that assumption may be present in other places of your sound system as well, I just didn't look at all of it).

Side note: Having your own sound system will also break BP's attempt at redirecting sounds in the remote world through portals. The issues mentioned in the comments seem minor to me, is there any major reason for circumventing MC's sound system?

commented

I'm not an official source, But one reason may be that he's added sound compression for moving vehicles

commented

The reasoning behind the SoundSystem circumvention is rather simple: Minecraft lies to you about what sounds are playing. Due to it's shoddy use of multi-threading, Minecraft doesn't play sounds right when you tell it to. Rather, it sends them to the SoundSystem thread to be played. This makes sense, as having audio on another thread keeps the main loop from blocking when that audio is queuing. What does not make sense, is that when you ask Minecraft if a sound is playing, it tells you if it told that thread to play the sound, not if the thread is actually playing that sound. This leads to the following situation:

Player Steve is trying to start an engine with too big of a propeller. He manages to get it spun up using the starter, which queues the _running sound to be started. IV does this by telling MC to play that sound, and MC goes and tells the thread to start playing it. However, due to the weak engine the RPM goes down and the engine dies in just a few ticks. Because the engine is no longer running, we need to stop any sounds. IV checks with the MC and is told that a sound is indeed playing, and asks MC to stop it.

However, due to the quick start-stop the SoundSystem thread hasn't had a chance to start that sound. When MC is told to stop it, MC goes and checks its internal list of sounds that it has told the SoundSystem to play. Since the sound is there, it assumes the thread is playing it, and tells the SoundSystem to stop that sound. Clearly there is no such sound to be stopped, and thus the game crashes.

A similar behavior can happen when MC tells the system to stop playing a sound. Since there is a small delay between a stop command and when the sound actually stops, it is possible that MC will say a sound doesn't exist even when it is actually playing. This leads to the fun time of asking MC to play a sound that is already playing if the engine starts up quickly after it shuts off, which is also a crash.

In a nutshell, MC can't code a proper sound manager, so I make my own.

commented

I don't quite follow your examples.
Just like MC doesn't immediately play sounds and instead puts them into a queue, it also puts the stop commands into the same queue. So by the time the stop command is actually executed on the audio thread, the play command will already have been executed on the same thread, so the sound will actually be playing and can be stopped just fine.
Quick stop-then-start shouldn't be an issue either if you create a new ISound object for each playSound call.

SoundManager.isSoundPlaying is nevertheless misnamed imo since it does check whether a sound is actually live as opposed to playSound/stopSound (i.e. there's no guarantee that calling playSound-stopSound-isSoundPlaying in that order will return false).
I don't see any actual use-case for it though (your SFXSystem doesn't even expose an equivalent method), so it shouldn't be an issue.

commented

I could be mistaken about the examples, but I distinctly remember getting crashes for adding sounds that already existed due to MC telling me they didn't when they did, and those crashes happened when players were starting and stopping engines quickly. The only way I could find to get reliable information on what sound is actually playing or not was to bypass MC's SoundManager wrapper class and roll my own. The checker code for entities is due to MC (or mods, not sure which of the two) re-assigning the Entity ID's for entities mid-game. This confuses my SoundSystem, as it uses those IDs to link sounds to entities. If you re-assign the ID, then the system will play a second sound for that entity, and when that entity dies, only that second sound will stop.

MC does allow for doppler effects with its default implementation, so while SnaveSuit is correct about me adding such things, the custom SoundSystem isn't needed to do that. Interestingly, there is a doppler effect built-in to the PaulsCode back-end, but MC doesn't use it. I felt it best to not use it either, as it could mess up things.

commented

Would you consider giving the vanilla sound system another chance? It seems to work fine for every other mod I've come across so far and seems by far the easiest way to get MTS compatible with BP.

It's probably also the only way to have all of BP's features working with MTS because I don't see myself supporting third-party sound systems until I'm convinced that the vanilla one is fundamentally flawed (and so long as you consider SoundManager.isSoundPlaying to simply be misnamed, I cannot find that flaw from staring at it).

commented

I don't know about that. I checked my commits, and it looks like the errors I was getting were ConcurrentModificationExceptions. To my recollection, that was due to adding sounds to the queue that were already there and being attempted to be played on that thread. In particular, this commit was where I changed the system. Perhaps you can tell me what I was doing wrong to get such errors? If you aren't marking entities as dead, I can see about checking the entity classes I cache to see if they are dead or inactive and remove sounds that way, but having the world variable swapped out constantly does break a lot of assumptions in my code...

c3ff5ae#diff-512a3ed5bf088a2f81228b13fe40cc1a

commented

@Johni0702 @SnaveSutit So I've gone and overhauled the entire sound system in this latest version of MTS (V17.4.0). Would either of y'all be able to re-test this bug and let me know if it still exists?

commented

Just tested 17.3.1 vs 17.4.2 (with BP 0.3.7.7), the main choppiness issue appears to be fixed.
AFAICT there are only two minor issues remaining:

  • Vehicle sounds cannot be heard through a portal, i.e. if I place a car in front of a portal in the overworld and go through that portal, the sound abruptly disappears (probably because of the difference in player position?), going back makes it reappear.
    I wouldn't expect this to be fixed until MC's sound system provides everything which MTS needs since this requires deep integration with BP.
  • All vehicle sounds stop when any world is unloaded, i.e. if I place a car in front of the only portal in the overworld, then break it (which will cause the nether to be unloaded), the car sound will be stopped as well, even though the overworld and the car are still loaded.

Since both of those are fairly minor and the first one is more just for the record than asking for a fix, if you don't think it's easily feasible to fix the latter one, then feel free to close this issue.

commented

No, the latter one is for sure a feasible fix. That's due to how MC handles the game unloading. If you're in singleplayer and exit the game, none of the entities are marked as dead, so the sounds keep playing. To combat this, I check if the world is unloaded and when it is I stop all the sounds. Clearly I need to only stop the sounds of the vehicles in the specific world that is unloaded, or find another event to trigger the sound stoppages. I should be able to test this on my end as it's a MC-based thing with the Nether. Will fix and close this ticket when done.

And yes, the sound issue is due to position. Come to think of it, if you were in the same position in the nether as a vehicle in the loaded overworld you'd probably hear the sound of that vehicle. Though that's not really likely unless that portal is by spawn which stays chunkloaded, as on clients the overworld unloads all but that section. Does BP keep the chunks by the portal loaded on both worlds?

commented

This will be fixed in V18.0.0. Would post a video, but MP4 ain't allowed.

commented

Fixed in V18.0.0.