mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
Fixed and completely refactored game music playing and categories choosing
This commit is contained in:
parent
515c22f50d
commit
dca3bf2bc3
|
|
@ -18,6 +18,10 @@ void ConsoleSoundEngine::SetIsPlayingStreamingGameMusic(bool bVal)
|
||||||
{
|
{
|
||||||
m_bIsPlayingStreamingGameMusic=bVal;
|
m_bIsPlayingStreamingGameMusic=bVal;
|
||||||
}
|
}
|
||||||
|
bool ConsoleSoundEngine::GetIsPlayingMenuMusic()
|
||||||
|
{
|
||||||
|
return m_bIsPlayingMenuMusic;
|
||||||
|
}
|
||||||
bool ConsoleSoundEngine::GetIsPlayingEndMusic()
|
bool ConsoleSoundEngine::GetIsPlayingEndMusic()
|
||||||
{
|
{
|
||||||
return m_bIsPlayingEndMusic;
|
return m_bIsPlayingEndMusic;
|
||||||
|
|
@ -26,6 +30,10 @@ bool ConsoleSoundEngine::GetIsPlayingNetherMusic()
|
||||||
{
|
{
|
||||||
return m_bIsPlayingNetherMusic;
|
return m_bIsPlayingNetherMusic;
|
||||||
}
|
}
|
||||||
|
void ConsoleSoundEngine::SetIsPlayingMenuMusic(bool bVal)
|
||||||
|
{
|
||||||
|
m_bIsPlayingMenuMusic = bVal;
|
||||||
|
}
|
||||||
void ConsoleSoundEngine::SetIsPlayingEndMusic(bool bVal)
|
void ConsoleSoundEngine::SetIsPlayingEndMusic(bool bVal)
|
||||||
{
|
{
|
||||||
m_bIsPlayingEndMusic=bVal;
|
m_bIsPlayingEndMusic=bVal;
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,11 @@ public:
|
||||||
virtual bool GetIsPlayingStreamingGameMusic() ;
|
virtual bool GetIsPlayingStreamingGameMusic() ;
|
||||||
virtual void SetIsPlayingStreamingCDMusic(bool bVal) ;
|
virtual void SetIsPlayingStreamingCDMusic(bool bVal) ;
|
||||||
virtual void SetIsPlayingStreamingGameMusic(bool bVal) ;
|
virtual void SetIsPlayingStreamingGameMusic(bool bVal) ;
|
||||||
|
virtual bool GetIsPlayingMenuMusic();
|
||||||
virtual bool GetIsPlayingEndMusic() ;
|
virtual bool GetIsPlayingEndMusic() ;
|
||||||
virtual bool GetIsPlayingNetherMusic() ;
|
virtual bool GetIsPlayingNetherMusic() ;
|
||||||
virtual void SetIsPlayingEndMusic(bool bVal) ;
|
virtual void SetIsPlayingEndMusic(bool bVal) ;
|
||||||
|
virtual void SetIsPlayingMenuMusic(bool bVal);
|
||||||
virtual void SetIsPlayingNetherMusic(bool bVal) ;
|
virtual void SetIsPlayingNetherMusic(bool bVal) ;
|
||||||
static const WCHAR *wchSoundNames[eSoundType_MAX];
|
static const WCHAR *wchSoundNames[eSoundType_MAX];
|
||||||
static const WCHAR *wchUISoundNames[eSFX_MAX];
|
static const WCHAR *wchUISoundNames[eSFX_MAX];
|
||||||
|
|
@ -94,6 +96,7 @@ private:
|
||||||
|
|
||||||
bool m_bIsPlayingStreamingCDMusic;
|
bool m_bIsPlayingStreamingCDMusic;
|
||||||
bool m_bIsPlayingStreamingGameMusic;
|
bool m_bIsPlayingStreamingGameMusic;
|
||||||
|
bool m_bIsPlayingMenuMusic;
|
||||||
bool m_bIsPlayingEndMusic;
|
bool m_bIsPlayingEndMusic;
|
||||||
bool m_bIsPlayingNetherMusic;
|
bool m_bIsPlayingNetherMusic;
|
||||||
};
|
};
|
||||||
97
Minecraft.Client/Common/Audio/MusicTrackManager.cpp
Normal file
97
Minecraft.Client/Common/Audio/MusicTrackManager.cpp
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "MusicTrackManager.h"
|
||||||
|
#include "../Minecraft.World/Random.h"
|
||||||
|
|
||||||
|
MusicTrackManager::MusicTrackManager(Random* rng)
|
||||||
|
: m_random(rng)
|
||||||
|
{
|
||||||
|
// The domains will be filled later via setDomainRange().
|
||||||
|
}
|
||||||
|
|
||||||
|
MusicTrackManager::~MusicTrackManager()
|
||||||
|
{
|
||||||
|
// unordered_map will automatically destroy its DomainInfo objects,
|
||||||
|
// which in turn delete[] the heard arrays.
|
||||||
|
}
|
||||||
|
|
||||||
|
void MusicTrackManager::setDomainRange(Domain domain, int minIdx, int maxIdx)
|
||||||
|
{
|
||||||
|
assert(minIdx <= maxIdx);
|
||||||
|
// Use emplace to construct the DomainInfo in-place.
|
||||||
|
// If the domain already exists, this will replace it (C++17).
|
||||||
|
m_domains.erase(domain); // Remove old entry if any
|
||||||
|
m_domains.emplace(domain, DomainInfo(minIdx, maxIdx));
|
||||||
|
}
|
||||||
|
|
||||||
|
int MusicTrackManager::selectTrack(Domain domain)
|
||||||
|
{
|
||||||
|
// Special case: if domain is None, return -1 (no track).
|
||||||
|
if (domain == Domain::None)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
DomainInfo& info = getInfo(domain);
|
||||||
|
|
||||||
|
// If range contains only one track, just return that track.
|
||||||
|
if (info.trackCount == 1)
|
||||||
|
return info.minIdx;
|
||||||
|
|
||||||
|
// Check whether all tracks have been heard.
|
||||||
|
bool allHeard = true;
|
||||||
|
for (int i = 0; i < info.trackCount; ++i)
|
||||||
|
{
|
||||||
|
if (!info.heard[i])
|
||||||
|
{
|
||||||
|
allHeard = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all tracks have been heard, reset the heard flags.
|
||||||
|
if (allHeard)
|
||||||
|
{
|
||||||
|
std::memset(info.heard, 0, sizeof(bool) * info.trackCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try up to (trackCount/2 + 1) times to pick a track that hasn't been heard.
|
||||||
|
// This biases toward unplayed tracks but doesn't guarantee it if the random
|
||||||
|
// keeps hitting played ones. It's a compromise between fairness and performance.
|
||||||
|
const int maxAttempts = info.trackCount / 2 + 1;
|
||||||
|
for (int attempt = 0; attempt < maxAttempts; ++attempt)
|
||||||
|
{
|
||||||
|
int idx = m_random->nextInt(info.trackCount); // 0 .. trackCount-1
|
||||||
|
if (!info.heard[idx])
|
||||||
|
{
|
||||||
|
info.heard[idx] = true;
|
||||||
|
return info.minIdx + idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: if we couldn't find an unplayed track (should be rare),
|
||||||
|
// just pick any random track and mark it as heard.
|
||||||
|
int fallbackIdx = m_random->nextInt(info.trackCount);
|
||||||
|
info.heard[fallbackIdx] = true;
|
||||||
|
return info.minIdx + fallbackIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MusicTrackManager::resetDomain(Domain domain)
|
||||||
|
{
|
||||||
|
DomainInfo& info = getInfo(domain);
|
||||||
|
std::memset(info.heard, 0, sizeof(bool) * info.trackCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- private helpers ----------
|
||||||
|
|
||||||
|
MusicTrackManager::DomainInfo& MusicTrackManager::getInfo(Domain domain)
|
||||||
|
{
|
||||||
|
auto it = m_domains.find(domain);
|
||||||
|
assert(it != m_domains.end() && "Domain not initialized. Call setDomainRange first.");
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MusicTrackManager::DomainInfo& MusicTrackManager::getInfo(Domain domain) const
|
||||||
|
{
|
||||||
|
auto it = m_domains.find(domain);
|
||||||
|
assert(it != m_domains.end() && "Domain not initialized.");
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
117
Minecraft.Client/Common/Audio/MusicTrackManager.h
Normal file
117
Minecraft.Client/Common/Audio/MusicTrackManager.h
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <cstring> // for memset
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// Forward declaration of the random number generator used by SoundEngine.
|
||||||
|
// Replace with your actual random class if different.
|
||||||
|
class Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages selection of music tracks across different gameplay domains
|
||||||
|
* (Menu, Overworld Survival, Overworld Creative, Nether, End).
|
||||||
|
* Each domain maintains its own range of track indices and a history
|
||||||
|
* of recently played tracks to avoid immediate repetition.
|
||||||
|
*/
|
||||||
|
class MusicTrackManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Enumeration of all music domains. The values match the original
|
||||||
|
// SoundEngine constants for easy conversion.
|
||||||
|
enum class Domain
|
||||||
|
{
|
||||||
|
Menu = -1,
|
||||||
|
OverworldSurvival = 0,
|
||||||
|
OverworldCreative = 1,
|
||||||
|
Nether = 2,
|
||||||
|
End = 3,
|
||||||
|
None = 4 // Special value for when no background music should play (e.g., during a music disc)
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param rng Pointer to a random number generator (must remain valid).
|
||||||
|
*/
|
||||||
|
explicit MusicTrackManager(Random* rng);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor – frees all dynamically allocated heard-track arrays.
|
||||||
|
*/
|
||||||
|
~MusicTrackManager();
|
||||||
|
|
||||||
|
// Prevent copying (to avoid double deletion of internal arrays).
|
||||||
|
MusicTrackManager(const MusicTrackManager&) = delete;
|
||||||
|
MusicTrackManager& operator=(const MusicTrackManager&) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the inclusive index range for a given domain.
|
||||||
|
* @param domain The music domain.
|
||||||
|
* @param minIdx First valid track index.
|
||||||
|
* @param maxIdx Last valid track index (must be >= minIdx).
|
||||||
|
*/
|
||||||
|
void setDomainRange(Domain domain, int minIdx, int maxIdx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects a track index for the specified domain.
|
||||||
|
* Tries to return a track that has not been played recently;
|
||||||
|
* if all tracks have been played, resets the history and picks one randomly.
|
||||||
|
* For domains with only one track, that track is always returned.
|
||||||
|
* @param domain The domain for which to choose a track.
|
||||||
|
* @return A valid track index within the domain's range.
|
||||||
|
*/
|
||||||
|
int selectTrack(Domain domain);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the heard history for a domain, marking all tracks as "not heard".
|
||||||
|
* Useful when switching domains or after a major game state change.
|
||||||
|
* @param domain The domain to reset.
|
||||||
|
*/
|
||||||
|
void resetDomain(Domain domain);
|
||||||
|
|
||||||
|
int getDomainMin(Domain d) const { return getInfo(d).minIdx; }
|
||||||
|
int getDomainMax(Domain d) const { return getInfo(d).maxIdx; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Internal structure storing range and heard-array for a domain.
|
||||||
|
struct DomainInfo
|
||||||
|
{
|
||||||
|
int minIdx; // First track index (inclusive)
|
||||||
|
int maxIdx; // Last track index (inclusive)
|
||||||
|
int trackCount; // Number of tracks in this domain
|
||||||
|
bool* heard; // Dynamic array: heard[i] == true if track (minIdx + i) has been played recently
|
||||||
|
|
||||||
|
DomainInfo(int minVal = 0, int maxVal = 0)
|
||||||
|
: minIdx(minVal), maxIdx(maxVal), trackCount(maxVal - minVal + 1)
|
||||||
|
{
|
||||||
|
heard = new bool[trackCount](); // value-initialized to false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move constructor (optional, but needed if we want to store in unordered_map with emplace)
|
||||||
|
DomainInfo(DomainInfo&& other) noexcept
|
||||||
|
: minIdx(other.minIdx), maxIdx(other.maxIdx), trackCount(other.trackCount), heard(other.heard)
|
||||||
|
{
|
||||||
|
other.heard = nullptr; // prevent double deletion
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~DomainInfo()
|
||||||
|
{
|
||||||
|
delete[] heard;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No copy
|
||||||
|
DomainInfo(const DomainInfo&) = delete;
|
||||||
|
DomainInfo& operator=(const DomainInfo&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Map from Domain to its info.
|
||||||
|
std::unordered_map<Domain, DomainInfo> m_domains;
|
||||||
|
|
||||||
|
// Pointer to the random number generator.
|
||||||
|
Random* m_random;
|
||||||
|
|
||||||
|
// Helper to get the info for a domain (assumes domain exists).
|
||||||
|
DomainInfo& getInfo(Domain domain);
|
||||||
|
const DomainInfo& getInfo(Domain domain) const;
|
||||||
|
};
|
||||||
|
|
@ -114,6 +114,9 @@ const char *SoundEngine::m_szStreamFileA[eStream_Max]=
|
||||||
"hal4",
|
"hal4",
|
||||||
"nuance1",
|
"nuance1",
|
||||||
"nuance2",
|
"nuance2",
|
||||||
|
"piano1",
|
||||||
|
"piano2",
|
||||||
|
"piano3", // 11
|
||||||
|
|
||||||
#ifndef _XBOX
|
#ifndef _XBOX
|
||||||
"creative1",
|
"creative1",
|
||||||
|
|
@ -121,26 +124,23 @@ const char *SoundEngine::m_szStreamFileA[eStream_Max]=
|
||||||
"creative3",
|
"creative3",
|
||||||
"creative4",
|
"creative4",
|
||||||
"creative5",
|
"creative5",
|
||||||
"creative6",
|
"creative6", // 17
|
||||||
|
|
||||||
"menu1",
|
"menu1",
|
||||||
"menu2",
|
"menu2",
|
||||||
"menu3",
|
"menu3",
|
||||||
"menu4",
|
"menu4", // 21
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
"piano1",
|
|
||||||
"piano2",
|
|
||||||
"piano3",
|
|
||||||
|
|
||||||
// Nether
|
// Nether
|
||||||
"nether1",
|
"nether1",
|
||||||
"nether2",
|
"nether2",
|
||||||
"nether3",
|
"nether3",
|
||||||
"nether4",
|
"nether4", // 25
|
||||||
|
|
||||||
// The End
|
// The End
|
||||||
"the_end_dragon_alive",
|
"the_end_dragon_alive",
|
||||||
"the_end_end",
|
"the_end_end", // 27
|
||||||
|
|
||||||
// CDs
|
// CDs
|
||||||
"11",
|
"11",
|
||||||
|
|
@ -191,23 +191,22 @@ void SoundEngine::init(Options* pOptions)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundEngine::SetStreamingSounds(int iOverworldMin, int iOverWorldMax, int iNetherMin, int iNetherMax, int iEndMin, int iEndMax, int iCD1)
|
void SoundEngine::SetStreamingSounds(int iMenuMin, int iMenuMax,
|
||||||
|
int iOverworldSurvivalMin, int iOverWorldSurvivalMax,
|
||||||
|
int iOverworldCreativeMin, int iOverWorldCreativeMax,
|
||||||
|
int iNetherMin, int iNetherMax,
|
||||||
|
int iEndMin, int iEndMax,
|
||||||
|
int iCD1)
|
||||||
{
|
{
|
||||||
m_iStream_Overworld_Min=iOverworldMin;
|
using Domain = MusicTrackManager::Domain;
|
||||||
m_iStream_Overworld_Max=iOverWorldMax;
|
|
||||||
m_iStream_Nether_Min=iNetherMin;
|
|
||||||
m_iStream_Nether_Max=iNetherMax;
|
|
||||||
m_iStream_End_Min=iEndMin;
|
|
||||||
m_iStream_End_Max=iEndMax;
|
|
||||||
m_iStream_CD_1=iCD1;
|
|
||||||
|
|
||||||
// array to monitor recently played tracks
|
m_musicTrackManager.setDomainRange(Domain::Menu, iMenuMin, iMenuMax);
|
||||||
if(m_bHeardTrackA)
|
m_musicTrackManager.setDomainRange(Domain::OverworldSurvival, iOverworldSurvivalMin, iOverWorldSurvivalMax);
|
||||||
{
|
m_musicTrackManager.setDomainRange(Domain::OverworldCreative, iOverworldCreativeMin, iOverWorldCreativeMax);
|
||||||
delete [] m_bHeardTrackA;
|
m_musicTrackManager.setDomainRange(Domain::Nether, iNetherMin, iNetherMax);
|
||||||
}
|
m_musicTrackManager.setDomainRange(Domain::End, iEndMin, iEndMax);
|
||||||
m_bHeardTrackA = new bool[iEndMax+1];
|
|
||||||
memset(m_bHeardTrackA,0,sizeof(bool)*iEndMax+1);
|
m_iStream_CD_1 = iCD1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundEngine::updateMiniAudio()
|
void SoundEngine::updateMiniAudio()
|
||||||
|
|
@ -391,9 +390,8 @@ void SoundEngine::tick(shared_ptr<Mob> *players, float a)
|
||||||
// SoundEngine
|
// SoundEngine
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
SoundEngine::SoundEngine()
|
SoundEngine::SoundEngine(): random(new Random()), m_musicTrackManager(random), m_currentMusicDomain(MusicTrackManager::Domain::Menu)
|
||||||
{
|
{
|
||||||
random = new Random();
|
|
||||||
memset(&m_engine, 0, sizeof(ma_engine));
|
memset(&m_engine, 0, sizeof(ma_engine));
|
||||||
memset(&m_engineConfig, 0, sizeof(ma_engine_config));
|
memset(&m_engineConfig, 0, sizeof(ma_engine_config));
|
||||||
m_musicStreamActive = false;
|
m_musicStreamActive = false;
|
||||||
|
|
@ -401,15 +399,29 @@ SoundEngine::SoundEngine()
|
||||||
m_iMusicDelay=0;
|
m_iMusicDelay=0;
|
||||||
m_validListenerCount=0;
|
m_validListenerCount=0;
|
||||||
|
|
||||||
m_bHeardTrackA=nullptr;
|
m_musicTrackManager.setDomainRange(MusicTrackManager::Domain::Menu,
|
||||||
|
eStream_Overworld_Menu1,
|
||||||
|
eStream_Overworld_Menu4);
|
||||||
|
|
||||||
// Start the streaming music playing some music from the overworld
|
m_musicTrackManager.setDomainRange(MusicTrackManager::Domain::OverworldSurvival,
|
||||||
SetStreamingSounds(eStream_Overworld_Calm1,eStream_Overworld_piano3,
|
eStream_Overworld_Calm1,
|
||||||
eStream_Nether1,eStream_Nether4,
|
eStream_Overworld_piano3);
|
||||||
eStream_end_dragon,eStream_end_end,
|
|
||||||
eStream_CD_1);
|
|
||||||
|
|
||||||
m_musicID=getMusicID(LevelData::DIMENSION_OVERWORLD);
|
m_musicTrackManager.setDomainRange(MusicTrackManager::Domain::OverworldCreative,
|
||||||
|
eStream_Overworld_Creative1,
|
||||||
|
eStream_Overworld_Creative6);
|
||||||
|
|
||||||
|
m_musicTrackManager.setDomainRange(MusicTrackManager::Domain::Nether,
|
||||||
|
eStream_Nether1,
|
||||||
|
eStream_Nether4);
|
||||||
|
|
||||||
|
m_musicTrackManager.setDomainRange(MusicTrackManager::Domain::End,
|
||||||
|
eStream_end_dragon,
|
||||||
|
eStream_end_end);
|
||||||
|
|
||||||
|
m_iStream_CD_1 = eStream_CD_1;
|
||||||
|
|
||||||
|
m_musicID = getTrackForDomain(MusicTrackManager::Domain::Menu);
|
||||||
|
|
||||||
m_StreamingAudioInfo.bIs3D=false;
|
m_StreamingAudioInfo.bIs3D=false;
|
||||||
m_StreamingAudioInfo.x=0;
|
m_StreamingAudioInfo.x=0;
|
||||||
|
|
@ -660,12 +672,36 @@ void SoundEngine::playUI(int iSound, float volume, float pitch)
|
||||||
// playStreaming
|
// playStreaming
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
MusicTrackManager::Domain SoundEngine::determineCurrentMusicDomain() const
|
||||||
|
{
|
||||||
|
Minecraft* mc = Minecraft::GetInstance();
|
||||||
|
if (!mc || !mc->level)
|
||||||
|
return MusicTrackManager::Domain::Menu;
|
||||||
|
|
||||||
|
bool inEnd = false, inNether = false, creative = false;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < MAX_LOCAL_PLAYERS; ++i)
|
||||||
|
{
|
||||||
|
auto player = mc->localplayers[i];
|
||||||
|
if (!player) continue;
|
||||||
|
|
||||||
|
if (player->dimension == LevelData::DIMENSION_END)
|
||||||
|
inEnd = true;
|
||||||
|
else if (player->dimension == LevelData::DIMENSION_NETHER)
|
||||||
|
inNether = true;
|
||||||
|
|
||||||
|
if (player->level->getLevelData()->getGameType()->isCreative())
|
||||||
|
creative = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inEnd) return MusicTrackManager::Domain::End;
|
||||||
|
if (inNether) return MusicTrackManager::Domain::Nether;
|
||||||
|
if (creative) return MusicTrackManager::Domain::OverworldCreative;
|
||||||
|
return MusicTrackManager::Domain::OverworldSurvival;
|
||||||
|
}
|
||||||
|
|
||||||
void SoundEngine::playStreaming(const wstring& name, float x, float y, float z, float volume, float pitch, bool bMusicDelay)
|
void SoundEngine::playStreaming(const wstring& name, float x, float y, float z, float volume, float pitch, bool bMusicDelay)
|
||||||
{
|
{
|
||||||
// This function doesn't actually play a streaming sound, just sets states and an id for the music tick to play it
|
|
||||||
// Level audio will be played when a play with an empty name comes in
|
|
||||||
// CD audio will be played when a named stream comes in
|
|
||||||
|
|
||||||
m_StreamingAudioInfo.x = x;
|
m_StreamingAudioInfo.x = x;
|
||||||
m_StreamingAudioInfo.y = y;
|
m_StreamingAudioInfo.y = y;
|
||||||
m_StreamingAudioInfo.z = z;
|
m_StreamingAudioInfo.z = z;
|
||||||
|
|
@ -673,163 +709,43 @@ void SoundEngine::playStreaming(const wstring& name, float x, float y , float z,
|
||||||
m_StreamingAudioInfo.pitch = pitch;
|
m_StreamingAudioInfo.pitch = pitch;
|
||||||
|
|
||||||
if (m_StreamState == eMusicStreamState_Playing)
|
if (m_StreamState == eMusicStreamState_Playing)
|
||||||
{
|
|
||||||
m_StreamState = eMusicStreamState_Stop;
|
m_StreamState = eMusicStreamState_Stop;
|
||||||
}
|
|
||||||
else if (m_StreamState == eMusicStreamState_Opening)
|
else if (m_StreamState == eMusicStreamState_Opening)
|
||||||
{
|
|
||||||
m_StreamState = eMusicStreamState_OpeningCancel;
|
m_StreamState = eMusicStreamState_OpeningCancel;
|
||||||
}
|
|
||||||
|
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
{
|
{
|
||||||
// music, or stop CD
|
|
||||||
m_StreamingAudioInfo.bIs3D = false;
|
m_StreamingAudioInfo.bIs3D = false;
|
||||||
|
m_iMusicDelay = bMusicDelay ? random->nextInt(20 * 60 * 3) : 0;
|
||||||
// we need a music id
|
|
||||||
// random delay of up to 3 minutes for music
|
|
||||||
m_iMusicDelay = random->nextInt(20 * 60 * 3);//random->nextInt(20 * 60 * 10) + 20 * 60 * 10;
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
m_iMusicDelay = 0;
|
m_iMusicDelay = 0;
|
||||||
#endif
|
#endif
|
||||||
Minecraft *pMinecraft=Minecraft::GetInstance();
|
|
||||||
|
|
||||||
bool playerInEnd=false;
|
MusicTrackManager::Domain domain = determineCurrentMusicDomain();
|
||||||
bool playerInNether=false;
|
m_currentMusicDomain = domain;
|
||||||
|
m_musicID = getTrackForDomain(domain);
|
||||||
for(unsigned int i=0;i<MAX_LOCAL_PLAYERS;i++)
|
|
||||||
{
|
|
||||||
if(pMinecraft->localplayers[i]!=nullptr)
|
|
||||||
{
|
|
||||||
if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_END)
|
|
||||||
{
|
|
||||||
playerInEnd=true;
|
|
||||||
}
|
|
||||||
else if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_NETHER)
|
|
||||||
{
|
|
||||||
playerInNether=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(playerInEnd)
|
|
||||||
{
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_END);
|
|
||||||
}
|
|
||||||
else if(playerInNether)
|
|
||||||
{
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_NETHER);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_OVERWORLD);
|
// Disk (jukebox)
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// jukebox
|
|
||||||
m_StreamingAudioInfo.bIs3D = true;
|
m_StreamingAudioInfo.bIs3D = true;
|
||||||
m_musicID = getMusicID(name);
|
m_musicID = getMusicID(name);
|
||||||
m_iMusicDelay = 0;
|
m_iMusicDelay = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int SoundEngine::GetRandomishTrack(int iStart,int iEnd)
|
|
||||||
{
|
|
||||||
// 4J-PB - make it more likely that we'll get a track we've not heard for a while, although repeating tracks sometimes is fine
|
|
||||||
|
|
||||||
// if all tracks have been heard, clear the flags
|
|
||||||
bool bAllTracksHeard=true;
|
|
||||||
int iVal=iStart;
|
|
||||||
for(size_t i=iStart;i<=iEnd;i++)
|
|
||||||
{
|
|
||||||
if(m_bHeardTrackA[i]==false)
|
|
||||||
{
|
|
||||||
bAllTracksHeard=false;
|
|
||||||
app.DebugPrintf("Not heard all tracks yet\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bAllTracksHeard)
|
|
||||||
{
|
|
||||||
app.DebugPrintf("Heard all tracks - resetting the tracking array\n");
|
|
||||||
|
|
||||||
for(size_t i=iStart;i<=iEnd;i++)
|
|
||||||
{
|
|
||||||
m_bHeardTrackA[i]=false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// trying to get a track we haven't heard, but not too hard
|
|
||||||
for(size_t i=0;i<=((iEnd-iStart)/2);i++)
|
|
||||||
{
|
|
||||||
// random->nextInt(1) will always return 0
|
|
||||||
iVal=random->nextInt((iEnd-iStart)+1)+iStart;
|
|
||||||
if(m_bHeardTrackA[iVal]==false)
|
|
||||||
{
|
|
||||||
// not heard this
|
|
||||||
app.DebugPrintf("(%d) Not heard track %d yet, so playing it now\n",i,iVal);
|
|
||||||
m_bHeardTrackA[iVal]=true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
app.DebugPrintf("(%d) Skipping track %d already heard it recently\n",i,iVal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
app.DebugPrintf("Select track %d\n",iVal);
|
|
||||||
return iVal;
|
|
||||||
}
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// getMusicID
|
// getTrackForDomain(MusicTrackManager::Domain domain)
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
int SoundEngine::getMusicID(int iDomain)
|
int SoundEngine::getTrackForDomain(MusicTrackManager::Domain domain)
|
||||||
{
|
{
|
||||||
int iRandomVal=0;
|
if (domain == MusicTrackManager::Domain::End)
|
||||||
Minecraft *pMinecraft=Minecraft::GetInstance();
|
return m_musicTrackManager.getDomainMin(domain);
|
||||||
|
|
||||||
// Before the game has started?
|
|
||||||
if(pMinecraft==nullptr)
|
|
||||||
{
|
|
||||||
// any track from the overworld
|
|
||||||
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pMinecraft->skins->isUsingDefaultSkin())
|
|
||||||
{
|
|
||||||
switch(iDomain)
|
|
||||||
{
|
|
||||||
case LevelData::DIMENSION_END:
|
|
||||||
// the end isn't random - it has different music depending on whether the dragon is alive or not, but we've not added the dead dragon music yet
|
|
||||||
return m_iStream_End_Min;
|
|
||||||
case LevelData::DIMENSION_NETHER:
|
|
||||||
return GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
|
|
||||||
//return m_iStream_Nether_Min + random->nextInt(m_iStream_Nether_Max-m_iStream_Nether_Min);
|
|
||||||
default: //overworld
|
|
||||||
//return m_iStream_Overworld_Min + random->nextInt(m_iStream_Overworld_Max-m_iStream_Overworld_Min);
|
|
||||||
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
return m_musicTrackManager.selectTrack(domain);
|
||||||
// using a texture pack - may have multiple End music tracks
|
|
||||||
switch(iDomain)
|
|
||||||
{
|
|
||||||
case LevelData::DIMENSION_END:
|
|
||||||
return GetRandomishTrack(m_iStream_End_Min,m_iStream_End_Max);
|
|
||||||
case LevelData::DIMENSION_NETHER:
|
|
||||||
//return m_iStream_Nether_Min + random->nextInt(m_iStream_Nether_Max-m_iStream_Nether_Min);
|
|
||||||
return GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
|
|
||||||
default: //overworld
|
|
||||||
//return m_iStream_Overworld_Min + random->nextInt(m_iStream_Overworld_Max-m_iStream_Overworld_Min);
|
|
||||||
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
|
@ -958,23 +874,34 @@ void SoundEngine::playMusicTick()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// AP - moved to a separate function so it can be called from the mixer callback on Vita
|
//=============================================================================
|
||||||
|
// playMusicUpdate
|
||||||
|
// Called every frame (or via mixer callback on Vita) to manage streaming music.
|
||||||
|
// Handles state machine for background music and music discs (jukebox).
|
||||||
|
//=============================================================================
|
||||||
void SoundEngine::playMusicUpdate()
|
void SoundEngine::playMusicUpdate()
|
||||||
{
|
{
|
||||||
static float fMusicVol = 0.0f;
|
// Cache the current master music volume (may be zero if system music is playing)
|
||||||
fMusicVol = getMasterMusicVolume();
|
float masterVolume = getMasterMusicVolume();
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// State machine for streaming audio (background music or discs)
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
switch (m_StreamState)
|
switch (m_StreamState)
|
||||||
{
|
{
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// IDLE – no stream is open; waiting for a delay or ready to start
|
||||||
|
//---------------------------------------------------------------------
|
||||||
case eMusicStreamState_Idle:
|
case eMusicStreamState_Idle:
|
||||||
|
{
|
||||||
// start a stream playing
|
// If a delay is active (e.g., between tracks), decrement and wait
|
||||||
if (m_iMusicDelay > 0)
|
if (m_iMusicDelay > 0)
|
||||||
{
|
{
|
||||||
m_iMusicDelay--;
|
m_iMusicDelay--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanity check: if a stream is already active, something went wrong
|
||||||
if (m_musicStreamActive)
|
if (m_musicStreamActive)
|
||||||
{
|
{
|
||||||
app.DebugPrintf("WARNING: m_musicStreamActive already true in Idle state, resetting to Playing\n");
|
app.DebugPrintf("WARNING: m_musicStreamActive already true in Idle state, resetting to Playing\n");
|
||||||
|
|
@ -982,15 +909,20 @@ void SoundEngine::playMusicUpdate()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_musicID!=-1)
|
// If no track ID is selected, fallback to a default (should not happen)
|
||||||
|
if (m_musicID == -1)
|
||||||
{
|
{
|
||||||
// start playing it
|
m_musicID = m_musicTrackManager.selectTrack(MusicTrackManager::Domain::Menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the full file path for the selected music ID.
|
||||||
|
// This block handles platform-specific paths, DLC/mash-up packs, and CD music.
|
||||||
|
// The result is stored in m_szStreamName.
|
||||||
|
{
|
||||||
|
// Start with the base music path (platform‑dependent)
|
||||||
#if (defined __PS3__ || defined __PSVITA__ || defined __ORBIS__)
|
#if (defined __PS3__ || defined __PSVITA__ || defined __ORBIS__)
|
||||||
|
|
||||||
#ifdef __PS3__
|
#ifdef __PS3__
|
||||||
// 4J-PB - Need to check if we are a patched BD build
|
// PS3 special case: booted from disc patch vs. installed data
|
||||||
if (app.GetBootedFromDiscPatch())
|
if (app.GetBootedFromDiscPatch())
|
||||||
{
|
{
|
||||||
sprintf(m_szStreamName, "%s/%s", app.GetBDUsrDirPath(m_szMusicPath), m_szMusicPath);
|
sprintf(m_szStreamName, "%s/%s", app.GetBDUsrDirPath(m_szMusicPath), m_szMusicPath);
|
||||||
|
|
@ -1001,17 +933,18 @@ void SoundEngine::playMusicUpdate()
|
||||||
sprintf(m_szStreamName, "%s/%s", getUsrDirPath(), m_szMusicPath);
|
sprintf(m_szStreamName, "%s/%s", getUsrDirPath(), m_szMusicPath);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
// Other consoles (Vita, Orbis)
|
||||||
sprintf(m_szStreamName, "%s/%s", getUsrDirPath(), m_szMusicPath);
|
sprintf(m_szStreamName, "%s/%s", getUsrDirPath(), m_szMusicPath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
// Windows / Durango – plain relative path
|
||||||
strcpy((char*)m_szStreamName, m_szMusicPath);
|
strcpy((char*)m_szStreamName, m_szMusicPath);
|
||||||
#endif
|
#endif
|
||||||
// are we using a mash-up pack?
|
|
||||||
//if(pMinecraft && !pMinecraft->skins->isUsingDefaultSkin() && pMinecraft->skins->getSelected()->hasAudio())
|
// Check if a mash‑up pack (DLC) is active and has custom audio
|
||||||
if (Minecraft::GetInstance()->skins->getSelected()->hasAudio())
|
if (Minecraft::GetInstance()->skins->getSelected()->hasAudio())
|
||||||
{
|
{
|
||||||
// It's a mash-up - need to use the DLC path for the music
|
// Mash‑up pack: use DLC audio files
|
||||||
TexturePack* pTexPack = Minecraft::GetInstance()->skins->getSelected();
|
TexturePack* pTexPack = Minecraft::GetInstance()->skins->getSelected();
|
||||||
DLCTexturePack* pDLCTexPack = (DLCTexturePack*)pTexPack;
|
DLCTexturePack* pDLCTexPack = (DLCTexturePack*)pTexPack;
|
||||||
DLCPack* pack = pDLCTexPack->getDLCInfoParentPack();
|
DLCPack* pack = pDLCTexPack->getDLCInfoParentPack();
|
||||||
|
|
@ -1019,22 +952,23 @@ void SoundEngine::playMusicUpdate()
|
||||||
|
|
||||||
app.DebugPrintf("Mashup pack\n");
|
app.DebugPrintf("Mashup pack\n");
|
||||||
|
|
||||||
// build the name
|
// Determine whether this is game music (track index < first CD) or a CD
|
||||||
|
|
||||||
// if the music ID is beyond the end of the texture pack music files, then it's a CD
|
|
||||||
if (m_musicID < m_iStream_CD_1)
|
if (m_musicID < m_iStream_CD_1)
|
||||||
{
|
{
|
||||||
|
// Game music from the mash‑up pack
|
||||||
SetIsPlayingStreamingGameMusic(true);
|
SetIsPlayingStreamingGameMusic(true);
|
||||||
SetIsPlayingStreamingCDMusic(false);
|
SetIsPlayingStreamingCDMusic(false);
|
||||||
m_MusicType = eMusicType_Game;
|
m_MusicType = eMusicType_Game;
|
||||||
m_StreamingAudioInfo.bIs3D = false;
|
m_StreamingAudioInfo.bIs3D = false;
|
||||||
|
|
||||||
#ifdef _XBOX_ONE
|
#ifdef _XBOX_ONE
|
||||||
|
// Xbox One: use StorageManager to resolve TPACK path
|
||||||
wstring& wstrSoundName = dlcAudioFile->GetSoundName(m_musicID);
|
wstring& wstrSoundName = dlcAudioFile->GetSoundName(m_musicID);
|
||||||
wstring wstrFile = L"TPACK:\\Data\\" + wstrSoundName + L".wav";
|
wstring wstrFile = L"TPACK:\\Data\\" + wstrSoundName + L".wav";
|
||||||
std::wstring mountedPath = StorageManager.GetMountedPath(wstrFile);
|
std::wstring mountedPath = StorageManager.GetMountedPath(wstrFile);
|
||||||
wcstombs(m_szStreamName, mountedPath.c_str(), 255);
|
wcstombs(m_szStreamName, mountedPath.c_str(), 255);
|
||||||
#else
|
#else
|
||||||
|
// Other platforms: convert wstring to char and build TPACK path
|
||||||
wstring& wstrSoundName = dlcAudioFile->GetSoundName(m_musicID);
|
wstring& wstrSoundName = dlcAudioFile->GetSoundName(m_musicID);
|
||||||
char szName[255];
|
char szName[255];
|
||||||
wcstombs(szName, wstrSoundName.c_str(), 255);
|
wcstombs(szName, wstrSoundName.c_str(), 255);
|
||||||
|
|
@ -1050,12 +984,13 @@ void SoundEngine::playMusicUpdate()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// CD track from the mash‑up pack
|
||||||
SetIsPlayingStreamingGameMusic(false);
|
SetIsPlayingStreamingGameMusic(false);
|
||||||
SetIsPlayingStreamingCDMusic(true);
|
SetIsPlayingStreamingCDMusic(true);
|
||||||
m_MusicType = eMusicType_CD;
|
m_MusicType = eMusicType_CD;
|
||||||
m_StreamingAudioInfo.bIs3D = true;
|
m_StreamingAudioInfo.bIs3D = true;
|
||||||
|
|
||||||
// Need to adjust to index into the cds in the game's m_szStreamFileA
|
// Append "cds/" and the base filename (from the global stream file array)
|
||||||
strcat((char*)m_szStreamName, "cds/");
|
strcat((char*)m_szStreamName, "cds/");
|
||||||
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID - m_iStream_CD_1 + eStream_CD_1]);
|
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID - m_iStream_CD_1 + eStream_CD_1]);
|
||||||
strcat((char*)m_szStreamName, ".wav");
|
strcat((char*)m_szStreamName, ".wav");
|
||||||
|
|
@ -1063,17 +998,18 @@ void SoundEngine::playMusicUpdate()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 4J-PB - if this is a PS3 disc patch, we have to check if the music file is in the patch data
|
// No mash‑up pack – use standard Minecraft music files
|
||||||
#ifdef __PS3__
|
#ifdef __PS3__
|
||||||
|
// PS3 disc patch handling
|
||||||
if (app.GetBootedFromDiscPatch() && (m_musicID < m_iStream_CD_1))
|
if (app.GetBootedFromDiscPatch() && (m_musicID < m_iStream_CD_1))
|
||||||
{
|
{
|
||||||
// rebuild the path for the music
|
// Rebuild path for patch data
|
||||||
strcpy((char*)m_szStreamName, m_szMusicPath);
|
strcpy((char*)m_szStreamName, m_szMusicPath);
|
||||||
strcat((char*)m_szStreamName, "music/");
|
strcat((char*)m_szStreamName, "music/");
|
||||||
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
|
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
|
||||||
strcat((char*)m_szStreamName, ".wav");
|
strcat((char*)m_szStreamName, ".wav");
|
||||||
|
|
||||||
// check if this is in the patch data
|
// Check if file exists in patch area; if not, fallback to original path
|
||||||
sprintf(m_szStreamName, "%s/%s", app.GetBDUsrDirPath(m_szStreamName), m_szMusicPath);
|
sprintf(m_szStreamName, "%s/%s", app.GetBDUsrDirPath(m_szStreamName), m_szMusicPath);
|
||||||
strcat((char*)m_szStreamName, "music/");
|
strcat((char*)m_szStreamName, "music/");
|
||||||
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
|
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
|
||||||
|
|
@ -1086,75 +1022,72 @@ void SoundEngine::playMusicUpdate()
|
||||||
}
|
}
|
||||||
else if (m_musicID < m_iStream_CD_1)
|
else if (m_musicID < m_iStream_CD_1)
|
||||||
{
|
{
|
||||||
|
// Standard game music (non‑CD)
|
||||||
SetIsPlayingStreamingGameMusic(true);
|
SetIsPlayingStreamingGameMusic(true);
|
||||||
SetIsPlayingStreamingCDMusic(false);
|
SetIsPlayingStreamingCDMusic(false);
|
||||||
m_MusicType = eMusicType_Game;
|
m_MusicType = eMusicType_Game;
|
||||||
m_StreamingAudioInfo.bIs3D = false;
|
m_StreamingAudioInfo.bIs3D = false;
|
||||||
// build the name
|
|
||||||
strcat((char*)m_szStreamName, "music/");
|
strcat((char*)m_szStreamName, "music/");
|
||||||
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
|
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
|
||||||
strcat((char*)m_szStreamName, ".wav");
|
strcat((char*)m_szStreamName, ".wav");
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// CD music
|
||||||
SetIsPlayingStreamingGameMusic(false);
|
SetIsPlayingStreamingGameMusic(false);
|
||||||
SetIsPlayingStreamingCDMusic(true);
|
SetIsPlayingStreamingCDMusic(true);
|
||||||
m_MusicType = eMusicType_CD;
|
m_MusicType = eMusicType_CD;
|
||||||
m_StreamingAudioInfo.bIs3D = true;
|
m_StreamingAudioInfo.bIs3D = true;
|
||||||
// build the name
|
|
||||||
strcat((char*)m_szStreamName, "cds/");
|
strcat((char*)m_szStreamName, "cds/");
|
||||||
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
|
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
|
||||||
strcat((char*)m_szStreamName, ".wav");
|
strcat((char*)m_szStreamName, ".wav");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
// Non‑PS3 platforms
|
||||||
if (m_musicID < m_iStream_CD_1)
|
if (m_musicID < m_iStream_CD_1)
|
||||||
{
|
{
|
||||||
|
// Game music
|
||||||
SetIsPlayingStreamingGameMusic(true);
|
SetIsPlayingStreamingGameMusic(true);
|
||||||
SetIsPlayingStreamingCDMusic(false);
|
SetIsPlayingStreamingCDMusic(false);
|
||||||
m_MusicType = eMusicType_Game;
|
m_MusicType = eMusicType_Game;
|
||||||
m_StreamingAudioInfo.bIs3D = false;
|
m_StreamingAudioInfo.bIs3D = false;
|
||||||
// build the name
|
|
||||||
strcat((char*)m_szStreamName, "music/");
|
strcat((char*)m_szStreamName, "music/");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// CD music
|
||||||
SetIsPlayingStreamingGameMusic(false);
|
SetIsPlayingStreamingGameMusic(false);
|
||||||
SetIsPlayingStreamingCDMusic(true);
|
SetIsPlayingStreamingCDMusic(true);
|
||||||
m_MusicType = eMusicType_CD;
|
m_MusicType = eMusicType_CD;
|
||||||
m_StreamingAudioInfo.bIs3D = true;
|
m_StreamingAudioInfo.bIs3D = true;
|
||||||
// build the name
|
|
||||||
strcat((char*)m_szStreamName, "cds/");
|
strcat((char*)m_szStreamName, "cds/");
|
||||||
}
|
}
|
||||||
|
// Append the base filename (from global array) and extension
|
||||||
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
|
strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
|
||||||
strcat((char*)m_szStreamName, ".wav");
|
strcat((char*)m_szStreamName, ".wav");
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// wstring name = m_szStreamFileA[m_musicID];
|
// Verify that the file exists; if not, try alternative extensions (.ogg, .mp3)
|
||||||
// char *SoundName = (char *)ConvertSoundPathToName(name);
|
|
||||||
// strcat((char *)szStreamName,SoundName);
|
|
||||||
|
|
||||||
FILE* pFile = nullptr;
|
FILE* pFile = nullptr;
|
||||||
|
|
||||||
if (fopen_s(&pFile, reinterpret_cast<char*>(m_szStreamName), "rb") == 0 && pFile)
|
if (fopen_s(&pFile, reinterpret_cast<char*>(m_szStreamName), "rb") == 0 && pFile)
|
||||||
{
|
{
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// File not found – try changing the extension
|
||||||
const char* extensions[] = { ".ogg", ".mp3", ".wav" };
|
const char* extensions[] = { ".ogg", ".mp3", ".wav" };
|
||||||
size_t extCount = sizeof(extensions) / sizeof(extensions[0]);
|
size_t extCount = sizeof(extensions) / sizeof(extensions[0]);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
|
// Find the position of the current extension (assumed to be ".wav")
|
||||||
char* dotPos = strrchr(reinterpret_cast<char*>(m_szStreamName), '.');
|
char* dotPos = strrchr(reinterpret_cast<char*>(m_szStreamName), '.');
|
||||||
if (dotPos != nullptr && (dotPos - reinterpret_cast<char*>(m_szStreamName)) < 250)
|
if (dotPos != nullptr && (dotPos - reinterpret_cast<char*>(m_szStreamName)) < 250)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < extCount; i++)
|
for (size_t i = 0; i < extCount; ++i)
|
||||||
{
|
{
|
||||||
strcpy_s(dotPos, 5, extensions[i]);
|
strcpy_s(dotPos, 5, extensions[i]); // Replace extension
|
||||||
|
|
||||||
if (fopen_s(&pFile, reinterpret_cast<char*>(m_szStreamName), "rb") == 0 && pFile)
|
if (fopen_s(&pFile, reinterpret_cast<char*>(m_szStreamName), "rb") == 0 && pFile)
|
||||||
{
|
{
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
|
|
@ -1166,62 +1099,74 @@ void SoundEngine::playMusicUpdate()
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
|
// Restore original extension for error message
|
||||||
if (dotPos != nullptr)
|
if (dotPos != nullptr)
|
||||||
{
|
|
||||||
strcpy_s(dotPos, 5, ".wav");
|
strcpy_s(dotPos, 5, ".wav");
|
||||||
}
|
|
||||||
app.DebugPrintf("WARNING: No audio file found for music ID %d (tried .ogg, .mp3, .wav)\n", m_musicID);
|
app.DebugPrintf("WARNING: No audio file found for music ID %d (tried .ogg, .mp3, .wav)\n", m_musicID);
|
||||||
return;
|
return; // Abort – stay in Idle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // end file path construction
|
||||||
|
|
||||||
app.DebugPrintf("Starting streaming - %s\n", m_szStreamName);
|
app.DebugPrintf("Starting streaming - %s\n", m_szStreamName);
|
||||||
|
|
||||||
|
// Launch a thread to open the audio file (prevents blocking the main thread)
|
||||||
m_openStreamThread = new C4JThread(OpenStreamThreadProc, this, "OpenStreamThreadProc");
|
m_openStreamThread = new C4JThread(OpenStreamThreadProc, this, "OpenStreamThreadProc");
|
||||||
m_openStreamThread->Run();
|
m_openStreamThread->Run();
|
||||||
m_StreamState = eMusicStreamState_Opening;
|
m_StreamState = eMusicStreamState_Opening;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// OPENING – waiting for the background thread to finish opening the file
|
||||||
|
//---------------------------------------------------------------------
|
||||||
case eMusicStreamState_Opening:
|
case eMusicStreamState_Opening:
|
||||||
|
{
|
||||||
if (!m_openStreamThread->isRunning())
|
if (!m_openStreamThread->isRunning())
|
||||||
{
|
{
|
||||||
|
// Thread finished
|
||||||
delete m_openStreamThread;
|
delete m_openStreamThread;
|
||||||
m_openStreamThread = nullptr;
|
m_openStreamThread = nullptr;
|
||||||
|
|
||||||
app.DebugPrintf("OpenStreamThreadProc finished. m_musicStreamActive=%d\n", m_musicStreamActive);
|
app.DebugPrintf("OpenStreamThreadProc finished. m_musicStreamActive=%d\n", m_musicStreamActive);
|
||||||
|
|
||||||
|
// If the stream failed to open, try a fallback (e.g., if we used a numbered variant)
|
||||||
if (!m_musicStreamActive)
|
if (!m_musicStreamActive)
|
||||||
{
|
{
|
||||||
const char* currentExt = strrchr(reinterpret_cast<char*>(m_szStreamName), '.');
|
const char* currentExt = strrchr(reinterpret_cast<char*>(m_szStreamName), '.');
|
||||||
if (currentExt && _stricmp(currentExt, ".wav") == 0)
|
if (currentExt && _stricmp(currentExt, ".wav") == 0)
|
||||||
{
|
{
|
||||||
|
// Attempt to rebuild the path using the base filename (without number)
|
||||||
const bool isCD = (m_musicID >= m_iStream_CD_1);
|
const bool isCD = (m_musicID >= m_iStream_CD_1);
|
||||||
const char* folder = isCD ? "cds/" : "music/";
|
const char* folder = isCD ? "cds/" : "music/";
|
||||||
|
int n = sprintf_s(reinterpret_cast<char*>(m_szStreamName), 512, "%s%s%s.wav",
|
||||||
int n = sprintf_s(reinterpret_cast<char*>(m_szStreamName), 512, "%s%s%s.wav", m_szMusicPath, folder, m_szStreamFileA[m_musicID]);
|
m_szMusicPath, folder, m_szStreamFileA[m_musicID]);
|
||||||
|
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
{
|
{
|
||||||
FILE* pFile = nullptr;
|
FILE* pFile = nullptr;
|
||||||
if (fopen_s(&pFile, reinterpret_cast<char*>(m_szStreamName), "rb") == 0 && pFile)
|
if (fopen_s(&pFile, reinterpret_cast<char*>(m_szStreamName), "rb") == 0 && pFile)
|
||||||
{
|
{
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
|
// Retry opening with the new path
|
||||||
m_openStreamThread = new C4JThread(OpenStreamThreadProc, this, "OpenStreamThreadProc");
|
m_openStreamThread = new C4JThread(OpenStreamThreadProc, this, "OpenStreamThreadProc");
|
||||||
m_openStreamThread->Run();
|
m_openStreamThread->Run();
|
||||||
break;
|
break; // stay in Opening
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// No fallback worked – go back to Idle
|
||||||
m_StreamState = eMusicStreamState_Idle;
|
m_StreamState = eMusicStreamState_Idle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stream opened successfully; configure spatialization, pitch, volume
|
||||||
if (m_StreamingAudioInfo.bIs3D)
|
if (m_StreamingAudioInfo.bIs3D)
|
||||||
{
|
{
|
||||||
ma_sound_set_spatialization_enabled(&m_musicStream, MA_TRUE);
|
ma_sound_set_spatialization_enabled(&m_musicStream, MA_TRUE);
|
||||||
ma_sound_set_position(&m_musicStream, m_StreamingAudioInfo.x, m_StreamingAudioInfo.y, m_StreamingAudioInfo.z);
|
ma_sound_set_position(&m_musicStream,
|
||||||
|
m_StreamingAudioInfo.x,
|
||||||
|
m_StreamingAudioInfo.y,
|
||||||
|
m_StreamingAudioInfo.z);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1230,16 +1175,23 @@ void SoundEngine::playMusicUpdate()
|
||||||
|
|
||||||
ma_sound_set_pitch(&m_musicStream, m_StreamingAudioInfo.pitch);
|
ma_sound_set_pitch(&m_musicStream, m_StreamingAudioInfo.pitch);
|
||||||
|
|
||||||
float finalVolume = m_StreamingAudioInfo.volume * getMasterMusicVolume();
|
float finalVolume = m_StreamingAudioInfo.volume * masterVolume;
|
||||||
|
|
||||||
ma_sound_set_volume(&m_musicStream, finalVolume);
|
ma_sound_set_volume(&m_musicStream, finalVolume);
|
||||||
|
|
||||||
|
// Start playback
|
||||||
ma_result startResult = ma_sound_start(&m_musicStream);
|
ma_result startResult = ma_sound_start(&m_musicStream);
|
||||||
app.DebugPrintf("ma_sound_start result: %d\n", startResult);
|
app.DebugPrintf("ma_sound_start result: %d\n", startResult);
|
||||||
|
|
||||||
m_StreamState = eMusicStreamState_Playing;
|
m_StreamState = eMusicStreamState_Playing;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// OPENINGCANCEL – user requested stop while opening
|
||||||
|
//---------------------------------------------------------------------
|
||||||
case eMusicStreamState_OpeningCancel:
|
case eMusicStreamState_OpeningCancel:
|
||||||
|
{
|
||||||
if (!m_openStreamThread->isRunning())
|
if (!m_openStreamThread->isRunning())
|
||||||
{
|
{
|
||||||
delete m_openStreamThread;
|
delete m_openStreamThread;
|
||||||
|
|
@ -1247,7 +1199,13 @@ void SoundEngine::playMusicUpdate()
|
||||||
m_StreamState = eMusicStreamState_Stop;
|
m_StreamState = eMusicStreamState_Stop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// STOP – actively stop the current stream
|
||||||
|
//---------------------------------------------------------------------
|
||||||
case eMusicStreamState_Stop:
|
case eMusicStreamState_Stop:
|
||||||
|
{
|
||||||
if (m_musicStreamActive)
|
if (m_musicStreamActive)
|
||||||
{
|
{
|
||||||
ma_sound_stop(&m_musicStream);
|
ma_sound_stop(&m_musicStream);
|
||||||
|
|
@ -1255,17 +1213,20 @@ void SoundEngine::playMusicUpdate()
|
||||||
m_musicStreamActive = false;
|
m_musicStreamActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear flags indicating what type of music was playing
|
||||||
SetIsPlayingStreamingCDMusic(false);
|
SetIsPlayingStreamingCDMusic(false);
|
||||||
SetIsPlayingStreamingGameMusic(false);
|
SetIsPlayingStreamingGameMusic(false);
|
||||||
|
|
||||||
m_StreamState = eMusicStreamState_Idle;
|
m_StreamState = eMusicStreamState_Idle;
|
||||||
break;
|
break;
|
||||||
case eMusicStreamState_Stopping:
|
}
|
||||||
break;
|
|
||||||
case eMusicStreamState_Play:
|
//---------------------------------------------------------------------
|
||||||
break;
|
// PLAYING – the stream is actively playing
|
||||||
|
//---------------------------------------------------------------------
|
||||||
case eMusicStreamState_Playing:
|
case eMusicStreamState_Playing:
|
||||||
{
|
{
|
||||||
|
// Optional periodic debug logging (once per second at 60 fps)
|
||||||
static int frameCount = 0;
|
static int frameCount = 0;
|
||||||
if (frameCount++ % 60 == 0)
|
if (frameCount++ % 60 == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -1274,109 +1235,45 @@ void SoundEngine::playMusicUpdate()
|
||||||
bool isPlaying = ma_sound_is_playing(&m_musicStream);
|
bool isPlaying = ma_sound_is_playing(&m_musicStream);
|
||||||
float vol = ma_sound_get_volume(&m_musicStream);
|
float vol = ma_sound_get_volume(&m_musicStream);
|
||||||
bool isAtEnd = ma_sound_at_end(&m_musicStream);
|
bool isAtEnd = ma_sound_at_end(&m_musicStream);
|
||||||
|
// (debug info could be printed here if needed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Separate handling for game music (background) and CD music (jukebox)
|
||||||
if (GetIsPlayingStreamingGameMusic())
|
if (GetIsPlayingStreamingGameMusic())
|
||||||
{
|
{
|
||||||
//if(m_MusicInfo.pCue!=nullptr)
|
// Background music: check if the musical context has changed
|
||||||
|
MusicTrackManager::Domain currentDomain = determineCurrentMusicDomain();
|
||||||
|
|
||||||
|
// If the domain changed, we need to stop the current track
|
||||||
|
// so that a new one (appropriate for the new domain) will start.
|
||||||
|
if (currentDomain != m_currentMusicDomain)
|
||||||
{
|
{
|
||||||
bool playerInEnd = false;
|
m_StreamState = eMusicStreamState_Stop;
|
||||||
bool playerInNether=false;
|
// Store the new domain for when we restart
|
||||||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
m_currentMusicDomain = currentDomain;
|
||||||
for(unsigned int i = 0; i < MAX_LOCAL_PLAYERS; ++i)
|
m_musicID = getTrackForDomain(currentDomain);
|
||||||
{
|
break;
|
||||||
if(pMinecraft->localplayers[i]!=nullptr)
|
|
||||||
{
|
|
||||||
if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_END)
|
|
||||||
{
|
|
||||||
playerInEnd=true;
|
|
||||||
}
|
|
||||||
else if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_NETHER)
|
|
||||||
{
|
|
||||||
playerInNether=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(playerInEnd && !GetIsPlayingEndMusic())
|
// Update volume if master volume changed
|
||||||
{
|
|
||||||
m_StreamState=eMusicStreamState_Stop;
|
|
||||||
|
|
||||||
// Set the end track
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_END);
|
|
||||||
SetIsPlayingEndMusic(true);
|
|
||||||
SetIsPlayingNetherMusic(false);
|
|
||||||
}
|
|
||||||
else if(!playerInEnd && GetIsPlayingEndMusic())
|
|
||||||
{
|
|
||||||
if(playerInNether)
|
|
||||||
{
|
|
||||||
m_StreamState=eMusicStreamState_Stop;
|
|
||||||
|
|
||||||
// Set the end track
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_NETHER);
|
|
||||||
SetIsPlayingEndMusic(false);
|
|
||||||
SetIsPlayingNetherMusic(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_StreamState=eMusicStreamState_Stop;
|
|
||||||
|
|
||||||
// Set the end track
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_OVERWORLD);
|
|
||||||
SetIsPlayingEndMusic(false);
|
|
||||||
SetIsPlayingNetherMusic(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (playerInNether && !GetIsPlayingNetherMusic())
|
|
||||||
{
|
|
||||||
m_StreamState=eMusicStreamState_Stop;
|
|
||||||
// set the Nether track
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_NETHER);
|
|
||||||
SetIsPlayingNetherMusic(true);
|
|
||||||
SetIsPlayingEndMusic(false);
|
|
||||||
}
|
|
||||||
else if(!playerInNether && GetIsPlayingNetherMusic())
|
|
||||||
{
|
|
||||||
if(playerInEnd)
|
|
||||||
{
|
|
||||||
m_StreamState=eMusicStreamState_Stop;
|
|
||||||
// set the Nether track
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_END);
|
|
||||||
SetIsPlayingNetherMusic(false);
|
|
||||||
SetIsPlayingEndMusic(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_StreamState=eMusicStreamState_Stop;
|
|
||||||
// set the Nether track
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_OVERWORLD);
|
|
||||||
SetIsPlayingNetherMusic(false);
|
|
||||||
SetIsPlayingEndMusic(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// volume change required?
|
|
||||||
if (m_musicStreamActive)
|
if (m_musicStreamActive)
|
||||||
{
|
{
|
||||||
float finalVolume = m_StreamingAudioInfo.volume * fMusicVol;
|
float finalVolume = m_StreamingAudioInfo.volume * masterVolume;
|
||||||
|
|
||||||
ma_sound_set_volume(&m_musicStream, finalVolume);
|
ma_sound_set_volume(&m_musicStream, finalVolume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Music disc playing - if it's a 3D stream, then set the position - we don't have any streaming audio in the world that moves, so this isn't
|
// Music disc playing (jukebox)
|
||||||
// required unless we have more than one listener, and are setting the listening position to the origin and setting a fake position
|
|
||||||
// for the sound down the z axis
|
|
||||||
if (m_StreamingAudioInfo.bIs3D && m_validListenerCount > 1)
|
if (m_StreamingAudioInfo.bIs3D && m_validListenerCount > 1)
|
||||||
{
|
{
|
||||||
|
// For split‑screen, we need to position the sound relative to the closest listener.
|
||||||
|
// (The engine's listener is set to the origin; we simulate distance by moving the sound.)
|
||||||
int iClosestListener = 0;
|
int iClosestListener = 0;
|
||||||
float fClosestDist = 1e6f;
|
float fClosestDist = 1e6f;
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_LOCAL_PLAYERS; i++)
|
for (size_t i = 0; i < MAX_LOCAL_PLAYERS; ++i)
|
||||||
{
|
{
|
||||||
if (m_ListenerA[i].bValid)
|
if (m_ListenerA[i].bValid)
|
||||||
{
|
{
|
||||||
|
|
@ -1393,6 +1290,7 @@ void SoundEngine::playMusicUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute sound position relative to that listener
|
||||||
float relX = m_StreamingAudioInfo.x - m_ListenerA[iClosestListener].vPosition.x;
|
float relX = m_StreamingAudioInfo.x - m_ListenerA[iClosestListener].vPosition.x;
|
||||||
float relY = m_StreamingAudioInfo.y - m_ListenerA[iClosestListener].vPosition.y;
|
float relY = m_StreamingAudioInfo.y - m_ListenerA[iClosestListener].vPosition.y;
|
||||||
float relZ = m_StreamingAudioInfo.z - m_ListenerA[iClosestListener].vPosition.z;
|
float relZ = m_StreamingAudioInfo.z - m_ListenerA[iClosestListener].vPosition.z;
|
||||||
|
|
@ -1403,58 +1301,45 @@ void SoundEngine::playMusicUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// COMPLETED – the current track reached its end naturally
|
||||||
|
//---------------------------------------------------------------------
|
||||||
case eMusicStreamState_Completed:
|
case eMusicStreamState_Completed:
|
||||||
{
|
{
|
||||||
// random delay of up to 3 minutes for music
|
// Set a random delay (0–3 minutes) before playing the next track
|
||||||
m_iMusicDelay = random->nextInt(20 * 60 * 3);//random->nextInt(20 * 60 * 10) + 20 * 60 * 10;
|
m_iMusicDelay = random->nextInt(20 * 60 * 3);
|
||||||
// Check if we have a local player in The Nether or in The End, and play that music if they are
|
|
||||||
Minecraft *pMinecraft=Minecraft::GetInstance();
|
|
||||||
bool playerInEnd=false;
|
|
||||||
bool playerInNether=false;
|
|
||||||
|
|
||||||
for(unsigned int i=0;i<MAX_LOCAL_PLAYERS;i++)
|
// Determine the current musical context
|
||||||
{
|
m_currentMusicDomain = determineCurrentMusicDomain();
|
||||||
if(pMinecraft->localplayers[i]!=nullptr)
|
|
||||||
{
|
// Select a new track ID appropriate for that domain
|
||||||
if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_END)
|
m_musicID = getTrackForDomain(m_currentMusicDomain);
|
||||||
{
|
|
||||||
playerInEnd=true;
|
// Update the flags that track which domain is active (for compatibility)
|
||||||
}
|
// These are used elsewhere; we keep them in sync.
|
||||||
else if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_NETHER)
|
SetIsPlayingMenuMusic(m_currentMusicDomain == MusicTrackManager::Domain::Menu);
|
||||||
{
|
SetIsPlayingEndMusic(m_currentMusicDomain == MusicTrackManager::Domain::End);
|
||||||
playerInNether=true;
|
SetIsPlayingNetherMusic(m_currentMusicDomain == MusicTrackManager::Domain::Nether);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(playerInEnd)
|
|
||||||
{
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_END);
|
|
||||||
SetIsPlayingEndMusic(true);
|
|
||||||
SetIsPlayingNetherMusic(false);
|
|
||||||
}
|
|
||||||
else if(playerInNether)
|
|
||||||
{
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_NETHER);
|
|
||||||
SetIsPlayingNetherMusic(true);
|
|
||||||
SetIsPlayingEndMusic(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_musicID = getMusicID(LevelData::DIMENSION_OVERWORLD);
|
|
||||||
SetIsPlayingNetherMusic(false);
|
|
||||||
SetIsPlayingEndMusic(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_StreamState = eMusicStreamState_Idle;
|
m_StreamState = eMusicStreamState_Idle;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the status of the stream - this is for when a track completes rather than is stopped by the user action
|
//---------------------------------------------------------------------
|
||||||
|
// States that require no action (STOPPING, PLAY – unused)
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
case eMusicStreamState_Stopping:
|
||||||
|
case eMusicStreamState_Play:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// End-of‑stream detection (common to all states)
|
||||||
|
// If the stream is active but has finished playing, transition to Completed.
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
if (m_musicStreamActive)
|
if (m_musicStreamActive)
|
||||||
{
|
{
|
||||||
if (!ma_sound_is_playing(&m_musicStream) && ma_sound_at_end(&m_musicStream))
|
if (!ma_sound_is_playing(&m_musicStream) && ma_sound_at_end(&m_musicStream))
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ class Mob;
|
||||||
class Options;
|
class Options;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
#include "..\..\Minecraft.World\SoundTypes.h"
|
#include "..\..\Minecraft.World\SoundTypes.h"
|
||||||
|
#include "MusicTrackManager.h"
|
||||||
|
|
||||||
#include "miniaudio.h"
|
#include "miniaudio.h"
|
||||||
|
|
||||||
|
|
@ -17,6 +18,10 @@ enum eMUSICFILES
|
||||||
eStream_Overworld_hal4,
|
eStream_Overworld_hal4,
|
||||||
eStream_Overworld_nuance1,
|
eStream_Overworld_nuance1,
|
||||||
eStream_Overworld_nuance2,
|
eStream_Overworld_nuance2,
|
||||||
|
eStream_Overworld_piano1,
|
||||||
|
eStream_Overworld_piano2,
|
||||||
|
eStream_Overworld_piano3, // <-- make piano3 the last overworld one
|
||||||
|
|
||||||
#ifndef _XBOX
|
#ifndef _XBOX
|
||||||
// Add the new music tracks
|
// Add the new music tracks
|
||||||
eStream_Overworld_Creative1,
|
eStream_Overworld_Creative1,
|
||||||
|
|
@ -25,14 +30,12 @@ enum eMUSICFILES
|
||||||
eStream_Overworld_Creative4,
|
eStream_Overworld_Creative4,
|
||||||
eStream_Overworld_Creative5,
|
eStream_Overworld_Creative5,
|
||||||
eStream_Overworld_Creative6,
|
eStream_Overworld_Creative6,
|
||||||
|
|
||||||
eStream_Overworld_Menu1,
|
eStream_Overworld_Menu1,
|
||||||
eStream_Overworld_Menu2,
|
eStream_Overworld_Menu2,
|
||||||
eStream_Overworld_Menu3,
|
eStream_Overworld_Menu3,
|
||||||
eStream_Overworld_Menu4,
|
eStream_Overworld_Menu4,
|
||||||
#endif
|
#endif
|
||||||
eStream_Overworld_piano1,
|
|
||||||
eStream_Overworld_piano2,
|
|
||||||
eStream_Overworld_piano3, // <-- make piano3 the last overworld one
|
|
||||||
// Nether
|
// Nether
|
||||||
eStream_Nether1,
|
eStream_Nether1,
|
||||||
eStream_Nether2,
|
eStream_Nether2,
|
||||||
|
|
@ -106,6 +109,7 @@ extern std::vector<MiniAudioSound*> m_activeSounds;
|
||||||
class SoundEngine : public ConsoleSoundEngine
|
class SoundEngine : public ConsoleSoundEngine
|
||||||
{
|
{
|
||||||
static const int MAX_SAME_SOUNDS_PLAYING = 8; // 4J added
|
static const int MAX_SAME_SOUNDS_PLAYING = 8; // 4J added
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SoundEngine();
|
SoundEngine();
|
||||||
void destroy() override;
|
void destroy() override;
|
||||||
|
|
@ -125,10 +129,11 @@ public:
|
||||||
void addMusic(const wstring& name, File *file) override;
|
void addMusic(const wstring& name, File *file) override;
|
||||||
void addStreaming(const wstring& name, File *file) override;
|
void addStreaming(const wstring& name, File *file) override;
|
||||||
char *ConvertSoundPathToName(const wstring& name, bool bConvertSpaces=false) override;
|
char *ConvertSoundPathToName(const wstring& name, bool bConvertSpaces=false) override;
|
||||||
bool isStreamingWavebankReady(); // 4J Added
|
bool isStreamingWavebankReady();
|
||||||
int getMusicID(int iDomain);
|
MusicTrackManager::Domain determineCurrentMusicDomain() const;
|
||||||
|
int getTrackForDomain(MusicTrackManager::Domain domain);
|
||||||
int getMusicID(const wstring& name);
|
int getMusicID(const wstring& name);
|
||||||
void SetStreamingSounds(int iOverworldMin, int iOverWorldMax, int iNetherMin, int iNetherMax, int iEndMin, int iEndMax, int iCD1);
|
void SetStreamingSounds(int iMenuMin, int iMenuMax, int iOverworldSurvivalMin, int iOverWorldSurvivalMax, int iOverworldCreativeMin, int iOverWorldCreativeMax, int iNetherMin, int iNetherMax, int iEndMin, int iEndMax, int iCD1);
|
||||||
void updateMiniAudio();
|
void updateMiniAudio();
|
||||||
void playMusicUpdate();
|
void playMusicUpdate();
|
||||||
|
|
||||||
|
|
@ -142,7 +147,9 @@ private:
|
||||||
{ return iMinSpeakers;}
|
{ return iMinSpeakers;}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int GetRandomishTrack(int iStart,int iEnd);
|
Random* random;
|
||||||
|
MusicTrackManager m_musicTrackManager;
|
||||||
|
MusicTrackManager::Domain m_currentMusicDomain;
|
||||||
|
|
||||||
ma_engine m_engine;
|
ma_engine m_engine;
|
||||||
ma_engine_config m_engineConfig;
|
ma_engine_config m_engineConfig;
|
||||||
|
|
@ -157,8 +164,6 @@ private:
|
||||||
AUDIO_LISTENER m_ListenerA[MAX_LOCAL_PLAYERS];
|
AUDIO_LISTENER m_ListenerA[MAX_LOCAL_PLAYERS];
|
||||||
int m_validListenerCount;
|
int m_validListenerCount;
|
||||||
|
|
||||||
|
|
||||||
Random *random;
|
|
||||||
int m_musicID;
|
int m_musicID;
|
||||||
int m_iMusicDelay;
|
int m_iMusicDelay;
|
||||||
int m_StreamState;
|
int m_StreamState;
|
||||||
|
|
@ -174,12 +179,7 @@ private:
|
||||||
char m_szStreamName[255];
|
char m_szStreamName[255];
|
||||||
int CurrentSoundsPlaying[eSoundType_MAX+eSFX_MAX];
|
int CurrentSoundsPlaying[eSoundType_MAX+eSFX_MAX];
|
||||||
|
|
||||||
// streaming music files - will be different for mash-up packs
|
|
||||||
int m_iStream_Overworld_Min,m_iStream_Overworld_Max;
|
|
||||||
int m_iStream_Nether_Min,m_iStream_Nether_Max;
|
|
||||||
int m_iStream_End_Min,m_iStream_End_Max;
|
|
||||||
int m_iStream_CD_1;
|
int m_iStream_CD_1;
|
||||||
bool *m_bHeardTrackA;
|
|
||||||
|
|
||||||
#ifdef __ORBIS__
|
#ifdef __ORBIS__
|
||||||
int32_t m_hBGMAudio;
|
int32_t m_hBGMAudio;
|
||||||
|
|
|
||||||
|
|
@ -3754,7 +3754,9 @@ void CMinecraftApp::HandleXuiActions(void)
|
||||||
// need to stop the streaming audio - by playing streaming audio from the default texture pack now
|
// need to stop the streaming audio - by playing streaming audio from the default texture pack now
|
||||||
// reset the streaming sounds back to the normal ones
|
// reset the streaming sounds back to the normal ones
|
||||||
#ifndef _XBOX
|
#ifndef _XBOX
|
||||||
pMinecraft->soundEngine->SetStreamingSounds(eStream_Overworld_Calm1,eStream_Overworld_piano3,
|
pMinecraft->soundEngine->SetStreamingSounds(eStream_Overworld_Menu1, eStream_Overworld_Menu4,
|
||||||
|
eStream_Overworld_Calm1, eStream_Overworld_piano3,
|
||||||
|
eStream_Overworld_Creative1, eStream_Overworld_Creative6,
|
||||||
eStream_Nether1, eStream_Nether4,
|
eStream_Nether1, eStream_Nether4,
|
||||||
eStream_end_dragon, eStream_end_end,
|
eStream_end_dragon, eStream_end_end,
|
||||||
eStream_CD_1);
|
eStream_CD_1);
|
||||||
|
|
|
||||||
|
|
@ -2064,7 +2064,9 @@ void UIController::NavigateToHomeMenu()
|
||||||
{
|
{
|
||||||
// need to stop the streaming audio - by playing streaming audio from the default texture pack now
|
// need to stop the streaming audio - by playing streaming audio from the default texture pack now
|
||||||
// reset the streaming sounds back to the normal ones
|
// reset the streaming sounds back to the normal ones
|
||||||
pMinecraft->soundEngine->SetStreamingSounds(eStream_Overworld_Calm1,eStream_Overworld_piano3,
|
pMinecraft->soundEngine->SetStreamingSounds(eStream_Overworld_Menu1, eStream_Overworld_Menu4,
|
||||||
|
eStream_Overworld_Calm1, eStream_Overworld_piano3,
|
||||||
|
eStream_Overworld_Creative1, eStream_Overworld_Creative6,
|
||||||
eStream_Nether1, eStream_Nether4,
|
eStream_Nether1, eStream_Nether4,
|
||||||
eStream_end_dragon, eStream_end_end,
|
eStream_end_dragon, eStream_end_end,
|
||||||
eStream_CD_1);
|
eStream_CD_1);
|
||||||
|
|
|
||||||
|
|
@ -483,7 +483,7 @@ int DLCTexturePack::packMounted(LPVOID pParam,int iPad,DWORD dwErr,DWORD dwLicen
|
||||||
iEndStart=iOverworldC+iNetherC;
|
iEndStart=iOverworldC+iNetherC;
|
||||||
iEndC=dlcFile->GetCountofType(DLCAudioFile::e_AudioType_End);
|
iEndC=dlcFile->GetCountofType(DLCAudioFile::e_AudioType_End);
|
||||||
|
|
||||||
Minecraft::GetInstance()->soundEngine->SetStreamingSounds(iOverworldStart,iOverworldStart+iOverworldC-1,
|
Minecraft::GetInstance()->soundEngine->SetStreamingSounds(iOverworldStart,iOverworldStart+iOverworldC-1, iOverworldStart, iOverworldStart + iOverworldC - 1, iOverworldStart, iOverworldStart + iOverworldC - 1,
|
||||||
iNetherStart,iNetherStart+iNetherC-1,iEndStart,iEndStart+iEndC-1,iEndStart+iEndC); // push the CD start to after
|
iNetherStart,iNetherStart+iNetherC-1,iEndStart,iEndStart+iEndC-1,iEndStart+iEndC); // push the CD start to after
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue