Optimizations

This solves an FPS problem when 10 or more entities take damage
This commit is contained in:
GabsPuNs
2026-05-28 22:22:22 -04:00
parent 338604d7c5
commit 8dececbf90
11 changed files with 230 additions and 480 deletions

View File

@@ -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 <vector>
#include <memory>
#include <mutex>
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<Mob> *players, float a)
{
ConsoleSoundEngine::tick();
@@ -332,9 +315,7 @@ void SoundEngine::tick(shared_ptr<Mob> *players, float a)
listenerCount++;
}
else
{
m_ListenerA[i].bValid=false;
}
}
}
@@ -351,12 +332,7 @@ void SoundEngine::tick(shared_ptr<Mob> *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<std::string>* 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<std::string> 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_iStream_CD_1))
{
// rebuild the path for the music
strcat_s((char *)m_szStreamName,m_szStreamFileA[m_musicID]);
strcat_s((char *)m_szStreamName,".wav");
// check if this is in the patch data
sprintf(m_szStreamName,"%s/%s",app.GetBDUsrDirPath(m_szStreamName), m_szMusicPath );
strcat((char *)m_szStreamName,m_szStreamFileA[m_musicID]);
strcat((char *)m_szStreamName,".wav");
SetIsPlayingStreamingGameMusic(true);
SetIsPlayingStreamingCDMusic(false);
m_StreamingAudioInfo.bIs3D=false;
}
else if(m_musicID<m_iStream_CD_1)
{
SetIsPlayingStreamingGameMusic(true);
SetIsPlayingStreamingCDMusic(false);
m_StreamingAudioInfo.bIs3D=false;
// build the name
strcat_s((char *)m_szStreamName,m_szStreamFileA[m_musicID]);
strcat_s((char *)m_szStreamName,".wav");
}
else
{
SetIsPlayingStreamingGameMusic(false);
SetIsPlayingStreamingCDMusic(true);
m_StreamingAudioInfo.bIs3D=true;
// build the name
strcat_s((char *)m_szStreamName, "CDs/");
strcat_s((char *)m_szStreamName,m_szStreamFileA[m_musicID]);
strcat_s((char *)m_szStreamName,".wav");
}
#else
// 4J-PB - if this is a PS3 disc patch, we have to check if the music file is in the patch data
if(m_musicID<m_iStream_CD_1)
{
SetIsPlayingStreamingGameMusic(true);
@@ -1121,8 +1007,6 @@ void SoundEngine::playMusicUpdate()
}
strcat_s((char *)m_szStreamName, _countof(m_szStreamName), m_szStreamFileA[m_musicID]);
strcat_s((char *)m_szStreamName, _countof(m_szStreamName), ".wav");
#endif
}
// wstring name = m_szStreamFileA[m_musicID];
@@ -1132,9 +1016,7 @@ void SoundEngine::playMusicUpdate()
FILE* pFile = nullptr;
if (fopen_s(&pFile, reinterpret_cast<char*>(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;

View File

@@ -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<MiniAudioSound*> 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<int, std::vector<std::string>> m_sfxPathCache;
std::unordered_map<int, std::string> m_uiPathCache;
};

View File

@@ -247,8 +247,8 @@ void EntityRenderer::renderFlame(shared_ptr<Entity> e, double x, double y, doubl
t->end();
glPopMatrix();
glEnable(GL_LIGHTING);
}
void EntityRenderer::renderShadow(shared_ptr<Entity> e, double x, double y, double z, float pow, float a)
{
glDisable(GL_LIGHTING);

View File

@@ -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()

View File

@@ -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<MemTextureProcessor> 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<MemTexture>(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()

View File

@@ -253,7 +253,7 @@ private:
unordered_map<wstring, HttpTexture *> httpTextures;
// 4J-PB - Added for GTS textures
unordered_map<wstring,MemTexture *> memTextures;
std::unordered_map<wstring, std::unique_ptr<MemTexture>> memTextures;
Options *options;
private:

View File

@@ -524,12 +524,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;
}
@@ -1346,6 +1341,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)
{

View File

@@ -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);
}
}

View File

@@ -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<Player> plr = dynamic_pointer_cast<Player>(shared_from_this());
shared_ptr<Player> plr = static_pointer_cast<Player>(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<int>(dmg * 4 + random->nextFloat() * dmg * 2.0f), dynamic_pointer_cast<LivingEntity>( shared_from_this() ));
getCarried(SLOT_HELM)->hurtAndBreak(static_cast<int>(dmg * 4 + random->nextFloat() * dmg * 2.0f), static_pointer_cast<LivingEntity>(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<LivingEntity>(sourceEntity));
setLastHurtByMob(static_pointer_cast<LivingEntity>(sourceEntity));
}
if ( sourceEntity->instanceof(eTYPE_PLAYER) )
{
lastHurtByPlayerTime = PLAYER_HURT_EXPERIENCE_TIME;
lastHurtByPlayer = dynamic_pointer_cast<Player>(sourceEntity);
lastHurtByPlayer = static_pointer_cast<Player>(sourceEntity);
}
else if ( sourceEntity->instanceof(eTYPE_WOLF) )
{
shared_ptr<Wolf> w = dynamic_pointer_cast<Wolf>(sourceEntity);
shared_ptr<Wolf> w = static_pointer_cast<Wolf>(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<Player> thisPlayer = dynamic_pointer_cast<Player>(shared_from_this());
#endif
thisPlayer = static_cast<Player*>(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<int>(x), 0, static_cast<int>(z)) && level->getChunkAt(static_cast<int>(x), static_cast<int>(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<float>(xt), bb->x0);
float tilexmax = min(static_cast<float>(xt + 1), bb->x1);
float dx = tilexmax - tilexmin;
for( int yt = ymin; yt <= ymax; yt++ )
{
float tileymin = max(static_cast<float>(yt), bb->y0);
float tileymax = min(static_cast<float>(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<float>(xt);
float tilexmax = static_cast<float>(xt + 1);
float tileymin = static_cast<float>(yt);
float tileymax = static_cast<float>(yt + 1);
float tilezmin = static_cast<float>(zt);
float tilezmax = static_cast<float>(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<float>(zt), bb->z0);
float tilezmax = min(static_cast<float>(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<float>(lc & 0xffff);
accum[1] += frac * static_cast<float>(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<int>(accum[1])<<16) | static_cast<int>(accum[0]);
return ( static_cast<int>(accum[1])<<16) | static_cast<int>(accum[0]);
}
bool LivingEntity::useNewAi()

View File

@@ -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);

View File

@@ -153,6 +153,7 @@ bool Zombie::hurt(DamageSource *source, float dmg)
{
if (Monster::hurt(source, dmg))
{
/*
shared_ptr<LivingEntity> target = getTarget();
if ( (target == nullptr) && getAttackTarget() != nullptr && getAttackTarget()->instanceof(eTYPE_LIVINGENTITY) ) target = dynamic_pointer_cast<LivingEntity>( getAttackTarget() );
if ( (target == nullptr) && source->getEntity() != nullptr && source->getEntity()->instanceof(eTYPE_LIVINGENTITY) ) target = dynamic_pointer_cast<LivingEntity>( source->getEntity() );
@@ -187,7 +188,7 @@ bool Zombie::hurt(DamageSource *source, float dmg)
}
}
}
*/
return true;
}