diff --git a/Minecraft.Client/Common/Audio/SoundEngine.cpp b/Minecraft.Client/Common/Audio/SoundEngine.cpp index debf8933..88d0d9e8 100644 --- a/Minecraft.Client/Common/Audio/SoundEngine.cpp +++ b/Minecraft.Client/Common/Audio/SoundEngine.cpp @@ -1,5 +1,4 @@ #include "SoundEngine.h" -#include "../Consoles_App.h" #include "../../MultiplayerLocalPlayer.h" #include "../../../Minecraft.World/net.minecraft.world.level.h" #include "../../../Minecraft.World/leveldata.h" @@ -18,9 +17,6 @@ #define MA_NO_WINMM #define MINIAUDIO_IMPLEMENTATION #include "../Libs/audio/miniaudio.h" -#include -#include -#include char SoundEngine::m_szMiscSoundPath[]={"Assets/Sounds/Misc/%s"}; char SoundEngine::m_szUISoundPath[]={"Assets/Sounds/UI/%s"}; @@ -142,9 +138,7 @@ void SoundEngine::SetStreamingSounds(int iOverworldMin, int iOverWorldMax, int i // array to monitor recently played tracks if(m_bHeardTrackA) - { delete [] m_bHeardTrackA; - } m_bHeardTrackA = new bool[iEndMax+1]; memset(m_bHeardTrackA, 0, sizeof(bool) * (iEndMax + 1)); @@ -272,19 +266,13 @@ inline void SoundEngine::getGameModeMusicID(Minecraft* pMinecraft, unsigned int /* // TODO(3UR): this is a part of minigames also in the future other minigame ids will need to be handled for now TU30 only checks for BATTLE else if (pMinecraft->GetCustomGameMode() && CustomGameModeInst::GetId() == EMiniGameId::BATTLE) // @3UR: thanks https://github.com/GRAnimated/MinecraftLCE/blob/6947670d152582457bfe02bd909ee30a7ab7eb55/src/Minecraft.World/net/minecraft/world/level/gamemode/minigames/EMiniGameId.h#L3 - { m_musicID = getMusicID(eMusicType_Battle); - } */ else - { m_musicID = getMusicID(eMusicType_Overworld); - } } else - { m_musicID = getMusicID(eMusicType_Menu); - } } } @@ -293,11 +281,6 @@ inline void SoundEngine::getGameModeMusicID(Minecraft* pMinecraft, unsigned int // tick // ///////////////////////////////////////////// - -#ifdef __PSVITA__ -static S32 running = AIL_ms_count(); -#endif - void SoundEngine::tick(shared_ptr *players, float a) { ConsoleSoundEngine::tick(); @@ -332,9 +315,7 @@ void SoundEngine::tick(shared_ptr *players, float a) listenerCount++; } else - { m_ListenerA[i].bValid=false; - } } } @@ -351,12 +332,7 @@ void SoundEngine::tick(shared_ptr *players, float a) } m_validListenerCount = listenerCount; -#ifdef __PSVITA__ - // AP - Show that a change has occurred so we know to update the values at the next Mixer callback - SoundEngine_Change = true; -#else updateMiniAudio(); -#endif } ///////////////////////////////////////////// @@ -398,10 +374,6 @@ SoundEngine::SoundEngine() memset(CurrentSoundsPlaying, 0, sizeof(int) * (eSoundType_MAX + eSFX_MAX)); memset(m_ListenerA, 0, sizeof(AUDIO_LISTENER) * XUSER_MAX_COUNT); - -#ifdef __ORBIS__ - m_hBGMAudio=GetAudioBGMHandle(); -#endif } SoundEngine::~SoundEngine() @@ -457,73 +429,67 @@ void SoundEngine::play(int iSound, float x, float y, float z, float volume, floa } wstring name = wchSoundNames[iSound]; - char* SoundName = (char*)ConvertSoundPathToName(name); - app.DebugPrintf(6, - "PlaySound - %d - Sounds/Misc/%s (%f %f %f, vol %f, pitch %f)\n", - iSound, SoundName, x, y, z, volume, pitch); + std::vector* validPaths = nullptr; + auto it = m_sfxPathCache.find(iSound); - char basePath[256]; - sprintf_s(basePath, m_szMiscSoundPath, SoundName); + if (it != m_sfxPathCache.end()) + { + validPaths = &it->second; + app.DebugPrintf(6, "Cache - PlaySound - %d - Sounds/Misc/%s (%f %f %f, vol %f, pitch %f)\n", + iSound, SoundName, x, y, z, volume, pitch); + } + else + { + std::vector foundPaths; - char finalPath[256]; - sprintf_s(finalPath, "%s.wav", basePath); + app.DebugPrintf(6, "PlaySound - %d - Sounds/Misc/%s (%f %f %f, vol %f, pitch %f)\n", + iSound, SoundName, x, y, z, volume, pitch); - const char* extensions[] = { ".ogg", ".wav" }; - size_t extCount = sizeof(extensions) / sizeof(extensions[0]); - bool found = false; + char basePath[256]; + sprintf_s(basePath, m_szMiscSoundPath, SoundName); - for (size_t extIdx = 0; extIdx < extCount; extIdx++) - { - char basePlusExt[256]; - sprintf_s(basePlusExt, "%s%s", basePath, extensions[extIdx]); - - if (fs::exists(basePlusExt)) - { - sprintf_s(finalPath, "%s", basePlusExt); - found = true; - break; - } - } + const char* extensions[] = { ".ogg", ".wav" }; + size_t count = sizeof(extensions) / sizeof(extensions[0]); - if (!found) - { - int count = 0; + for (size_t i = 0; i < count; i++) + { + char path[256]; + sprintf_s(path, "%s%s", basePath, extensions[i]); + if (fs::exists(path)) + foundPaths.push_back(path); + } - for (size_t extIdx = 0; extIdx < extCount; extIdx++) - { + if (foundPaths.empty()) + { for (size_t i = 1; i < 32; i++) - { - char numberedPath[256]; - sprintf_s(numberedPath, "%s%d%s", basePath, i, extensions[extIdx]); - - if (fs::exists(numberedPath)) - count = i; - } - } + { + for (size_t i2 = 0; i2 < count; i2++) + { + char path[256]; + sprintf_s(path, "%s%d%s", basePath, i, extensions[i2]); + if (fs::exists(path)) + foundPaths.push_back(path); + } + } + } - if (count > 0) + m_sfxPathCache[iSound] = foundPaths; + validPaths = &m_sfxPathCache[iSound]; + + if (validPaths->empty()) { - int chosen = (rand() % count) + 1; - for (size_t extIdx = 0; extIdx < extCount; extIdx++) - { - char numberedPath[256]; - sprintf_s(numberedPath, "%s%d%s", basePath, chosen, extensions[extIdx]); - - if (fs::exists(numberedPath)) - { - sprintf_s(finalPath, "%s", numberedPath); - found = true; - break; - } - } - if (!found) - { - sprintf_s(finalPath, "%s%d.wav", basePath, chosen); - } + app.DebugPrintf("No sound file found: %s\n", basePath); + return; } - } + } + + if (validPaths->empty()) + return; + + int chosen = random->nextInt((int)validPaths->size()); + const char* finalPath = (*validPaths)[chosen].c_str(); MiniAudioSound* s = new MiniAudioSound(); memset(&s->info, 0, sizeof(AUDIO_INFO)); @@ -541,7 +507,7 @@ void SoundEngine::play(int iSound, float x, float y, float z, float volume, floa if (ma_sound_init_from_file( &m_engine, finalPath, - MA_SOUND_FLAG_ASYNC, + MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, nullptr, nullptr, &s->sound) != MA_SUCCESS) @@ -576,39 +542,47 @@ void SoundEngine::play(int iSound, float x, float y, float z, float volume, floa ///////////////////////////////////////////// void SoundEngine::playUI(int iSound, float volume, float pitch) { - wstring name; - name = wchUISoundNames[iSound]; + std::string finalPathStr; + auto it = m_uiPathCache.find(iSound); + wstring name = wchUISoundNames[iSound]; char* SoundName = (char*)ConvertSoundPathToName(name); - app.DebugPrintf(6, - "PlaySound - %d - Sounds/UI/%s (vol %f, pitch %f)\n", - iSound, SoundName, volume, pitch); + if (it != m_uiPathCache.end()) + { + finalPathStr = it->second; + app.DebugPrintf(6, "Cache - PlaySound - %d - Sounds/UI/%s (vol %f, pitch %f)\n", + iSound, SoundName, volume, pitch); + } + else + { + app.DebugPrintf(6, "PlaySound - %d - Sounds/UI/%s (vol %f, pitch %f)\n", + iSound, SoundName, volume, pitch); - char basePath[256]; - sprintf_s(basePath, m_szUISoundPath, SoundName); + char basePath[256]; + sprintf_s(basePath, m_szUISoundPath, SoundName); + + bool found = false; - char finalPath[256]; - sprintf_s(finalPath, "%s.wav", basePath); + const char* extensions[] = { ".ogg", ".wav" }; + size_t count = sizeof(extensions) / sizeof(extensions[0]); + for (size_t i = 0; i < count; i++) + { + char path[256]; + sprintf_s(path, "%s%s", basePath, extensions[i]); + if (fs::exists(path)) + { + finalPathStr = path; + found = true; + break; + } + } + + if (!found) + app.DebugPrintf("No sound file found for UI sound: %s\n", basePath); - const char* extensions[] = { ".ogg", ".wav" }; - size_t count = sizeof(extensions) / sizeof(extensions[0]); - bool found = false; - - for (size_t i = 0; i < count; i++) - { - sprintf_s(finalPath, "%s%s", basePath, extensions[i]); - if (fs::exists(finalPath)) - { - found = true; - break; - } - } - if (!found) - { - app.DebugPrintf("No sound file found for UI sound: %s\n", basePath); - return; - } + m_uiPathCache[iSound] = finalPathStr; + } MiniAudioSound* s = new MiniAudioSound(); memset(&s->info, 0, sizeof(AUDIO_INFO)); @@ -620,14 +594,14 @@ void SoundEngine::playUI(int iSound, float volume, float pitch) if (ma_sound_init_from_file( &m_engine, - finalPath, - MA_SOUND_FLAG_ASYNC, + finalPathStr.c_str(), + MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, nullptr, nullptr, &s->sound) != MA_SUCCESS) { delete s; - app.DebugPrintf("ma_sound_init_from_file failed: %s\n", finalPath); + app.DebugPrintf("Failed to initialize sound from file: %s\n", finalPathStr.c_str()); return; } @@ -669,13 +643,9 @@ void SoundEngine::playStreaming(const wstring& name, float x, float y , float z, m_StreamingAudioInfo.pitch = pitch; if(m_StreamState == eMusicStreamState_Playing) - { m_StreamState = eMusicStreamState_Stop; - } else if(m_StreamState == eMusicStreamState_Opening) - { m_StreamState = eMusicStreamState_OpeningCancel; - } if(name.empty()) { @@ -716,13 +686,9 @@ void SoundEngine::playStreaming(const wstring& name, float x, float y , float z, m_musicID = getMusicID(eMusicType_End); } else if(playerInNether) - { m_musicID = getMusicID(eMusicType_Nether); - } else - { getGameModeMusicID(pMinecraft, i); - } } else { @@ -733,7 +699,6 @@ void SoundEngine::playStreaming(const wstring& name, float x, float y , float z, } } - 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 @@ -756,9 +721,7 @@ int SoundEngine::GetRandomishTrack(int iStart,int iEnd) 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 @@ -774,9 +737,7 @@ int SoundEngine::GetRandomishTrack(int iStart,int iEnd) break; } else - { app.DebugPrintf("(%d) Skipping track %d already heard it recently\n",i,iVal); - } } app.DebugPrintf("Select track %d\n",iVal); @@ -871,13 +832,9 @@ int SoundEngine::getMusicID(const wstring& name) float SoundEngine::getMasterMusicVolume() { if( m_bSystemMusicPlaying ) - { return 0.0f; - } else - { return m_MasterMusicVolume; - } } ///////////////////////////////////////////// @@ -958,10 +915,7 @@ int SoundEngine::OpenStreamThreadProc(void* lpParameter) ///////////////////////////////////////////// void SoundEngine::playMusicTick() { -// AP - vita will update the music during the mixer callback -#ifndef __PSVITA__ playMusicUpdate(); -#endif } // AP - moved to a separate function so it can be called from the mixer callback on Vita @@ -991,28 +945,8 @@ void SoundEngine::playMusicUpdate() if(m_musicID!=-1) { // start playing it - - -#if ( defined __PS3__ || defined __PSVITA__ || defined __ORBIS__ ) - -#ifdef __PS3__ - // 4J-PB - Need to check if we are a patched BD build - if(app.GetBootedFromDiscPatch()) - { - sprintf(m_szStreamName,"%s/%s",app.GetBDUsrDirPath(m_szMusicPath), m_szMusicPath ); - app.DebugPrintf("SoundEngine::playMusicUpdate - (booted from disc patch) music path - %s",m_szStreamName); - } - else - { - sprintf(m_szStreamName,"%s/%s",getUsrDirPath(), m_szMusicPath ); - } -#else - sprintf(m_szStreamName,"%s/%s",getUsrDirPath(), m_szMusicPath ); -#endif - -#else strcpy_s((char *)m_szStreamName, _countof(m_szStreamName), m_szMusicPath); -#endif + // are we using a mash-up pack? //if(pMinecraft && !pMinecraft->skins->isUsingDefaultSkin() && pMinecraft->skins->getSelected()->hasAudio()) if(Minecraft::GetInstance()->skins->getSelected()->hasAudio()) @@ -1033,25 +967,14 @@ void SoundEngine::playMusicUpdate() SetIsPlayingStreamingGameMusic(true); SetIsPlayingStreamingCDMusic(false); m_StreamingAudioInfo.bIs3D=false; - -#ifdef _XBOX_ONE - wstring &wstrSoundName=dlcAudioFile->GetSoundName(m_musicID); - wstring wstrFile=L"TPACK:\\Data\\" + wstrSoundName +L".wav"; - std::wstring mountedPath = StorageManager.GetMountedPath(wstrFile); - wcstombs(m_szStreamName,mountedPath.c_str(),255); -#else + wstring &wstrSoundName=dlcAudioFile->GetSoundName(m_musicID); char szName[255]; wcstombs_s(nullptr, szName, sizeof(szName), wstrSoundName.c_str(), _TRUNCATE); -#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ - string strFile="TPACK:/Data/" + string(szName) + ".wav"; -#else string strFile="TPACK:\\Data\\" + string(szName) + ".wav"; -#endif std::string mountedPath = StorageManager.GetMountedPath(strFile); strcpy_s(m_szStreamName,mountedPath.c_str()); -#endif } else { @@ -1067,44 +990,7 @@ void SoundEngine::playMusicUpdate() } else { - // 4J-PB - if this is a PS3 disc patch, we have to check if the music file is in the patch data -#ifdef __PS3__ - if(app.GetBootedFromDiscPatch() && (m_musicID(m_szStreamName), "rb") == 0 && pFile) - { fclose(pFile); - } else { const char* extensions[] = { ".ogg", ".wav" }; @@ -1160,9 +1042,8 @@ void SoundEngine::playMusicUpdate() if (!found) { if (dotPos != nullptr) - { strcpy_s(dotPos, 5, ".wav"); - } + app.DebugPrintf("WARNING: No audio file found for music ID %d (tried .ogg, .wav)\n", m_musicID); return; } @@ -1216,9 +1097,7 @@ void SoundEngine::playMusicUpdate() ma_sound_set_position(&m_musicStream, m_StreamingAudioInfo.x, m_StreamingAudioInfo.y, -m_StreamingAudioInfo.z); } else - { ma_sound_set_spatialization_enabled(&m_musicStream, MA_FALSE); - } ma_sound_set_pitch(&m_musicStream, m_StreamingAudioInfo.pitch); @@ -1349,9 +1228,7 @@ void SoundEngine::playMusicUpdate() } /* //This is setting the music in loop else if ( !playerInEnd && !playerInNether ) - { getGameModeMusicID(pMinecraft, i); - } */ // volume change required? @@ -1394,9 +1271,7 @@ void SoundEngine::playMusicUpdate() float relZ = m_StreamingAudioInfo.z - m_ListenerA[iClosestListener].vPosition.z; if (m_musicStreamActive) - { ma_sound_set_position(&m_musicStream, relX, relY, relZ); - } } } @@ -1484,11 +1359,12 @@ char *SoundEngine::ConvertSoundPathToName(const wstring& name, bool bConvertSpac for(unsigned int i = 0; i < name.length(); i++ ) { wchar_t c = name[i]; - if(c=='.') c='/'; + if(c=='.') + c='/'; + if(bConvertSpaces) - { if(c==' ') c='_'; - } + buf[i] = (char)c; } buf[name.length()] = 0; diff --git a/Minecraft.Client/Common/Audio/SoundEngine.h b/Minecraft.Client/Common/Audio/SoundEngine.h index fdbab468..bbaf4baa 100644 --- a/Minecraft.Client/Common/Audio/SoundEngine.h +++ b/Minecraft.Client/Common/Audio/SoundEngine.h @@ -100,11 +100,7 @@ enum eMusicStreamState typedef struct { - #ifndef _WINDOWS64 - F32 x,y,z,volume,pitch; - #else float x,y,z,volume,pitch; - #endif int iSound; bool bIs3D; bool bUseSoundsPitchVal; @@ -114,7 +110,6 @@ typedef struct } AUDIO_INFO; -#ifdef _WINDOWS64 struct MiniAudioSound { ma_sound sound; @@ -123,7 +118,6 @@ struct MiniAudioSound }; extern std::vector m_activeSounds; -#endif class SoundEngine : public ConsoleSoundEngine { @@ -158,12 +152,9 @@ public: private: float getMasterMusicVolume(); // platform specific functions -#ifdef __PS3__ - int initAudioHardware(int iMinSpeakers); -#else + int initAudioHardware(int iMinSpeakers) override { return iMinSpeakers;} -#endif int GetRandomishTrack(int iStart,int iEnd); @@ -208,7 +199,6 @@ private: int m_iStream_CD_1; bool *m_bHeardTrackA; -#ifdef __ORBIS__ - int32_t m_hBGMAudio; -#endif + std::unordered_map> m_sfxPathCache; + std::unordered_map m_uiPathCache; }; \ No newline at end of file diff --git a/Minecraft.Client/EntityRenderer.cpp b/Minecraft.Client/EntityRenderer.cpp index 704653fc..0ca21632 100644 --- a/Minecraft.Client/EntityRenderer.cpp +++ b/Minecraft.Client/EntityRenderer.cpp @@ -146,8 +146,8 @@ void EntityRenderer::renderFlame(shared_ptr e, double x, double y, doubl t->end(); glPopMatrix(); glEnable(GL_LIGHTING); - } + void EntityRenderer::renderShadow(shared_ptr e, double x, double y, double z, float pow, float a) { glDisable(GL_LIGHTING); diff --git a/Minecraft.Client/MemTexture.cpp b/Minecraft.Client/MemTexture.cpp index 243adf52..28322a7b 100644 --- a/Minecraft.Client/MemTexture.cpp +++ b/Minecraft.Client/MemTexture.cpp @@ -15,16 +15,6 @@ MemTexture::MemTexture(const wstring& _url, PBYTE pbData,DWORD dwBytes, MemTextu //loadedImage=Textures::getTexture() // 4J - remember to add deletes in here for any created BufferedImages when implemented loadedImage = new BufferedImage(pbData,dwBytes); - if(processor==nullptr) - { - - } - else - { - //loadedImage=processor.process(ImageIO.read(huc.getInputStream())); - } - - } MemTexture::~MemTexture() diff --git a/Minecraft.Client/Textures.cpp b/Minecraft.Client/Textures.cpp index 8aed7a75..a341165b 100644 --- a/Minecraft.Client/Textures.cpp +++ b/Minecraft.Client/Textures.cpp @@ -295,7 +295,7 @@ void Textures::loadIndexedTextures() intArray Textures::loadTexturePixels(TEXTURE_NAME texId, const wstring& resourceName) { - TexturePack *skin = skins->getSelected(); + //TexturePack *skin = skins->getSelected(); { intArray id = pixelsMap[resourceName]; @@ -1097,172 +1097,147 @@ void Textures::removeHttpTexture(const wstring& url) int Textures::loadMemTexture(const wstring& url, const wstring& backup) { MemTexture *texture = nullptr; + auto it = memTextures.find(url); if (it != memTextures.end()) - { - texture = (*it).second; - } + texture = it->second.get(); + if(texture == nullptr && app.IsFileInMemoryTextures(url)) { // If we haven't loaded it yet, but we have the data for it then add it texture = addMemTexture(url, new MobSkinMemTextureProcessor() ); } + if(texture != nullptr) { + texture->ticksSinceLastUse = 0; + if (texture->loadedImage != nullptr && !texture->isLoaded) { // 4J - Disable mipmapping in general for skins & capes. Have seen problems with edge-on polys for some eg mumbo jumbo - if( ( url.substr(0,7) == L"dlcskin" ) || - ( url.substr(0,7) == L"dlccape" ) ) - { - MIPMAP = false; - } + bool isDlc = (url.compare(0, 7, L"dlcskin") == 0) || (url.compare(0, 7, L"dlccape") == 0); + if (isDlc) + MIPMAP = false; if (texture->id < 0) - { texture->id = getTexture(texture->loadedImage, C4JRender::TEXTURE_FORMAT_RxGyBzAw, MIPMAP); - } else - { loadTexture(texture->loadedImage, texture->id); - } + texture->isLoaded = true; MIPMAP = true; } } + if (texture == nullptr || texture->id < 0) { - if (backup.empty() ) return -1; + if (backup.empty() ) + return -1; + return loadTexture(TN_COUNT,backup); } + return texture->id; } int Textures::loadMemTexture(const wstring& url, int backup) { MemTexture *texture = nullptr; + auto it = memTextures.find(url); if (it != memTextures.end()) - { - texture = (*it).second; - } + texture = it->second.get(); + if(texture == nullptr && app.IsFileInMemoryTextures(url)) { // If we haven't loaded it yet, but we have the data for it then add it texture = addMemTexture(url, new MobSkinMemTextureProcessor() ); } + if(texture != nullptr) { texture->ticksSinceLastUse = 0; + if (texture->loadedImage != nullptr && !texture->isLoaded) { // 4J - Disable mipmapping in general for skins & capes. Have seen problems with edge-on polys for some eg mumbo jumbo - if( ( url.substr(0,7) == L"dlcskin" ) || - ( url.substr(0,7) == L"dlccape" ) ) - { - MIPMAP = false; - } + bool isDlc = (url.compare(0, 7, L"dlcskin") == 0) || (url.compare(0, 7, L"dlccape") == 0); + if (isDlc) MIPMAP = false; + if (texture->id < 0) - { texture->id = getTexture(texture->loadedImage, C4JRender::TEXTURE_FORMAT_RxGyBzAw, MIPMAP); - } else - { loadTexture(texture->loadedImage, texture->id); - } + texture->isLoaded = true; MIPMAP = true; } } if (texture == nullptr || texture->id < 0) - { return loadTexture(backup); - } + return texture->id; } MemTexture *Textures::addMemTexture(const wstring& name,MemTextureProcessor *processor) { - MemTexture *texture = nullptr; + std::unique_ptr safeProcessor(processor); + auto it = memTextures.find(name); if (it != memTextures.end()) { - texture = (*it).second; - } - if(texture == nullptr) - { - // can we find it in the app mem files? - PBYTE pbData=nullptr; - DWORD dwBytes=0; - app.GetMemFileDetails(name,&pbData,&dwBytes); + MemTexture* texture = it->second.get(); + if (texture) + texture->count++; - if(dwBytes!=0) - { - texture = new MemTexture(name, pbData, dwBytes, processor); - memTextures[name] = texture; - } - else - { - // 4J Stu - Make an entry for this anyway and we can populate it later - memTextures[name] = nullptr; - } + return texture; + } + + // can we find it in the app mem files? + PBYTE pbData = nullptr; + DWORD dwBytes = 0; + app.GetMemFileDetails(name,&pbData,&dwBytes); + + if(dwBytes!=0) + { + memTextures[name] = std::make_unique(name, pbData, dwBytes, safeProcessor.get()); + return memTextures[name].get(); } else { - texture->count++; + // 4J Stu - Make an entry for this anyway and we can populate it later + memTextures[name] = nullptr; + return nullptr; } - - delete processor; - - return texture; } -// MemTexture *Textures::getMemTexture(const wstring& url, MemTextureProcessor *processor) -// { -// MemTexture *texture = memTextures[url]; -// if (texture != nullptr) -// { -// texture->count++; -// } -// return texture; -// } - void Textures::removeMemTexture(const wstring& url) { - MemTexture *texture = nullptr; auto it = memTextures.find(url); - if (it != memTextures.end()) - { - texture = (*it).second; + if (it == memTextures.end()) return; - // If it's nullptr then we should just remove the entry - if( texture == nullptr ) memTextures.erase(url); - } - if(texture != nullptr) + if (it->second == nullptr) + { + memTextures.erase(it); + return; + } + + MemTexture* texture = it->second.get(); + texture->count--; + if (texture->count == 0) { - texture->count--; - if (texture->count == 0) - { - if (texture->id >= 0) releaseTexture(texture->id); - memTextures.erase(url); - delete texture; - } + if (texture->id >= 0) + releaseTexture(texture->id); + + memTextures.erase(it); } } void Textures::tick(bool updateTextures, bool tickDynamics) // 4J added updateTextures parameter & tickDynamics { MemSect(22); - if(tickDynamics) + if(tickDynamics && updateTextures) { - // 4J - added - if we aren't updating the final renderer textures, just tick each of the dynamic textures instead. This is used so that in frames were we have multiple - // ticks due to framerate compensation, that we don't lock the renderer textures twice needlessly and force the CPU to sync with the GPU. - if( !updateTextures ) - { - MemSect(0); - return; - } - // 4J - added - tell renderer that we're about to do a block of dynamic texture updates, so we can unlock the resources after they are done rather than a series of locks/unlocks //RenderManager.TextureDynamicUpdateStart(); terrain->cycleAnimationFrames(); @@ -1274,31 +1249,26 @@ void Textures::tick(bool updateTextures, bool tickDynamics) // 4J added updateTe // have their ticksSinceLastUse reset in Textures::loadMemTexture. for (auto it = memTextures.begin(); it != memTextures.end();) { - MemTexture *tex = it->second; - - if( tex && ( ++tex->ticksSinceLastUse > MemTexture::UNUSED_TICKS_TO_FREE ) ) + MemTexture* tex = it->second.get(); + if( tex && ( ++tex->ticksSinceLastUse > MemTexture::UNUSED_TICKS_TO_FREE ) ) { - if (tex->id >= 0) releaseTexture(tex->id); - delete tex; + if (tex->id >= 0) + releaseTexture(tex->id); + it = memTextures.erase(it); } else - { - it++; - } - + ++it; } MemSect(0); } void Textures::reloadAll() { - TexturePack *skin = skins->getSelected(); + //TexturePack *skin = skins->getSelected(); for( int i = 0; i < TN_COUNT - 2; i++ ) - { releaseTexture(preLoadedIdx[i]); - } idMap.clear(); loadedImages.clear(); @@ -1306,66 +1276,10 @@ void Textures::reloadAll() loadIndexedTextures(); pixelsMap.clear(); - // 4J Stu - These are not used any more - //WaterColor::init(loadTexturePixels(L"misc/watercolor.png")); - //GrassColor::init(loadTexturePixels(L"misc/grasscolor.png")); - //FoliageColor::init(loadTexturePixels(L"misc/foliagecolor.png")); stitch(); skins->clearInvalidTexturePacks(); - -#if 0 - for(auto it = loadedImages.begin(); it != loadedImages.end(); it++ ) - { - BufferedImage *image = it->second; - loadTexture(image, it->first); - } - - for(auto it = httpTextures.begin(); it != httpTextures.end(); it++ ) - { - it->second->isLoaded = false; - } - - for(auto it = memTextures.begin(); it != memTextures.end(); it++ ) - { - it->second->isLoaded = false; - } - - - for( auto it = idMap.begin(); it != idMap.end(); it++ ) - { - wstring name = it->first; - - int id = idMap[name]; - BufferedImage *image; - - wstring prefix = L"%blur%"; - bool blur = name.substr(0, prefix.size()).compare(prefix) == 0; //name.startsWith("%blur%"); - if (blur) name = name.substr(6); - - prefix = L"%clamp%"; - bool clamp = name.substr(0, prefix.size()).compare(prefix) == 0; //name.startsWith("%clamp%"); - if (clamp) name = name.substr(7); - - image = readImage(skin->getResource(name)); - - loadTexture(image, id, blur, clamp); - delete image; - } - for( auto it = pixelsMap.begin(); it != pixelsMap.end(); it++ ) - { - wstring name = it->first; - BufferedImage *image = readImage(skin->getResource(name)); - - loadTexturePixels(image, pixelsMap[name]); - delete image; - } -#endif - - // Recalculate fonts - //Minecraft::GetInstance()->font->loadCharacterWidths(); - //Minecraft::GetInstance()->altFont->loadCharacterWidths(); } void Textures::stitch() diff --git a/Minecraft.Client/Textures.h b/Minecraft.Client/Textures.h index 1fca5610..b30a507d 100644 --- a/Minecraft.Client/Textures.h +++ b/Minecraft.Client/Textures.h @@ -253,7 +253,7 @@ private: unordered_map httpTextures; // 4J-PB - Added for GTS textures - unordered_map memTextures; + std::unordered_map> memTextures; Options *options; private: diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index 75f03cc2..53ddc94b 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -523,12 +523,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) nullptr); if (!g_hWnd) - { return FALSE; - } - - ShowWindow(g_hWnd, (nCmdShow != SW_HIDE) ? SW_SHOWMAXIMIZED : nCmdShow); - UpdateWindow(g_hWnd); return TRUE; } @@ -1345,6 +1340,9 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, hr = XuiTimersRun(); } #endif + ShowWindow(g_hWnd, (nCmdShow != SW_HIDE) ? SW_SHOWMAXIMIZED : nCmdShow); + UpdateWindow(g_hWnd); + MSG msg = {0}; while( WM_QUIT != msg.message && !app.m_bShutdown) { diff --git a/Minecraft.World/Entity.cpp b/Minecraft.World/Entity.cpp index 6fc623e7..52b6c18f 100644 --- a/Minecraft.World/Entity.cpp +++ b/Minecraft.World/Entity.cpp @@ -730,24 +730,26 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J - bool isPlayerSneaking = onGround && isSneaking() && instanceof(eTYPE_PLAYER); + auto shared = shared_from_this(); + if (isPlayerSneaking) { double d = 0.05; - while (xa != 0 && level->getCubes(shared_from_this(), bb->cloneMove(xa, -1.0, 0))->empty()) + while (xa != 0 && level->getCubes(shared, bb->cloneMove(xa, -1.0, 0))->empty()) { if (xa < d && xa >= -d) xa = 0; else if (xa > 0) xa -= d; else xa += d; xaOrg = xa; } - while (za != 0 && level->getCubes(shared_from_this(), bb->cloneMove(0, -1.0, za))->empty()) + while (za != 0 && level->getCubes(shared, bb->cloneMove(0, -1.0, za))->empty()) { if (za < d && za >= -d) za = 0; else if (za > 0) za -= d; else za += d; zaOrg = za; } - while (xa != 0 && za != 0 && level->getCubes(shared_from_this(), bb->cloneMove(xa, -1.0, za))->empty()) + while (xa != 0 && za != 0 && level->getCubes(shared, bb->cloneMove(xa, -1.0, za))->empty()) { if (xa < d && xa >= -d) xa = 0; else if (xa > 0) xa -= d; @@ -760,8 +762,7 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J - } } - AABBList *aABBs = level->getCubes(shared_from_this(), bb->expand(xa, ya, za), noEntityCubes, true); - + AABBList *aABBs = level->getCubes(shared, bb->expand(xa, ya, za), noEntityCubes, true); // 4J Stu - Particles (and possibly other entities) don't have xChunk and zChunk set, so calculate the chunk instead int xc = Mth::floor(x / 16); @@ -815,7 +816,7 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J - bb->set(bbOrg); // 4J - added extra expand, as if we don't move up by footSize by hitting a block above us, then overall we could be trying to move as much as footSize downwards, // so we'd better include cubes under our feet in this list of things we might possibly collide with - aABBs = level->getCubes(shared_from_this(), bb->expand(xa, ya, za)->expand(0,-ya,0),false,true); + aABBs = level->getCubes(shared, bb->expand(xa, ya, za)->expand(0,-ya,0),false,true); if(!level->isClientSide || level->reallyHasChunk(xc, zc)) { @@ -925,7 +926,7 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J - playSound(eSoundType_LIQUID_SWIM, speed, 1 + (random->nextFloat() - random->nextFloat()) * 0.4f); } playStepSound(xt, yt, zt, t); - Tile::tiles[t]->stepOn(level, xt, yt, zt, shared_from_this()); + Tile::tiles[t]->stepOn(level, xt, yt, zt, shared); } } diff --git a/Minecraft.World/LivingEntity.cpp b/Minecraft.World/LivingEntity.cpp index 90ad2596..2d9183da 100644 --- a/Minecraft.World/LivingEntity.cpp +++ b/Minecraft.World/LivingEntity.cpp @@ -773,7 +773,7 @@ bool LivingEntity::hurt(DamageSource *source, float dmg) // 4J-JEV, for new achievement Stayin'Frosty, TODO merge with Java version. if ( this->instanceof(eTYPE_PLAYER) && (source == DamageSource::lava) ) // Only award when in lava (not any fire). { - shared_ptr plr = dynamic_pointer_cast(shared_from_this()); + shared_ptr plr = static_pointer_cast(shared_from_this()); plr->awardStat(GenericStats::stayinFrosty(),GenericStats::param_stayinFrosty()); } return false; @@ -781,7 +781,7 @@ bool LivingEntity::hurt(DamageSource *source, float dmg) if ((source == DamageSource::anvil || source == DamageSource::fallingBlock) && getCarried(SLOT_HELM) != nullptr) { - getCarried(SLOT_HELM)->hurtAndBreak(static_cast(dmg * 4 + random->nextFloat() * dmg * 2.0f), dynamic_pointer_cast( shared_from_this() )); + getCarried(SLOT_HELM)->hurtAndBreak(static_cast(dmg * 4 + random->nextFloat() * dmg * 2.0f), static_pointer_cast(shared_from_this())); dmg *= 0.75f; } @@ -811,17 +811,17 @@ bool LivingEntity::hurt(DamageSource *source, float dmg) { if ( sourceEntity->instanceof(eTYPE_LIVINGENTITY) ) { - setLastHurtByMob(dynamic_pointer_cast(sourceEntity)); + setLastHurtByMob(static_pointer_cast(sourceEntity)); } if ( sourceEntity->instanceof(eTYPE_PLAYER) ) { lastHurtByPlayerTime = PLAYER_HURT_EXPERIENCE_TIME; - lastHurtByPlayer = dynamic_pointer_cast(sourceEntity); + lastHurtByPlayer = static_pointer_cast(sourceEntity); } else if ( sourceEntity->instanceof(eTYPE_WOLF) ) { - shared_ptr w = dynamic_pointer_cast(sourceEntity); + shared_ptr w = static_pointer_cast(sourceEntity); if (w->isTame()) { lastHurtByPlayerTime = PLAYER_HURT_EXPERIENCE_TIME; @@ -1386,16 +1386,11 @@ void LivingEntity::jumpFromGround() void LivingEntity::travel(float xa, float ya) { -#ifdef __PSVITA__ // AP - dynamic_pointer_cast is a non-trivial call Player *thisPlayer = nullptr; if( this->instanceof(eTYPE_PLAYER) ) - { - thisPlayer = (Player*) this; - } -#else - shared_ptr thisPlayer = dynamic_pointer_cast(shared_from_this()); -#endif + thisPlayer = static_cast(this); + if (isInWater() && !(thisPlayer && thisPlayer->abilities.flying) ) { double yo = y; @@ -1408,9 +1403,7 @@ void LivingEntity::travel(float xa, float ya) yd -= 0.02; if (horizontalCollision && isFree(xd, yd + 0.6f - y + yo, zd)) - { yd = 0.3f; - } } else if (isInLava() && !(thisPlayer && thisPlayer->abilities.flying) ) { @@ -1423,9 +1416,7 @@ void LivingEntity::travel(float xa, float ya) yd -= 0.02; if (horizontalCollision && isFree(xd, yd + 0.6f - y + yo, zd)) - { yd = 0.3f; - } } else { @@ -1435,35 +1426,16 @@ void LivingEntity::travel(float xa, float ya) friction = 0.6f * 0.91f; int t = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, Mth::floor(z)); if (t > 0) - { friction = Tile::tiles[t]->friction * 0.91f; - } } - float friction2 = (0.6f * 0.6f * 0.91f * 0.91f * 0.6f * 0.91f) / (friction * friction * friction); + constexpr float MAGIC_FRICTION_CUBE = 0.6f * 0.6f * 0.91f * 0.91f * 0.6f * 0.91f; + float friction2 = MAGIC_FRICTION_CUBE / (friction * friction * friction); - float speed; - if (onGround) - { - speed = getSpeed() * friction2; - } - else - { - speed = flyingSpeed; - } + float speed = onGround ? (getSpeed() * friction2) : flyingSpeed; moveRelative(xa, ya, speed); - friction = 0.91f; - if (onGround) - { - friction = 0.6f * 0.91f; - int t = level->getTile( Mth::floor(x), Mth::floor(bb->y0) - 1, Mth::floor(z)); - if (t > 0) - { - friction = Tile::tiles[t]->friction * 0.91f; - } - } if (onLadder()) { float max = 0.15f; @@ -1473,29 +1445,21 @@ void LivingEntity::travel(float xa, float ya) if (zd > max) zd = max; fallDistance = 0; if (yd < -0.15) yd = -0.15; - bool playerSneaking = isSneaking() && this->instanceof(eTYPE_PLAYER); + bool playerSneaking = isSneaking() && (thisPlayer != nullptr); if (playerSneaking && yd < 0) yd = 0; } move(xd, yd, zd); if (horizontalCollision && onLadder()) - { yd = 0.2; - } if (!level->isClientSide || (level->hasChunkAt(static_cast(x), 0, static_cast(z)) && level->getChunkAt(static_cast(x), static_cast(z))->loaded)) - { yd -= 0.08; - } else if (y > 0) - { yd = -0.1; - } else - { yd = 0; - } yd *= 0.98f; xd *= friction; @@ -1505,8 +1469,11 @@ void LivingEntity::travel(float xa, float ya) walkAnimSpeedO = walkAnimSpeed; double xxd = x - xo; double zzd = z - zo; + float wst = Mth::sqrt(xxd * xxd + zzd * zzd) * 4; - if (wst > 1) wst = 1; + if (wst > 1) + wst = 1; + walkAnimSpeed += (wst - walkAnimSpeed) * 0.4f; walkAnimPos += walkAnimSpeed; } @@ -1515,41 +1482,54 @@ void LivingEntity::travel(float xa, float ya) // mobs too) simply gets a single tile's lighting value causing sudden changes of lighting values when entities go in and out of lit areas, for example when bobbing in the water. int LivingEntity::getLightColor(float a) { - float accum[2] = {0,0}; float totVol = ( bb->x1 - bb->x0 ) * ( bb->y1 - bb->y0 ) * ( bb->z1 - bb->z0 ); + if (totVol <= 0.0001f) return 0; + + float totVol2 = 1.0f / totVol; + int xmin = Mth::floor(bb->x0); int xmax = Mth::floor(bb->x1); int ymin = Mth::floor(bb->y0); int ymax = Mth::floor(bb->y1); int zmin = Mth::floor(bb->z0); int zmax = Mth::floor(bb->z1); + + float accum[2] = {0,0}; + for( int xt = xmin; xt <= xmax; xt++ ) + { + float tilexmin = max(static_cast(xt), bb->x0); + float tilexmax = min(static_cast(xt + 1), bb->x1); + float dx = tilexmax - tilexmin; for( int yt = ymin; yt <= ymax; yt++ ) + { + float tileymin = max(static_cast(yt), bb->y0); + float tileymax = min(static_cast(yt + 1), bb->y1); + float dy = tileymax - tileymin; + + float dxdyarea = dx * dy * totVol2; + if (dxdyarea <= 0.0f) + continue; + for( int zt = zmin; zt <= zmax; zt++ ) { - float tilexmin = static_cast(xt); - float tilexmax = static_cast(xt + 1); - float tileymin = static_cast(yt); - float tileymax = static_cast(yt + 1); - float tilezmin = static_cast(zt); - float tilezmax = static_cast(zt + 1); - if( tilexmin < bb->x0 ) tilexmin = bb->x0; - if( tilexmax > bb->x1 ) tilexmax = bb->x1; - if( tileymin < bb->y0 ) tileymin = bb->y0; - if( tileymax > bb->y1 ) tileymax = bb->y1; - if( tilezmin < bb->z0 ) tilezmin = bb->z0; - if( tilezmax > bb->z1 ) tilezmax = bb->z1; - float tileVol = ( tilexmax - tilexmin ) * ( tileymax - tileymin ) * ( tilezmax - tilezmin ); - float frac = tileVol / totVol; + float tilezmin = max(static_cast(zt), bb->z0); + float tilezmax = min(static_cast(zt + 1), bb->z1); + float dz = tilezmax - tilezmin; + + float frac = dxdyarea * dz; + int lc = level->getLightColor(xt, yt, zt, 0); accum[0] += frac * static_cast(lc & 0xffff); accum[1] += frac * static_cast(lc >> 16); } + } + } - if( accum[0] > 240.0f ) accum[0] = 240.0f; - if( accum[1] > 240.0f ) accum[1] = 240.0f; + accum[0] = min(accum[0], 240.0f); + accum[1] = min(accum[1], 240.0f); - return ( static_cast(accum[1])<<16) | static_cast(accum[0]); + return ( static_cast(accum[1])<<16) | static_cast(accum[0]); } bool LivingEntity::useNewAi() diff --git a/Minecraft.World/RecordPlayerTile.cpp b/Minecraft.World/RecordPlayerTile.cpp index 3abf81f6..59c3b5d4 100644 --- a/Minecraft.World/RecordPlayerTile.cpp +++ b/Minecraft.World/RecordPlayerTile.cpp @@ -56,13 +56,13 @@ void RecordPlayerTile::dropRecording(Level *level, int x, int y, int z) if( rte == nullptr ) return; int oldRecord = rte->record; - if (oldRecord == 0) return; + if (oldRecord == nullptr) return; level->levelEvent(LevelEvent::SOUND_PLAY_RECORDING, x, y, z, 0); // 4J-PB- the level event will play the music //level->playStreamingMusic(L"", x, y, z); - rte->record = 0; + rte->record = nullptr; rte->setChanged(); level->setData(x, y, z, 0); diff --git a/Minecraft.World/Zombie.cpp b/Minecraft.World/Zombie.cpp index e9568702..a367c6ea 100644 --- a/Minecraft.World/Zombie.cpp +++ b/Minecraft.World/Zombie.cpp @@ -153,6 +153,7 @@ bool Zombie::hurt(DamageSource *source, float dmg) { if (Monster::hurt(source, dmg)) { +/* shared_ptr target = getTarget(); if ( (target == nullptr) && getAttackTarget() != nullptr && getAttackTarget()->instanceof(eTYPE_LIVINGENTITY) ) target = dynamic_pointer_cast( getAttackTarget() ); if ( (target == nullptr) && source->getEntity() != nullptr && source->getEntity()->instanceof(eTYPE_LIVINGENTITY) ) target = dynamic_pointer_cast( source->getEntity() ); @@ -187,7 +188,7 @@ bool Zombie::hurt(DamageSource *source, float dmg) } } } - +*/ return true; }