diff --git a/Minecraft.Client/Common/App_Defines.h b/Minecraft.Client/Common/App_Defines.h index 004436b2..d44eaa33 100644 --- a/Minecraft.Client/Common/App_Defines.h +++ b/Minecraft.Client/Common/App_Defines.h @@ -109,6 +109,7 @@ enum EGameHostOptionWorldSize #define GAMESETTING_EXCLUSIVEFULLSCREEN 0x02000000 #define GAMESETTING_CLASSICCRAFTING 0x04000000 #define GAMESETTING_CAVESOUNDS 0x08000000 +#define GAMESETTING_MINECARTSOUNDS 0x10000000 // defines for languages diff --git a/Minecraft.Client/Common/App_enums.h b/Minecraft.Client/Common/App_enums.h index 1564f088..d272bb51 100644 --- a/Minecraft.Client/Common/App_enums.h +++ b/Minecraft.Client/Common/App_enums.h @@ -185,6 +185,7 @@ enum eGameSetting //TU25 eGameSetting_ClassicCrafting, eGameSetting_CaveSounds, + eGameSetting_MinecartSounds, }; diff --git a/Minecraft.Client/Common/Audio/SoundEngine.cpp b/Minecraft.Client/Common/Audio/SoundEngine.cpp index 2828713d..7662c4f8 100644 --- a/Minecraft.Client/Common/Audio/SoundEngine.cpp +++ b/Minecraft.Client/Common/Audio/SoundEngine.cpp @@ -605,34 +605,8 @@ void SoundEngine::play(int iSound, float x, float y, float z, float volume, floa m_activeSounds.push_back(s); } -///////////////////////////////////////////// -// -// -// startElytraSound / stopElytraSound -// Manages a single persistent looping sound for elytra gliding. -// Call startElytraSound every tick while gliding (it no-ops if already running, -// just updates volume). Call stopElytraSound when gliding ends. -// -// IMPORTANT: m_elytraLoopingSound is NOT added to m_activeSounds. -// The tick() cleanup loop deletes sounds where is_playing()==false. -// A looping sound briefly reports is_playing()==false at the loop point, -// which would cause tick() to free it and leave m_elytraLoopingSound dangling. -// -///////////////////////////////////////////// -void SoundEngine::startElytraSound(float x, float y, float z, float volume, float pitch) +MiniAudioSound* SoundEngine::startLoopingSound(const wstring& name, float x, float y, float z, float volume, float pitch, bool bIs3D) { - // If already initialized just update volume and pitch - never reinitialize mid-flight. - if (m_elytraLoopingSound != nullptr) - { - float finalVolume = volume * m_MasterEffectsVolume * SFX_VOLUME_MULTIPLIER; - if (finalVolume > SFX_MAX_GAIN) finalVolume = SFX_MAX_GAIN; - ma_sound_set_volume(&m_elytraLoopingSound->sound, finalVolume); - ma_sound_set_pitch(&m_elytraLoopingSound->sound, pitch); - return; - } - - // Resolve file path using the same logic as play(). - wstring name = wchSoundNames[eSoundType_ITEM_ELYTRA_FLYING]; char* soundName = ConvertSoundPathToName(name); char basePath[256]; sprintf_s(basePath, "Windows64Media/Sound/Minecraft/%s", soundName); @@ -652,42 +626,100 @@ void SoundEngine::startElytraSound(float x, float y, float z, float volume, floa break; } } - if (!found) return; + if (!found) + { + return nullptr; + } MiniAudioSound* s = new MiniAudioSound(); memset(&s->info, 0, sizeof(AUDIO_INFO)); - s->info.volume = volume; s->info.pitch = pitch; - s->info.bIs3D = false; - s->info.iSound = eSoundType_ITEM_ELYTRA_FLYING + eSFX_MAX; + s->info.x = x; + s->info.y = y; + s->info.z = z; + s->info.volume = volume; + s->info.pitch = pitch; + s->info.bIs3D = bIs3D; + s->info.bUseSoundsPitchVal = false; - // Synchronous load so the sound is immediately ready - no ASYNC gap. - if (ma_sound_init_from_file(&m_engine, finalPath, 0, - nullptr, nullptr, &s->sound) != MA_SUCCESS) + if (ma_sound_init_from_file(&m_engine, finalPath, 0, nullptr, nullptr, &s->sound) != MA_SUCCESS) { delete s; - return; + return nullptr; } - ma_sound_set_spatialization_enabled(&s->sound, MA_FALSE); + ma_sound_set_spatialization_enabled(&s->sound, bIs3D ? MA_TRUE : MA_FALSE); ma_sound_set_looping(&s->sound, MA_TRUE); float finalVolume = volume * m_MasterEffectsVolume * SFX_VOLUME_MULTIPLIER; - if (finalVolume > SFX_MAX_GAIN) finalVolume = SFX_MAX_GAIN; + if (finalVolume > SFX_MAX_GAIN) + finalVolume = SFX_MAX_GAIN; ma_sound_set_volume(&s->sound, finalVolume); ma_sound_set_pitch(&s->sound, pitch); + if (bIs3D) + { + ma_sound_set_position(&s->sound, x, y, z); + } ma_sound_start(&s->sound); + return s; +} +void SoundEngine::updateLoopingSound(MiniAudioSound* sound, float x, float y, float z, float volume, float pitch) +{ + if (sound == nullptr) + { + return; + } + + float finalVolume = volume * m_MasterEffectsVolume * SFX_VOLUME_MULTIPLIER; + if (finalVolume > SFX_MAX_GAIN) + finalVolume = SFX_MAX_GAIN; + ma_sound_set_volume(&sound->sound, finalVolume); + ma_sound_set_pitch(&sound->sound, pitch); + ma_sound_set_position(&sound->sound, x, y, z); +} + +void SoundEngine::stopLoopingSound(MiniAudioSound* sound) +{ + if (sound == nullptr) + { + return; + } + + ma_sound_stop(&sound->sound); + ma_sound_uninit(&sound->sound); + delete sound; +} + +///////////////////////////////////////////// +// +// +// startElytraSound / stopElytraSound +// Manages a single persistent looping sound for elytra gliding. +// Call startElytraSound every tick while gliding (it no-ops if already running, +// just updates volume). Call stopElytraSound when gliding ends. +// +// IMPORTANT: m_elytraLoopingSound is NOT added to m_activeSounds. +// The tick() cleanup loop deletes sounds where is_playing()==false. +// A looping sound briefly reports is_playing()==false at the loop point, +// which would cause tick() to free it and leave m_elytraLoopingSound dangling. +// +///////////////////////////////////////////// +void SoundEngine::startElytraSound(float x, float y, float z, float volume, float pitch) +{ + // If already initialized just update volume and pitch - never reinitialize mid-flight. + if (m_elytraLoopingSound != nullptr) + { + updateLoopingSound(m_elytraLoopingSound, x, y, z, volume, pitch); + return; + } // NOT added to m_activeSounds - tick() cleanup would delete it at loop boundaries. - m_elytraLoopingSound = s; + m_elytraLoopingSound = startLoopingSound(wchSoundNames[eSoundType_ITEM_ELYTRA_FLYING], x, y, z, volume, pitch, false); } void SoundEngine::stopElytraSound() { if (m_elytraLoopingSound == nullptr) return; - - ma_sound_stop(&m_elytraLoopingSound->sound); - ma_sound_uninit(&m_elytraLoopingSound->sound); - delete m_elytraLoopingSound; + stopLoopingSound(m_elytraLoopingSound); m_elytraLoopingSound = nullptr; } ///////////////////////////////////////////// diff --git a/Minecraft.Client/Common/Audio/SoundEngine.h b/Minecraft.Client/Common/Audio/SoundEngine.h index 5a593df9..8b3ec7a2 100644 --- a/Minecraft.Client/Common/Audio/SoundEngine.h +++ b/Minecraft.Client/Common/Audio/SoundEngine.h @@ -127,6 +127,9 @@ public: void GetSoundName(char *szSoundName,int iSound); #endif void play(int iSound, float x, float y, float z, float volume, float pitch) override; + MiniAudioSound* startLoopingSound(const wstring& name, float x, float y, float z, float volume, float pitch, bool bIs3D = true); + void updateLoopingSound(MiniAudioSound* sound, float x, float y, float z, float volume, float pitch); + void stopLoopingSound(MiniAudioSound* sound); void startElytraSound(float x, float y, float z, float volume, float pitch); void stopElytraSound(); void playStreaming(const wstring& name, float x, float y , float z, float volume, float pitch, bool bMusicDelay=true) override; diff --git a/Minecraft.Client/Common/Consoles_App.cpp b/Minecraft.Client/Common/Consoles_App.cpp index cb400e4f..9627c7a9 100644 --- a/Minecraft.Client/Common/Consoles_App.cpp +++ b/Minecraft.Client/Common/Consoles_App.cpp @@ -1043,6 +1043,7 @@ int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,con //TU25 SetGameSettings(iPad, eGameSetting_ClassicCrafting, 0); SetGameSettings(iPad, eGameSetting_CaveSounds, 1); + SetGameSettings(iPad, eGameSetting_MinecartSounds, 1); // 4J-PB - leave these in, or remove from everywhere they are referenced! // Although probably best to leave in unless we split the profile settings into platform specific classes - having different meaning per platform for the same bitmask could get confusing @@ -1504,6 +1505,7 @@ void CMinecraftApp::ApplyGameSettingsChanged(int iPad) //TU25 ActionGameSettings(iPad, eGameSetting_ClassicCrafting); ActionGameSettings(iPad, eGameSetting_CaveSounds); + ActionGameSettings(iPad, eGameSetting_MinecartSounds); } void CMinecraftApp::ActionGameSettings(int iPad,eGameSetting eVal) @@ -2529,6 +2531,21 @@ void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucV GameSettingsA[iPad]->bSettingsChanged = true; } break; + case eGameSetting_MinecartSounds: + if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_MINECARTSOUNDS) != (ucVal & 0x01) << 28) + { + if (ucVal == 1) + { + GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_MINECARTSOUNDS; + } + else + { + GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_MINECARTSOUNDS; + } + ActionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; } } @@ -2670,6 +2687,9 @@ unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal) case eGameSetting_CaveSounds: return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CAVESOUNDS) >> 27; + case eGameSetting_MinecartSounds: + return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_MINECARTSOUNDS) >> 28; + case eGameSetting_VSync: return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_VSYNC)>>24; diff --git a/Minecraft.Client/Common/Media/MediaWindows64/SettingsAudioMenu1080.swf b/Minecraft.Client/Common/Media/MediaWindows64/SettingsAudioMenu1080.swf index 8e46ea2a..a0bbdfba 100644 Binary files a/Minecraft.Client/Common/Media/MediaWindows64/SettingsAudioMenu1080.swf and b/Minecraft.Client/Common/Media/MediaWindows64/SettingsAudioMenu1080.swf differ diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp index 7bfee03f..dc0e7b19 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp @@ -16,6 +16,8 @@ UIScene_SettingsAudioMenu::UIScene_SettingsAudioMenu(int iPad, void *initData, U m_checkboxCaveSounds.init(L"Cave Sounds",eControl_CaveSounds,(app.GetGameSettings(m_iPad,eGameSetting_CaveSounds)!=0)); + m_checkboxMinecartSounds.init(L"Minecart Sounds",eControl_MinecartSounds,(app.GetGameSettings(m_iPad,eGameSetting_MinecartSounds)!=0)); + doHorizontalResizeCheck(); if(app.GetLocalPlayerCount()>1) @@ -124,5 +126,8 @@ void UIScene_SettingsAudioMenu::handleCheckboxToggled(F64 controlId, bool select case eControl_CaveSounds: app.SetGameSettings(m_iPad, eGameSetting_CaveSounds, selected ? 1 : 0); break; + case eControl_MinecartSounds: + app.SetGameSettings(m_iPad, eGameSetting_MinecartSounds, selected ? 1 : 0); + break; } } diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h index b0123b5a..fdc2bbbc 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.h @@ -9,15 +9,18 @@ private: { eControl_Music, eControl_Sound, - eControl_CaveSounds + eControl_CaveSounds, + eControl_MinecartSounds }; UIControl_Slider m_sliderMusic, m_sliderSound; // Sliders UIControl_CheckBox m_checkboxCaveSounds; // Checkboxes + UIControl_CheckBox m_checkboxMinecartSounds; UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) UI_MAP_ELEMENT( m_sliderMusic, "Music") UI_MAP_ELEMENT( m_sliderSound, "Sound") UI_MAP_ELEMENT( m_checkboxCaveSounds, "CaveSounds") + UI_MAP_ELEMENT( m_checkboxMinecartSounds, "MinecartSounds") UI_END_MAP_ELEMENTS_AND_NAMES() public: diff --git a/Minecraft.Client/Windows64Media/Sound/Minecraft/mob/minecart/inside.ogg b/Minecraft.Client/Windows64Media/Sound/Minecraft/mob/minecart/inside.ogg new file mode 100644 index 00000000..92487c8c Binary files /dev/null and b/Minecraft.Client/Windows64Media/Sound/Minecraft/mob/minecart/inside.ogg differ diff --git a/Minecraft.Client/Windows64Media/Sound/Minecraft/mob/minecart/rolling.ogg b/Minecraft.Client/Windows64Media/Sound/Minecraft/mob/minecart/rolling.ogg new file mode 100644 index 00000000..534618f3 Binary files /dev/null and b/Minecraft.Client/Windows64Media/Sound/Minecraft/mob/minecart/rolling.ogg differ diff --git a/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml b/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml index 89c9928a..77fad9fd 100644 --- a/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml +++ b/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml @@ -6582,6 +6582,10 @@ Would you like to install the mash-up pack or texture pack now? Cave Sounds + + Minecart Sounds + + What would you like to do with this save game? diff --git a/Minecraft.World/Minecart.cpp b/Minecraft.World/Minecart.cpp index efefb7ea..1a06e5cd 100644 --- a/Minecraft.World/Minecart.cpp +++ b/Minecraft.World/Minecart.cpp @@ -13,6 +13,7 @@ #include "../Minecraft.Client/ServerLevel.h" #include "com.mojang.nbt.h" #include "Minecart.h" +#include "MinecartSoundInstance.h" #include "SharedConstants.h" @@ -44,7 +45,8 @@ void Minecart::_init() blocksBuilding = true; setSize(0.98f, 0.7f); heightOffset = bbHeight / 2.0f; - soundUpdater = nullptr; + m_rollingSound = nullptr; + m_ridingSound = nullptr; name = L""; // @@ -61,26 +63,43 @@ Minecart::Minecart(Level *level) : Entity( level ) Minecart::~Minecart() { - delete soundUpdater; + delete m_rollingSound; + delete m_ridingSound; } shared_ptr Minecart::createMinecart(Level *level, double x, double y, double z, int type) { + shared_ptr minecart; + switch (type) { case TYPE_CHEST: - return std::make_shared(level, x, y, z); + minecart = std::make_shared(level, x, y, z); + break; case TYPE_FURNACE: - return std::make_shared(level, x, y, z); + minecart = std::make_shared(level, x, y, z); + break; case TYPE_TNT: - return std::make_shared(level, x, y, z); + minecart = std::make_shared(level, x, y, z); + break; case TYPE_SPAWNER: - return std::make_shared(level, x, y, z); + minecart = std::make_shared(level, x, y, z); + break; case TYPE_HOPPER: - return std::make_shared(level, x, y, z); + minecart = std::make_shared(level, x, y, z); + break; default: - return std::make_shared(level, x, y, z); + minecart = std::make_shared(level, x, y, z); + break; } + + if (level != nullptr && level->isClientSide) + { + minecart->m_rollingSound = new MinecartSoundInstance(minecart); + minecart->m_ridingSound = new RidingMinecartSoundInstance(minecart); + } + + return minecart; } bool Minecart::makeStepSound() @@ -207,11 +226,36 @@ bool Minecart::isPickable() void Minecart::remove() { Entity::remove(); + // clean up sounds after invalidation + if (m_rollingSound) + { + delete m_rollingSound; + m_rollingSound = nullptr; + } + if (m_ridingSound) + { + delete m_ridingSound; + m_ridingSound = nullptr; + } //if (soundUpdater != nullptr) soundUpdater->tick(); } void Minecart::tick() { + // minecart tick handler + if (level->isClientSide) + { + if (m_rollingSound) + { + m_rollingSound->tick(); + } + + if (m_ridingSound) + { + m_ridingSound->tick(); + } + } + //if (soundUpdater != nullptr) soundUpdater->tick(); // 4J - make minecarts (server-side) tick twice, to put things back to how they were when we were accidently ticking them twice for( int i = 0; i < 2; i++ ) diff --git a/Minecraft.World/Minecart.h b/Minecraft.World/Minecart.h index bd1a69e6..e4a9121c 100644 --- a/Minecraft.World/Minecart.h +++ b/Minecraft.World/Minecart.h @@ -2,7 +2,8 @@ #include "Entity.h" class DamageSource; -class Tickable; +class MinecartSoundInstance; +class RidingMinecartSoundInstance; class Minecart : public Entity { @@ -30,7 +31,8 @@ private: static const int DATA_ID_CUSTOM_DISPLAY = 22; bool flipped; - Tickable *soundUpdater; + MinecartSoundInstance *m_rollingSound; + RidingMinecartSoundInstance *m_ridingSound; wstring name; protected: diff --git a/Minecraft.World/MinecartSoundInstance.cpp b/Minecraft.World/MinecartSoundInstance.cpp new file mode 100644 index 00000000..482ff8eb --- /dev/null +++ b/Minecraft.World/MinecartSoundInstance.cpp @@ -0,0 +1,175 @@ +#include "stdafx.h" +#include "MinecartSoundInstance.h" +#include "Minecart.h" +#include "net.minecraft.world.level.h" +#include "../Minecraft.Client/Minecraft.h" +#include "../Minecraft.Client/Common/Audio/SoundEngine.h" + +// MinecartSoundInstance + +MinecartSoundInstance::MinecartSoundInstance(shared_ptr minecart) + : m_minecart(minecart), m_bIsCurrentlyPlaying(false), m_sound(nullptr), m_volume(0.0f), m_pitch(1.0f) +{ +} + +MinecartSoundInstance::~MinecartSoundInstance() +{ + if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->stopLoopingSound(m_sound); + } + m_sound = nullptr; +} + +void MinecartSoundInstance::tick() +{ + if (!m_minecart || m_minecart->removed) + { + if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->stopLoopingSound(m_sound); + m_sound = nullptr; + } + m_bIsCurrentlyPlaying = false; + return; + } + + // minecart sound functionality check + if (!app.GetGameSettings(0, eGameSetting_MinecartSounds)) + { + if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->stopLoopingSound(m_sound); + m_sound = nullptr; + } + m_bIsCurrentlyPlaying = false; + return; + } + + // volume + pitch calculations + // relative to minecart velocity + double xd = m_minecart->xd; + double zd = m_minecart->zd; + double velocity = sqrt(xd * xd + zd * zd); + + if (velocity >= 0.01) + { + float clampedVel = (float)(velocity > 1.0 ? 1.0 : (velocity < 0.0 ? 0.0 : velocity)); + m_volume = clampedVel * 0.75f; + m_pitch = 1.0f; + + if (!m_bIsCurrentlyPlaying) + { + m_bIsCurrentlyPlaying = true; + if (Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + m_sound = Minecraft::GetInstance()->soundEngine->startLoopingSound(L"mob.minecart.rolling", (float)m_minecart->x, (float)m_minecart->y, (float)m_minecart->z, m_volume, m_pitch, true); + } + } + else if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->updateLoopingSound(m_sound, (float)m_minecart->x, (float)m_minecart->y, (float)m_minecart->z, m_volume, m_pitch); + } + } + else + { + if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->stopLoopingSound(m_sound); + m_sound = nullptr; + } + m_volume = 0.0f; + m_pitch = 0.0f; + m_bIsCurrentlyPlaying = false; + } +} + +// RidingMinecartSoundInstance + +RidingMinecartSoundInstance::RidingMinecartSoundInstance(shared_ptr minecart) + : m_minecart(minecart), m_bIsCurrentlyPlaying(false), m_sound(nullptr), m_volume(0.0f), m_pitch(0.0f) +{ +} + +RidingMinecartSoundInstance::~RidingMinecartSoundInstance() +{ + if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->stopLoopingSound(m_sound); + } + m_sound = nullptr; +} + +void RidingMinecartSoundInstance::tick() +{ + if (!m_minecart || m_minecart->removed) + { + if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->stopLoopingSound(m_sound); + m_sound = nullptr; + } + m_bIsCurrentlyPlaying = false; + return; + } + + // minecart sound functionality check + if (!app.GetGameSettings(0, eGameSetting_MinecartSounds)) + { + if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->stopLoopingSound(m_sound); + m_sound = nullptr; + } + m_bIsCurrentlyPlaying = false; + return; + } + + // minecart passenger check + if (m_minecart->rider.lock() == nullptr) + { + if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->stopLoopingSound(m_sound); + m_sound = nullptr; + } + m_bIsCurrentlyPlaying = false; + return; + } + + // volume + pitch calculations + // relative to minecart velocity + double xd = m_minecart->xd; + double zd = m_minecart->zd; + double velocity = sqrt(xd * xd + zd * zd); + + if (velocity >= 0.01) + { + float clampedVel = (float)(velocity > 1.0 ? 1.0 : (velocity < 0.0 ? 0.0 : velocity)); + m_volume = clampedVel * 0.75f; + m_pitch = 1.0f; + + if (!m_bIsCurrentlyPlaying) + { + m_bIsCurrentlyPlaying = true; + if (Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + m_sound = Minecraft::GetInstance()->soundEngine->startLoopingSound(L"mob.minecart.inside", (float)m_minecart->x, (float)m_minecart->y, (float)m_minecart->z, m_volume, m_pitch, false); + } + } + else if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->updateLoopingSound(m_sound, (float)m_minecart->x, (float)m_minecart->y, (float)m_minecart->z, m_volume, m_pitch); + } + } + else + { + if (m_sound && Minecraft::GetInstance() && Minecraft::GetInstance()->soundEngine) + { + Minecraft::GetInstance()->soundEngine->stopLoopingSound(m_sound); + m_sound = nullptr; + } + m_volume = 0.0f; + m_bIsCurrentlyPlaying = false; + } +} diff --git a/Minecraft.World/MinecartSoundInstance.h b/Minecraft.World/MinecartSoundInstance.h new file mode 100644 index 00000000..e7d2ba78 --- /dev/null +++ b/Minecraft.World/MinecartSoundInstance.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +class Minecart; +class SoundEngine; +struct MiniAudioSound; + +// minecart rolling sound +class MinecartSoundInstance +{ +protected: + shared_ptr m_minecart; + bool m_bIsCurrentlyPlaying; + MiniAudioSound* m_sound; + float m_volume; + float m_pitch; + +public: + MinecartSoundInstance(shared_ptr minecart); + virtual ~MinecartSoundInstance(); + + virtual void tick(); + bool isCurrentlyPlaying() const { return m_bIsCurrentlyPlaying; } +}; + +// minecart passenger sound +class RidingMinecartSoundInstance +{ +protected: + shared_ptr m_minecart; + bool m_bIsCurrentlyPlaying; + MiniAudioSound* m_sound; + float m_volume; + float m_pitch; + +public: + RidingMinecartSoundInstance(shared_ptr minecart); + virtual ~RidingMinecartSoundInstance(); + + virtual void tick(); + bool isCurrentlyPlaying() const { return m_bIsCurrentlyPlaying; } +}; diff --git a/Minecraft.World/cmake/sources/Common.cmake b/Minecraft.World/cmake/sources/Common.cmake index 8c201c0b..3d522d3d 100644 --- a/Minecraft.World/cmake/sources/Common.cmake +++ b/Minecraft.World/cmake/sources/Common.cmake @@ -838,6 +838,8 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_ENTITY_ITEM "${CMAKE_CURRENT_SOURCE_DIR}/ItemEntity.h" "${CMAKE_CURRENT_SOURCE_DIR}/Minecart.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Minecart.h" + "${CMAKE_CURRENT_SOURCE_DIR}/MinecartSoundInstance.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/MinecartSoundInstance.h" "${CMAKE_CURRENT_SOURCE_DIR}/MinecartChest.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MinecartChest.h" "${CMAKE_CURRENT_SOURCE_DIR}/MinecartContainer.cpp"