From 6e59e4045f58599205de000fe224206bb496fa7d Mon Sep 17 00:00:00 2001 From: Fireblade <3+fireblade@noreply.neolegacy.dev> Date: Thu, 9 Jul 2026 20:31:16 -0400 Subject: [PATCH] feat: pick block + jukebox fixes --- Minecraft.Client/Common/Audio/SoundEngine.cpp | 28 +++- Minecraft.Client/Common/Audio/SoundEngine.h | 1 + Minecraft.Client/LevelRenderer.cpp | 3 +- Minecraft.Client/Minecraft.cpp | 143 ++++++++++++++++++ 4 files changed, 172 insertions(+), 3 deletions(-) diff --git a/Minecraft.Client/Common/Audio/SoundEngine.cpp b/Minecraft.Client/Common/Audio/SoundEngine.cpp index d9a94929..f24a760d 100644 --- a/Minecraft.Client/Common/Audio/SoundEngine.cpp +++ b/Minecraft.Client/Common/Audio/SoundEngine.cpp @@ -57,6 +57,7 @@ void SoundEngine::playUI(int iSound, float volume, float pitch) {} void SoundEngine::updateMusicVolume(float fVal) {} void SoundEngine::updateSoundEffectVolume(float fVal) {} +void SoundEngine::stopStreamingNow() {} void SoundEngine::add(const wstring& name, File *file) {} void SoundEngine::addMusic(const wstring& name, File *file) {} @@ -66,6 +67,22 @@ bool SoundEngine::isStreamingWavebankReady() { return true; } void SoundEngine::playMusicTick() {}; #else +void SoundEngine::stopStreamingNow() +{ + if (m_musicStreamActive) + { + ma_sound_stop(&m_musicStream); + ma_sound_uninit(&m_musicStream); + m_musicStreamActive = false; + } + + SetIsPlayingStreamingCDMusic(false); + SetIsPlayingStreamingGameMusic(false); + + m_StreamState = eMusicStreamState_Idle; + m_musicID = -1; + m_iMusicDelay = 0; +} #ifdef _WINDOWS64 char SoundEngine::m_szSoundPath[]={"Windows64Media\\Sound\\"}; @@ -904,8 +921,15 @@ void SoundEngine::playStreaming(const wstring& name, float x, float y, float z, { // jukebox m_StreamingAudioInfo.bIs3D=true; - m_musicID=getMusicID(name); - m_iMusicDelay=0; + m_musicID = getMusicID(name); + m_iMusicDelay = 0; + + if (m_StreamState == eMusicStreamState_Playing || m_StreamState == eMusicStreamState_Opening || m_musicStreamActive) + { + m_StreamState = eMusicStreamState_Fading; + m_musicFadeSecondsRemaining = MUSIC_FADE_DURATION_SECONDS; + m_musicFadeLastUpdateTime = std::chrono::steady_clock::now(); + } } } diff --git a/Minecraft.Client/Common/Audio/SoundEngine.h b/Minecraft.Client/Common/Audio/SoundEngine.h index 3cef9432..3fe3f9dd 100644 --- a/Minecraft.Client/Common/Audio/SoundEngine.h +++ b/Minecraft.Client/Common/Audio/SoundEngine.h @@ -135,6 +135,7 @@ public: 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; + void stopStreamingNow(); void playUI(int iSound, float volume, float pitch) override; void playMusicTick() override; void updateMusicVolume(float fVal) override; diff --git a/Minecraft.Client/LevelRenderer.cpp b/Minecraft.Client/LevelRenderer.cpp index 2bb48002..849e6a0d 100644 --- a/Minecraft.Client/LevelRenderer.cpp +++ b/Minecraft.Client/LevelRenderer.cpp @@ -3566,8 +3566,9 @@ void LevelRenderer::levelEvent(shared_ptr source, int type, int x, int y else { // 4J-PB - only play streaming music if there isn't already some playing - the CD playing may have finished, and game music started playing already - if(!mc->soundEngine->GetIsPlayingStreamingGameMusic()) + if(mc->soundEngine->GetIsPlayingStreamingCDMusic()) { + mc->soundEngine->stopStreamingNow(); level[playerIndex]->playStreamingMusic(L"", x, y, z); // 4J - used to pass nullptr, but using empty string here now instead } } diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 05194bef..86501331 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -3648,6 +3648,149 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) } } +#ifdef _WINDOWS64 + static bool wasMiddleMouseDown = false; + const bool middleMouseDown = (iPad == 0 && g_KBMInput.IsKBMActive() && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_MIDDLE)); + const bool pickBlockPressed = middleMouseDown && !wasMiddleMouseDown; + wasMiddleMouseDown = middleMouseDown; + + if (pickBlockPressed && gameMode->hasInfiniteItems() && hitResult != nullptr) + { + int pickedId = -1; + int pickedData = 0; + + if (hitResult->type == HitResult::TILE) + { + const int hitX = hitResult->x; + const int hitY = hitResult->y; + const int hitZ = hitResult->z; + const int tileId = level->getTile(hitX, hitY, hitZ); + + if (tileId > 0 && tileId < Tile::TILE_NUM_COUNT && Tile::tiles[tileId] != nullptr) + { + Tile *pickedTile = Tile::tiles[tileId]; + const int tileData = level->getData(hitX, hitY, hitZ); + + if (pickedTile->mayPick(tileData, false)) + { + pickedId = pickedTile->cloneTileId(level, hitX, hitY, hitZ); + pickedData = pickedTile->cloneTileData(level, hitX, hitY, hitZ); + } + } + } + else if (hitResult->type == HitResult::ENTITY && hitResult->entity != nullptr) + { + shared_ptr pickedEntity = hitResult->entity; + int eggAux = EntityIO::eTypeToIoid(pickedEntity->GetType()); + + if (eggAux >= 0) + { + if (pickedEntity->instanceof(eTYPE_GUARDIAN)) + { + shared_ptr pickedGuardian = dynamic_pointer_cast(pickedEntity); + if (pickedGuardian != nullptr && pickedGuardian->isElder()) + { + eggAux = EntityIO::eTypeToIoid(eTYPE_ELDER_GUARDIAN); + } + } + else if (pickedEntity->instanceof(eTYPE_HORSE)) + { + shared_ptr pickedHorse = dynamic_pointer_cast(pickedEntity); + if (pickedHorse != nullptr) + { + const int horseType = pickedHorse->getType(); + if (horseType != EntityHorse::TYPE_HORSE) + { + eggAux = (eggAux & 0xFFF) | ((horseType + 1) << 12); + } + } + } + else if (pickedEntity->instanceof(eTYPE_OCELOT)) + { + shared_ptr pickedOcelot = dynamic_pointer_cast(pickedEntity); + if (pickedOcelot != nullptr) + { + const int catType = pickedOcelot->getCatType(); + if (catType != Ocelot::TYPE_OCELOT) + { + eggAux = (eggAux & 0xFFF) | ((catType + 1) << 12); + } + } + } + + auto spawnEggIt = EntityIO::idsSpawnableInCreative.find(eggAux); + if (spawnEggIt == EntityIO::idsSpawnableInCreative.end()) + { + const int fallbackEggAux = eggAux & 0xFFF; + auto fallbackIt = EntityIO::idsSpawnableInCreative.find(fallbackEggAux); + if (fallbackIt != EntityIO::idsSpawnableInCreative.end()) + { + eggAux = fallbackEggAux; + } + else + { + eggAux = -1; + } + } + + if (eggAux >= 0 && Item::spawn_egg_Id >= 0 && Item::spawn_egg_Id < Item::items.length && Item::items[Item::spawn_egg_Id] != nullptr) + { + pickedId = Item::spawn_egg_Id; + pickedData = eggAux; + } + } + } + + if (pickedId >= 0 && pickedId < Item::items.length && Item::items[pickedId] != nullptr) + { + shared_ptr playerInventory = player->inventory; + const int previousSelected = playerInventory->selected; + const int fallbackSelected = (previousSelected >= 0 && previousSelected < Inventory::getSelectionSize()) ? previousSelected : 0; + int targetSlot = -1; + + for (int slot = 0; slot < Inventory::getSelectionSize(); ++slot) + { + shared_ptr hotbarItem = playerInventory->items[slot]; + if (hotbarItem != nullptr && hotbarItem->id == pickedId && + (!hotbarItem->isStackedByData() || hotbarItem->getAuxValue() == pickedData)) + { + targetSlot = slot; + break; + } + } + + if (targetSlot < 0) + { + for (int slot = 0; slot < Inventory::getSelectionSize(); ++slot) + { + if (playerInventory->items[slot] == nullptr) + { + targetSlot = slot; + break; + } + } + + if (targetSlot < 0) + { + targetSlot = fallbackSelected; + } + + playerInventory->items[targetSlot] = std::make_shared(Item::items[pickedId], 1, pickedData); + gameMode->handleCreativeModeItemAdd(playerInventory->items[targetSlot], 36 + targetSlot); + } + + playerInventory->selected = targetSlot; + + if( gameMode != nullptr && gameMode->getTutorial() != nullptr ) + { + gameMode->getTutorial()->onSelectedItemChanged(playerInventory->getSelected()); + } + + player->updateRichPresence(); + } + } +#endif + if( gameMode->isInputAllowed(MINECRAFT_ACTION_ACTION) ) { if((player->ullButtonsPressed&(1LL<