diff --git a/Minecraft.Client/Common/DLC/DLCPack.cpp b/Minecraft.Client/Common/DLC/DLCPack.cpp index 5f3874d0..e3dfcd00 100644 --- a/Minecraft.Client/Common/DLC/DLCPack.cpp +++ b/Minecraft.Client/Common/DLC/DLCPack.cpp @@ -416,15 +416,28 @@ bool DLCPack::hasPurchasedFile(DLCManager::EDLCType type, const wstring &path) void DLCPack::UpdateLanguage() { // find the language file - DLCManager::e_DLCType_LocalisationData; - DLCFile *file = nullptr; - - if(m_files[DLCManager::e_DLCType_LocalisationData].size() > 0) + if (m_files[DLCManager::e_DLCType_LocalisationData].empty()) { - file = m_files[DLCManager::e_DLCType_LocalisationData][0]; - DLCLocalisationFile *localisationFile = static_cast(getFile(DLCManager::e_DLCType_LocalisationData, L"languages.loc")); - StringTable *strTable = localisationFile->getStringTable(); - strTable->ReloadStringTable(); + return; } -} \ No newline at end of file + DLCFile *file = getFile(DLCManager::e_DLCType_LocalisationData, L"languages.loc"); + if (!file) + { + file = m_files[DLCManager::e_DLCType_LocalisationData][0]; + } + + DLCLocalisationFile *localisationFile = static_cast(file); + if (!localisationFile) + { + return; + } + + StringTable *strTable = localisationFile->getStringTable(); + if (!strTable) + { + return; + } + + strTable->ReloadStringTable(); +} diff --git a/Minecraft.Client/Common/GameRules/LevelGenerationOptions.h b/Minecraft.Client/Common/GameRules/LevelGenerationOptions.h index dee60c82..26f7b23b 100644 --- a/Minecraft.Client/Common/GameRules/LevelGenerationOptions.h +++ b/Minecraft.Client/Common/GameRules/LevelGenerationOptions.h @@ -13,6 +13,7 @@ class ConsoleSchematicFile; class LevelRuleset; class BiomeOverride; class StartFeature; +class DLCPack; class GrSource { @@ -135,6 +136,7 @@ public: void setBaseSavePath(const wstring &x); bool ready(); + DLCPack *getParentDLCPack() { return m_parentDLCPack; } void setBaseSaveData(PBYTE pbData, DWORD dwSize); PBYTE getBaseSaveData(DWORD &size); diff --git a/Minecraft.Client/Common/Media/MediaWindows64/Graphics/ControlType/Panorama/Panorama_N.png b/Minecraft.Client/Common/Media/MediaWindows64/Graphics/ControlType/Panorama/Panorama_N.png new file mode 100644 index 00000000..f394b273 Binary files /dev/null and b/Minecraft.Client/Common/Media/MediaWindows64/Graphics/ControlType/Panorama/Panorama_N.png differ diff --git a/Minecraft.Client/Common/Media/MediaWindows64/Graphics/ControlType/Panorama/Panorama_S.png b/Minecraft.Client/Common/Media/MediaWindows64/Graphics/ControlType/Panorama/Panorama_S.png new file mode 100644 index 00000000..f8c77def Binary files /dev/null and b/Minecraft.Client/Common/Media/MediaWindows64/Graphics/ControlType/Panorama/Panorama_S.png differ diff --git a/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp b/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp index 606b1499..60997d41 100644 --- a/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp +++ b/Minecraft.Client/Common/UI/UIComponent_Panorama.cpp @@ -5,45 +5,237 @@ #include "MultiPlayerLevel.h" #include "../../../Minecraft.World/net.minecraft.world.level.dimension.h" #include "../../../Minecraft.World/net.minecraft.world.level.storage.h" +#include "Tesselator.h" +#include "Textures.h" +#include "BufferedImage.h" +#include "../GameRules/LevelGenerationOptions.h" +#include +#include +#include + +static const wchar_t *PANORAMA_TEXTURE_RELPATH = L"Graphics/ControlType/Panorama/"; + +static wstring GetPanoramaTexturePath() +{ + const wchar_t *envOverride = _wgetenv(L"PANORAMA_TEXTURE_PATH"); + if(envOverride && envOverride[0] != L'\0') + { + wstring path(envOverride); + if(!path.empty() && path.back() != L'/' && path.back() != L'\\') + path += L'/'; + return path; + } + + if(app.getLevelGenerationOptions() != nullptr) + { + LevelGenerationOptions *levelGen = app.getLevelGenerationOptions(); + DLCPack *parentPack = levelGen->getParentDLCPack(); + if(parentPack != nullptr) + { + wstring packName = parentPack->getName(); + if(!packName.empty()) + { + wchar_t buf[MAX_PATH]; + if(_wgetcwd(buf, MAX_PATH)) + { + wstring path(buf); + path += L"\\Windows64Media\\DLC\\"; + path += packName; + path += L"\\Data\\Panorama\\"; + wstring sampleDay = path + L"Panorama_S.png"; + wstring sampleNight = path + L"Panorama_N.png"; + if(GetFileAttributesW(sampleDay.c_str()) != INVALID_FILE_ATTRIBUTES || + GetFileAttributesW(sampleNight.c_str()) != INVALID_FILE_ATTRIBUTES) + { + return path; + } + } + } + } + } + + const char *mountedPanoramaRoots[] = + { + "TPACK:Data/Panorama/", + "WPACK:Data/Panorama/", + }; + + for(const char *mountedRoot : mountedPanoramaRoots) + { + wstring mountedPath = convStringToWstring(StorageManager.GetMountedPath(mountedRoot)); + if(mountedPath.empty()) continue; + + wstring sampleDay = mountedPath + L"Panorama_S.png"; + wstring sampleNight = mountedPath + L"Panorama_N.png"; + if(GetFileAttributesW(sampleDay.c_str()) != INVALID_FILE_ATTRIBUTES || + GetFileAttributesW(sampleNight.c_str()) != INVALID_FILE_ATTRIBUTES) + { + if(!mountedPath.empty() && mountedPath.back() != L'/' && mountedPath.back() != L'\\') + mountedPath += L'/'; + return mountedPath; + } + } + + wchar_t buf[MAX_PATH]; + if(_wgetcwd(buf, MAX_PATH)) + { + wstring path(buf); + path += L"\\Common\\Media\\MediaWindows64\\Graphics\\ControlType\\Panorama\\"; + return path; + } + + // fallback + return PANORAMA_TEXTURE_RELPATH; +} + +// opengl time :v +static int LoadPanoramaQuadTexture(const wstring &fileName, int &outWidth, int &outHeight) +{ + wstring filePath = GetPanoramaTexturePath() + fileName; + const char *nativePath = wstringtofilename(filePath); + std::ifstream stream(nativePath, std::ios::binary); + if(!stream) + { + printf("Failed to open panorama quad texture %ls\n", filePath.c_str()); + return -1; + } + + stream.seekg(0, std::ios::end); + std::streamoff size = stream.tellg(); + if(size <= 0) + { + printf("Empty panorama quad texture %ls\n", filePath.c_str()); + return -1; + } + stream.seekg(0, std::ios::beg); + + BYTE *data = new BYTE[static_cast(size)]; + if(!stream.read(reinterpret_cast(data), size)) + { + delete [] data; + printf("Failed to read panorama quad texture %ls\n", filePath.c_str()); + return -1; + } + + BufferedImage image(data, static_cast(size)); + delete [] data; + + if(image.getData() == nullptr) + { + printf("Failed to decode panorama quad texture %ls\n", filePath.c_str()); + return -1; + } + + // gaussian blur + const float sigma = 0.5f; + const int width = image.getWidth(); + const int height = image.getHeight(); + + const int radius = static_cast(ceilf(3.0f * sigma)); + const int ksize = radius * 2 + 1; + vector kernel(ksize); + float sum = 0.0f; + for(int i = -radius; i <= radius; ++i) + { + float v = expf(-(i*i) / (2.0f * sigma * sigma)); + kernel[i + radius] = v; + sum += v; + } + for(int i = 0; i < ksize; ++i) kernel[i] /= sum; + + float *tmpA = new float[width * height]; + float *tmpR = new float[width * height]; + float *tmpG = new float[width * height]; + float *tmpB = new float[width * height]; + + int *sourcePixels = image.getData(); + + for(int y = 0; y < height; ++y) + { + for(int x = 0; x < width; ++x) + { + float a = 0, r = 0, g = 0, b = 0; + for(int k = -radius; k <= radius; ++k) + { + // horizontal wrap + int sx = x + k; + while(sx < 0) sx += width; + while(sx >= width) sx -= width; + int p = sourcePixels[sx + y * width]; + float w = kernel[k + radius]; + a += w * static_cast((p >> 24) & 0xff); + r += w * static_cast((p >> 16) & 0xff); + g += w * static_cast((p >> 8) & 0xff); + b += w * static_cast(p & 0xff); + } + int idx = x + y * width; + tmpA[idx] = a; + tmpR[idx] = r; + tmpG[idx] = g; + tmpB[idx] = b; + } + } + + // vertical clamp + BufferedImage blurredImage(width, height, BufferedImage::TYPE_INT_ARGB); + int *targetPixels = blurredImage.getData(); + for(int y = 0; y < height; ++y) + { + for(int x = 0; x < width; ++x) + { + float a = 0, r = 0, g = 0, b = 0; + for(int k = -radius; k <= radius; ++k) + { + int sy = y + k; + if(sy < 0) sy = 0; + if(sy >= height) sy = height - 1; + int idx = x + sy * width; + float w = kernel[k + radius]; + a += w * tmpA[idx]; + r += w * tmpR[idx]; + g += w * tmpG[idx]; + b += w * tmpB[idx]; + } + int ia = static_cast(a + 0.5f); + int ir = static_cast(r + 0.5f); + int ig = static_cast(g + 0.5f); + int ib = static_cast(b + 0.5f); + if(ia < 0) ia = 0; if(ia > 255) ia = 255; + if(ir < 0) ir = 0; if(ir > 255) ir = 255; + if(ig < 0) ig = 0; if(ig > 255) ig = 255; + if(ib < 0) ib = 0; if(ib > 255) ib = 255; + targetPixels[x + y * width] = (ia << 24) | (ir << 16) | (ig << 8) | ib; + } + } + + delete [] tmpA; + delete [] tmpR; + delete [] tmpG; + delete [] tmpB; + + outWidth = image.getWidth(); + outHeight = image.getHeight(); + + int id = Minecraft::GetInstance()->textures->getTexture(&blurredImage, C4JRender::TEXTURE_FORMAT_RxGyBzAw, false); + printf("Loaded panorama background quad '%ls' -> texture id %d\n", filePath.c_str(), id); + return id; +} UIComponent_Panorama::UIComponent_Panorama(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) { - // Setup all the Iggy references we need for this scene - initialiseMovie(); - m_bShowingDay = true; - - while(!m_hasTickedOnce) tick(); + tick(); } wstring UIComponent_Panorama::getMoviePath() { - switch( m_parentLayer->getViewport() ) - { - case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: - case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: - case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: - case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: - case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: - case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: - case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: - case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: - m_bSplitscreen = true; - return L"PanoramaSplit"; - break; - case C4JRender::VIEWPORT_TYPE_FULLSCREEN: - default: - m_bSplitscreen = false; - return L"Panorama"; - break; - } + return L""; } void UIComponent_Panorama::tick() { - if(!hasMovie()) return; - Minecraft *pMinecraft = Minecraft::GetInstance(); + bool isDay = true; EnterCriticalSection(&pMinecraft->m_setLevelCS); if(pMinecraft->level!=nullptr) { @@ -52,24 +244,111 @@ void UIComponent_Panorama::tick() if(pMinecraft->level->dimension->id==0) { i64TimeOfDay = pMinecraft->level->getLevelData()->getGameTime() % 24000; + isDay = (i64TimeOfDay <= 14000); } - if(i64TimeOfDay>14000) - { - setPanorama(false); - } - else - { - setPanorama(true); - } + setPanorama(isDay); } else { setPanorama(true); } + + // scroll forever + m_panoramaScroll += 0.000035f; LeaveCriticalSection(&pMinecraft->m_setLevelCS); - UIScene::tick(); + m_hasTickedOnce = true; +} + +void UIComponent_Panorama::EnsurePanoramaTexturesLoaded() +{ + wstring currentRoot = GetPanoramaTexturePath(); + if(m_bPanoramaTexturesLoaded && currentRoot == m_panoramaTextureRoot) return; + + if(m_texPanoramaDay >= 0) + { + Minecraft::GetInstance()->textures->releaseTexture(m_texPanoramaDay); + m_texPanoramaDay = -1; + } + if(m_texPanoramaNight >= 0) + { + Minecraft::GetInstance()->textures->releaseTexture(m_texPanoramaNight); + m_texPanoramaNight = -1; + } + + m_panoramaTextureRoot = currentRoot; + m_bPanoramaTexturesLoaded = false; + int dayWidth = 0; + int dayHeight = 0; + m_texPanoramaDay = LoadPanoramaQuadTexture(L"Panorama_S.png", dayWidth, dayHeight); + int nightWidth = 0; + int nightHeight = 0; + m_texPanoramaNight = LoadPanoramaQuadTexture(L"Panorama_N.png", nightWidth, nightHeight); + if(dayWidth > 0 && dayHeight > 0) + { + m_panoramaAspect = static_cast(dayWidth) / static_cast(dayHeight); + } + else if(nightWidth > 0 && nightHeight > 0) + { + m_panoramaAspect = static_cast(nightWidth) / static_cast(nightHeight); + } + m_bPanoramaTexturesLoaded = (m_texPanoramaDay >= 0 || m_texPanoramaNight >= 0); +} + +void UIComponent_Panorama::DrawPanoramaBackgroundQuad(S32 width, S32 height) +{ + EnsurePanoramaTexturesLoaded(); + + int texId = m_bShowingDay ? m_texPanoramaDay : m_texPanoramaNight; + if(texId < 0) return; // failed + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, width, height, 0, -1, 1); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glEnable(GL_TEXTURE_2D); + + Minecraft::GetInstance()->textures->bind(texId); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + float sourceWidth = static_cast(height) * m_panoramaAspect; + float scroll = m_panoramaScroll - floorf(m_panoramaScroll); + float scrollPx = scroll * sourceWidth; + float startX = -scrollPx; + float startY = 0.0f; + const float overscanY = (static_cast(height) * 0.03f > 8.0f) ? (static_cast(height) * 0.03f) : 8.0f; + const float drawTop = -overscanY; + const float drawBottom = static_cast(height) + overscanY; + + Tesselator *t = Tesselator::getInstance(); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + t->begin(); + for(float x = startX - sourceWidth; x < static_cast(width) + sourceWidth; x += sourceWidth) + { + float left = x; + float right = x + sourceWidth; + t->vertexUV(left, drawBottom, 0.0f, 0.0f, 1.0f); + t->vertexUV(right, drawBottom, 0.0f, 1.0f, 1.0f); + t->vertexUV(right, drawTop, 0.0f, 1.0f, 0.0f); + t->vertexUV(left, drawTop, 0.0f, 0.0f, 0.0f); + } + t->end(); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glDisable(GL_BLEND); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } void UIComponent_Panorama::render(S32 width, S32 height, C4JRender::eViewportType viewport) @@ -78,7 +357,7 @@ void UIComponent_Panorama::render(S32 width, S32 height, C4JRender::eViewportTyp (viewport == C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM) || (viewport == C4JRender::VIEWPORT_TYPE_SPLIT_LEFT) || (viewport == C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT); - if(m_bSplitscreen && specialViewport) + if(specialViewport) { S32 xPos = 0; S32 yPos = 0; @@ -108,32 +387,17 @@ void UIComponent_Panorama::render(S32 width, S32 height, C4JRender::eViewportTyp tileYStart = static_cast(ui.getScreenHeight() / 2); } - F32 scaleW = static_cast(tileXStart + tileWidth) / static_cast(m_movieWidth); - F32 scaleH = static_cast(tileYStart + tileHeight) / static_cast(m_movieHeight); - F32 scale = (scaleW > scaleH) ? scaleW : scaleH; - if(scale < 1.0f) scale = 1.0f; - - IggyPlayerSetDisplaySize( getMovie(), static_cast(m_movieWidth * scale), static_cast(m_movieHeight * scale) ); - - IggyPlayerDrawTilesStart ( getMovie() ); - m_renderWidth = tileWidth; m_renderHeight = tileHeight; - IggyPlayerDrawTile ( getMovie() , - tileXStart , - tileYStart , - tileXStart + tileWidth , - tileYStart + tileHeight , - 0 ); - IggyPlayerDrawTilesEnd ( getMovie() ); + + DrawPanoramaBackgroundQuad(tileWidth, tileHeight); } else { - if(m_bIsReloading) return; - if(!m_hasTickedOnce || !getMovie()) return; ui.setupRenderPosition(0, 0); - IggyPlayerSetDisplaySize( getMovie(), static_cast(ui.getScreenWidth()), static_cast(ui.getScreenHeight()) ); - IggyPlayerDraw( getMovie() ); + m_renderWidth = static_cast(ui.getScreenWidth()); + m_renderHeight = static_cast(ui.getScreenHeight()); + DrawPanoramaBackgroundQuad(static_cast(ui.getScreenWidth()), static_cast(ui.getScreenHeight())); } } @@ -142,12 +406,5 @@ void UIComponent_Panorama::setPanorama(bool isDay) if(isDay != m_bShowingDay) { m_bShowingDay = isDay; - - IggyDataValue result; - IggyDataValue value[1]; - value[0].type = IGGY_DATATYPE_boolean; - value[0].boolval = isDay; - - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcShowPanoramaDay , 1 , value ); } -} +} \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIComponent_Panorama.h b/Minecraft.Client/Common/UI/UIComponent_Panorama.h index 99dc115c..eafedbaa 100644 --- a/Minecraft.Client/Common/UI/UIComponent_Panorama.h +++ b/Minecraft.Client/Common/UI/UIComponent_Panorama.h @@ -5,14 +5,15 @@ class UIComponent_Panorama : public UIScene { private: - bool m_bSplitscreen; bool m_bShowingDay; - -protected: - IggyName m_funcShowPanoramaDay; - UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) - UI_MAP_NAME(m_funcShowPanoramaDay, L"ShowPanoramaDay"); - UI_END_MAP_ELEMENTS_AND_NAMES() + void EnsurePanoramaTexturesLoaded(); + void DrawPanoramaBackgroundQuad(S32 width, S32 height); + int m_texPanoramaDay = -1; + int m_texPanoramaNight = -1; + bool m_bPanoramaTexturesLoaded = false; + wstring m_panoramaTextureRoot; + float m_panoramaAspect = 1.0f; + float m_panoramaScroll = 0.0f; public: UIComponent_Panorama(int iPad, void *initData, UILayer *parentLayer); @@ -23,6 +24,8 @@ protected: public: virtual EUIScene getSceneType() { return eUIComponent_Panorama;} + virtual bool isPanoramaOverrideScene() { return true; } + virtual bool isPanoramaDayOverride() { return m_bShowingDay; } // Returns true if this scene handles input virtual bool stealsFocus() { return false; } diff --git a/Minecraft.Client/Common/UI/UIScene.cpp b/Minecraft.Client/Common/UI/UIScene.cpp index 0d92176a..2b94ab02 100644 --- a/Minecraft.Client/Common/UI/UIScene.cpp +++ b/Minecraft.Client/Common/UI/UIScene.cpp @@ -123,7 +123,10 @@ void UIScene::reloadMovie(bool force) value[0].type = IGGY_DATATYPE_number; value[0].number = m_iFocusControl; - IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); + if(swf && m_funcSetFocus) + { + IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetFocus , 1 , value ); + } m_needsCacheRendered = true; m_bIsReloading = false; @@ -238,6 +241,8 @@ void UIScene::updateSafeZone() void UIScene::setSafeZone(S32 safeTop, S32 safeBottom, S32 safeLeft, S32 safeRight) { + if(!swf) return; + IggyDataValue result; IggyDataValue value[4]; @@ -254,8 +259,12 @@ void UIScene::setSafeZone(S32 safeTop, S32 safeBottom, S32 safeLeft, S32 safeRig void UIScene::initialiseMovie() { - loadMovie(); - mapElementsAndNames(); + wstring moviePath = getMoviePath(); + if(!moviePath.empty()) + { + loadMovie(); + mapElementsAndNames(); + } updateSafeZone(); diff --git a/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.cpp index b38fa9ce..fd54b3b6 100644 --- a/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.cpp @@ -765,7 +765,7 @@ UIScene_LoadCreateJoinMenu::UIScene_LoadCreateJoinMenu(int iPad, void *initData, m_controlSavesTimer.setVisible( true ); - m_controlNewGameTimer.setVisible( true ); + m_controlNewGameTimer.setVisible( false ); m_controlJoinTimer.setVisible( false ); @@ -2256,23 +2256,7 @@ void UIScene_LoadCreateJoinMenu::tick() - HANDLE hFile = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr); - - DWORD fileSize = 0; - - - - if (hFile != INVALID_HANDLE_VALUE) { - - fileSize = GetFileSize(hFile, nullptr); - - if (fileSize < 12 || fileSize == INVALID_FILE_SIZE) fileSize = 0; - - CloseHandle(hFile); - - } - - m_spaceIndicatorSaves.addSave(fileSize); + m_spaceIndicatorSaves.addSave(m_pSaveDetails->SaveInfoA[origIdx].metaData.dataSize); #elif defined(__ORBIS__) @@ -3143,11 +3127,12 @@ void UIScene_LoadCreateJoinMenu::handleInput(int iPad, int key, bool repeat, boo if(StorageManager.EnoughSpaceForAMinSaveGame() && !StorageManager.GetSaveDisabled()) { - UINT uiIDA[3]; + UINT uiIDA[4]; uiIDA[0]=IDS_CONFIRM_CANCEL; uiIDA[1]=IDS_TITLE_RENAMESAVE; uiIDA[2]=IDS_TOOLTIPS_DELETESAVE; - ui.RequestAlertMessage(IDS_TOOLTIPS_SAVEOPTIONS, IDS_TEXT_SAVEOPTIONS, uiIDA, 3, iPad,&UIScene_LoadCreateJoinMenu::SaveOptionsDialogReturned,this); + uiIDA[3]=IDS_COPYSAVE; + ui.RequestAlertMessage(IDS_TOOLTIPS_SAVEOPTIONS, IDS_TEXT_SAVEOPTIONS, uiIDA, 4, iPad,&UIScene_LoadCreateJoinMenu::SaveOptionsDialogReturned,this); } else { @@ -5825,30 +5810,6 @@ int UIScene_LoadCreateJoinMenu::SaveOptionsDialogReturned(void *pParam,int iPad, -#ifdef SONY_REMOTE_STORAGE_UPLOAD - - case C4JStorage::EMessage_ResultFourthOption: // upload to cloud - - { - - UINT uiIDA[2]; - - uiIDA[0]=IDS_CONFIRM_OK; - - uiIDA[1]=IDS_CONFIRM_CANCEL; - - - - ui.RequestAlertMessage(IDS_TOOLTIPS_SAVETRANSFER_UPLOAD, IDS_SAVE_TRANSFER_TEXT, uiIDA, 2, iPad,&UIScene_LoadCreateJoinMenu::SaveTransferDialogReturned,pClass); - - } - - break; - -#endif // SONY_REMOTE_STORAGE_UPLOAD - -#if defined _XBOX_ONE || defined __ORBIS__ - case C4JStorage::EMessage_ResultFourthOption: // copy save { @@ -5867,7 +5828,6 @@ int UIScene_LoadCreateJoinMenu::SaveOptionsDialogReturned(void *pParam,int iPad, break; -#endif @@ -8691,7 +8651,7 @@ void UIScene_LoadCreateJoinMenu::HandleDLCLicenseChange() -#if defined _XBOX_ONE || defined __ORBIS__ +#if defined _XBOX_ONE || defined __ORBIS__ || defined(_WINDOWS64) int UIScene_LoadCreateJoinMenu::CopySaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result) @@ -8875,54 +8835,10 @@ int UIScene_LoadCreateJoinMenu::CopySaveDataReturned(LPVOID lpParam, bool succes { -#ifdef __ORBIS__ - - UINT uiIDA[1]; - - // you cancelled the save on exit after choosing exit and save? You go back to the Exit choices then. - - uiIDA[0]=IDS_OK; - - - - if( stat == C4JStorage::ESaveGame_CopyCompleteFailLocalStorage ) - - { - - ui.LeaveCallbackIdCriticalSection(); - - ui.RequestErrorMessage(IDS_COPYSAVE_FAILED_TITLE, IDS_COPYSAVE_FAILED_LOCAL, uiIDA, 1, ProfileManager.GetPrimaryPad(), CopySaveErrorDialogFinishedCallback, lpParam); - - } - - else if( stat == C4JStorage::ESaveGame_CopyCompleteFailQuota ) - - { - - ui.LeaveCallbackIdCriticalSection(); - - ui.RequestErrorMessage(IDS_COPYSAVE_FAILED_TITLE, IDS_COPYSAVE_FAILED_QUOTA, uiIDA, 1, ProfileManager.GetPrimaryPad(), CopySaveErrorDialogFinishedCallback, lpParam); - - } - - else - - { - - pClass->m_bCopying = false; - - ui.LeaveCallbackIdCriticalSection(); - - } - -#else - pClass->m_bCopying = false; ui.LeaveCallbackIdCriticalSection(); -#endif - } } diff --git a/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.h b/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.h index dd12816e..28ca3e4c 100644 --- a/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_LoadCreateJoinMenu.h @@ -396,7 +396,7 @@ private: static int CrossSaveUploadFinishedCallback(void *pParam,int iPad,C4JStorage::EMessageResult result); #endif -#if defined _XBOX_ONE || defined __ORBIS__ +#if defined _XBOX_ONE || defined __ORBIS__ || defined(_WINDOWS64) static int CopySaveDialogReturned(void *pParam,int iPad,C4JStorage::EMessageResult result); static int CopySaveThreadProc( LPVOID lpParameter ); static int CopySaveDataReturned( LPVOID lpParameter, bool success, C4JStorage::ESaveGameState state ); diff --git a/Minecraft.Client/Windows64/4JLibs b/Minecraft.Client/Windows64/4JLibs index 9b25ddf5..8ad0c385 160000 --- a/Minecraft.Client/Windows64/4JLibs +++ b/Minecraft.Client/Windows64/4JLibs @@ -1 +1 @@ -Subproject commit 9b25ddf5758dffbcdda2f996d3cd310aa5b3c0e9 +Subproject commit 8ad0c385ded218c3d02d9b6dcf86b657933a883b diff --git a/Minecraft.Client/Windows64Media/DLC/Festive/Data/Panorama/Panorama_N.png b/Minecraft.Client/Windows64Media/DLC/Festive/Data/Panorama/Panorama_N.png new file mode 100644 index 00000000..194a1f8a Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Festive/Data/Panorama/Panorama_N.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Festive/Data/Panorama/Panorama_S.png b/Minecraft.Client/Windows64Media/DLC/Festive/Data/Panorama/Panorama_S.png new file mode 100644 index 00000000..8a5d0d9e Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Festive/Data/Panorama/Panorama_S.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Greek Mythology/Data/Panorama/Panorama_N.png b/Minecraft.Client/Windows64Media/DLC/Greek Mythology/Data/Panorama/Panorama_N.png new file mode 100644 index 00000000..9c450c52 Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Greek Mythology/Data/Panorama/Panorama_N.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Greek Mythology/Data/Panorama/Panorama_S.png b/Minecraft.Client/Windows64Media/DLC/Greek Mythology/Data/Panorama/Panorama_S.png new file mode 100644 index 00000000..2e298b51 Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Greek Mythology/Data/Panorama/Panorama_S.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Halloween 2015/Data/Panorama/Panorama_N.png b/Minecraft.Client/Windows64Media/DLC/Halloween 2015/Data/Panorama/Panorama_N.png new file mode 100644 index 00000000..54d43af8 Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Halloween 2015/Data/Panorama/Panorama_N.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Halloween 2015/Data/Panorama/Panorama_S.png b/Minecraft.Client/Windows64Media/DLC/Halloween 2015/Data/Panorama/Panorama_S.png new file mode 100644 index 00000000..d03ebcf7 Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Halloween 2015/Data/Panorama/Panorama_S.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Halo/Data/Panorama/Panorama_N.png b/Minecraft.Client/Windows64Media/DLC/Halo/Data/Panorama/Panorama_N.png new file mode 100644 index 00000000..8dafe8ee Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Halo/Data/Panorama/Panorama_N.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Halo/Data/Panorama/Panorama_S.png b/Minecraft.Client/Windows64Media/DLC/Halo/Data/Panorama/Panorama_S.png new file mode 100644 index 00000000..8388ead9 Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Halo/Data/Panorama/Panorama_S.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Mass Effect/Data/Panorama/Panorama_N.png b/Minecraft.Client/Windows64Media/DLC/Mass Effect/Data/Panorama/Panorama_N.png new file mode 100644 index 00000000..b86ee4e5 Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Mass Effect/Data/Panorama/Panorama_N.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Mass Effect/Data/Panorama/Panorama_S.png b/Minecraft.Client/Windows64Media/DLC/Mass Effect/Data/Panorama/Panorama_S.png new file mode 100644 index 00000000..8ca2931c Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Mass Effect/Data/Panorama/Panorama_S.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Skyrim/Data/Panorama/Panorama_N.png b/Minecraft.Client/Windows64Media/DLC/Skyrim/Data/Panorama/Panorama_N.png new file mode 100644 index 00000000..0a033c27 Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Skyrim/Data/Panorama/Panorama_N.png differ diff --git a/Minecraft.Client/Windows64Media/DLC/Skyrim/Data/Panorama/Panorama_S.png b/Minecraft.Client/Windows64Media/DLC/Skyrim/Data/Panorama/Panorama_S.png new file mode 100644 index 00000000..3cda1acb Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/Skyrim/Data/Panorama/Panorama_S.png differ diff --git a/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml b/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml index 1791279a..7286bfb9 100644 --- a/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml +++ b/Minecraft.Client/Windows64Media/loc/stringsGeneric.xml @@ -9634,4 +9634,16 @@ All Ender Chests in a world are linked. Items placed into an Ender Chest are acc Swap + + + Copy Save + + + + Are you sure you want to copy this save game? + + + + Copying Save + diff --git a/Minecraft.World/Biome.cpp b/Minecraft.World/Biome.cpp index ac105b23..efd6014d 100644 --- a/Minecraft.World/Biome.cpp +++ b/Minecraft.World/Biome.cpp @@ -112,6 +112,7 @@ void Biome::staticCtor() Biome::jungleEdge = (new JungleBiome(23, true))->setColor(0x628b17)->setName(L"Jungle Edge")->setLeafColor(0x537b09)->setTemperatureAndDownfall(0.95F, 0.8F)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Jungle, eMinecraftColour_Foliage_Jungle, eMinecraftColour_Water_JungleEdge,eMinecraftColour_Sky_JungleEdge); Biome::deepOcean= (new OceanBiome(24))->setName(L"Deep Ocean")->setDepthAndScale(-1.8,0.1f)->setColor(0x000070)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Ocean, eMinecraftColour_Foliage_Ocean, eMinecraftColour_Water_Ocean,eMinecraftColour_Sky_Ocean);; //public static final BiomeGenBase stoneBeach = (new BiomeGenStoneBeach(25)).setColor(10658436).setBiomeName("Stone Beach").setTemperatureRainfall(0.2F, 0.3F).setHeight(height_RockyWaters); + Biome::stoneBeach = (new StoneBeachBiome(25))->setColor(0xa2a284)->setName(L"Stone Beach")->setTemperatureAndDownfall(0.2f, 0.3f)->setDepthAndScale(0.1f, 0.8f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Beach, eMinecraftColour_Foliage_Beach, eMinecraftColour_Water_Beach, eMinecraftColour_Sky_Beach); Biome::coldBeach = (new BeachBiome(26))->setColor(0xFAF0C0)->setName(L"Cold Beach")->setTemperatureAndDownfall(0.05F, 0.3F)->setDepthAndScale(0.0F, 0.025F)->setSnowCovered()->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_IcePlains, eMinecraftColour_Foliage_IcePlains, eMinecraftColour_Water_IcePlains, eMinecraftColour_Sky_IcePlains); Biome::birchForest=(new ForestBiome(27, 2))->setColor(0x307444)->setName(L"Birch Forest")->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Forest, eMinecraftColour_Foliage_Birch, eMinecraftColour_Water_Forest, eMinecraftColour_Sky_Forest); Biome::birchForestHills=(new ForestBiome(28, 2))->setColor(0x1f5f32)->setName(L"Birch Forest Hills")->setDepthAndScale(0.45f, 0.3f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_ForestHills, eMinecraftColour_Foliage_Birch, eMinecraftColour_Water_Forest, eMinecraftColour_Sky_ForestHills); diff --git a/Minecraft.World/BiomeEdgeLayer.cpp b/Minecraft.World/BiomeEdgeLayer.cpp index 97e7024a..2ad5c505 100644 --- a/Minecraft.World/BiomeEdgeLayer.cpp +++ b/Minecraft.World/BiomeEdgeLayer.cpp @@ -1,3 +1,4 @@ +// TODO: fix cold-swampland edge-case scenario #include "stdafx.h" #include "BiomeEdgeLayer.h" #include "net.minecraft.world.level.biome.h" @@ -21,47 +22,92 @@ intArray BiomeEdgeLayer::getArea(int xo, int yo, int w, int h) initRandom(ix + xo, iy + yo); int center = b[(ix + 1) + (iy + 1) * stride]; - if (!checkEdge(b, result, ix, iy, stride, Biome::extremeHills->id, Biome::smallerExtremeHills->id, center) && - !checkEdge(b, result, ix, iy, stride, Biome::mesaPlateauF->id, Biome::mesaPlateau->id, center) && - !checkEdge(b, result, ix, iy, stride, Biome::mesaPlateau->id, Biome::mesaPlateau->id, center) && - !checkEdge(b, result, ix, iy, stride, Biome::megaTaiga->id, Biome::megaTaiga->id, center)) + if (checkEdge(b, result, ix, iy, stride, Biome::extremeHills->id, Biome::smallerExtremeHills->id, center)) + continue; + if (checkEdgeStrict(b, result, ix, iy, stride, Biome::mesaPlateauF->id, Biome::mesa->id, center)) + continue; + if (checkEdgeStrict(b, result, ix, iy, stride, Biome::mesaPlateau->id, Biome::mesa->id, center)) + continue; + if (checkEdgeStrict(b, result, ix, iy, stride, Biome::megaTaiga->id, Biome::taiga->id, center)) + continue; + + int n = b[(ix + 1) + (iy + 0) * stride]; + int e = b[(ix + 2) + (iy + 1) * stride]; + int w1 = b[(ix + 0) + (iy + 1) * stride]; + int s = b[(ix + 1) + (iy + 2) * stride]; + + if (center == Biome::desert->id) { - if (center == Biome::desert->id) { - int n = b[(ix + 1) + (iy + 0) * stride]; - int e = b[(ix + 2) + (iy + 1) * stride]; - int w1 = b[(ix + 0) + (iy + 1) * stride]; - int s = b[(ix + 1) + (iy + 2) * stride]; - if (n == Biome::iceFlats->id || e == Biome::iceFlats->id || w1 == Biome::iceFlats->id || s == Biome::iceFlats->id) { - center = Biome::extremeHills->id; - } - } - result[ix + iy * w] = center; + bool nearIce = (n == Biome::iceFlats->id || e == Biome::iceFlats->id || + w1 == Biome::iceFlats->id || s == Biome::iceFlats->id); + result[ix + iy * w] = nearIce ? Biome::extremeHills_plus->id : center; + } + else if (center == Biome::swampland->id) + { + bool nearDesert = (n == Biome::desert->id || e == Biome::desert->id || w1 == Biome::desert->id || s == Biome::desert->id); + bool nearColdTaiga = (n == Biome::coldTaiga->id || e == Biome::coldTaiga->id || w1 == Biome::coldTaiga->id || s == Biome::coldTaiga->id); + bool nearIceFlats = (n == Biome::iceFlats->id || e == Biome::iceFlats->id || w1 == Biome::iceFlats->id || s == Biome::iceFlats->id); + + if (nearDesert || nearColdTaiga || nearIceFlats) + { + result[ix + iy * w] = Biome::plains->id; + } + else + { + bool nearJungle = (n == Biome::jungle->id || e == Biome::jungle->id || w1 == Biome::jungle->id || s == Biome::jungle->id); + result[ix + iy * w] = nearJungle ? Biome::jungleEdge->id : center; + } + } + else + { + result[ix + iy * w] = center; } } } return result; } -bool BiomeEdgeLayer::checkEdge(intArray& b, intArray& result, int x, int y, int w, int biome, int target, int center) +bool BiomeEdgeLayer::checkEdge(intArray& b, intArray& result, int x, int y, int stride, int biome, int target, int center) +{ + if (!isSame(center, biome)) return false; + + int n = b[(x + 1) + (y + 0) * stride]; + int e = b[(x + 2) + (y + 1) * stride]; + int w1 = b[(x + 0) + (y + 1) * stride]; + int s = b[(x + 1) + (y + 2) * stride]; + + bool interior = isValidTemperatureEdge(n, biome) && isValidTemperatureEdge(e, biome) && + isValidTemperatureEdge(w1, biome) && isValidTemperatureEdge(s, biome); + + result[x + y * (stride - 2)] = interior ? center : target; + return true; +} + +bool BiomeEdgeLayer::checkEdgeStrict(intArray& b, intArray& result, int x, int y, int stride, int biome, int target, int center) { if (center != biome) return false; - int n = b[(x + 1) + (y + 0) * w]; - int e = b[(x + 2) + (y + 1) * w]; - int w1 = b[(x + 0) + (y + 1) * w]; - int s = b[(x + 1) + (y + 2) * w]; + int n = b[(x + 1) + (y + 0) * stride]; + int e = b[(x + 2) + (y + 1) * stride]; + int w1 = b[(x + 0) + (y + 1) * stride]; + int s = b[(x + 1) + (y + 2) * stride]; - if (n != biome || e != biome || w1 != biome || s != biome) + bool interior = isSame(n, biome) && isSame(e, biome) && isSame(w1, biome) && isSame(s, biome); + + result[x + y * (stride - 2)] = interior ? center : target; + return true; +} + +bool BiomeEdgeLayer::isValidTemperatureEdge(int neighbor, int target) +{ + if (isSame(neighbor, target)) return true; + Biome* a = Biome::getBiome(neighbor); + Biome* b = Biome::getBiome(target); + if (a != nullptr && b != nullptr) { - result[x + y * (w-2)] = target; - return true; + int catA = a->getTemperatureCategory(); + int catB = b->getTemperatureCategory(); + return catA == catB || catA == 2 || catB == 2; } return false; -} - -bool BiomeEdgeLayer::isValidTemperatureEdge(int a1biome, int a2biome) -{ - if (a1biome == a2biome) return true; - - return true; -} +} \ No newline at end of file diff --git a/Minecraft.World/BiomeEdgeLayer.h b/Minecraft.World/BiomeEdgeLayer.h index d8ee324a..822e3548 100644 --- a/Minecraft.World/BiomeEdgeLayer.h +++ b/Minecraft.World/BiomeEdgeLayer.h @@ -9,7 +9,7 @@ public: virtual intArray getArea(int xo, int yo, int w, int h) override; private: - static bool isValidTemperatureEdge(int a1biome, int a2biome); + bool isValidTemperatureEdge(int a1biome, int a2biome); bool checkEdge(intArray& b, intArray& result, int x, int y, int w, int biome, int target, int replacement); bool checkEdgeStrict(intArray& b, intArray& result, int x, int y, int w, int biome, int target, int replacement); }; \ No newline at end of file diff --git a/Minecraft.World/BiomeSource.cpp b/Minecraft.World/BiomeSource.cpp index 864a098e..158afe0f 100644 --- a/Minecraft.World/BiomeSource.cpp +++ b/Minecraft.World/BiomeSource.cpp @@ -453,15 +453,8 @@ void BiomeSource::getFracs(intArray indices, float *fracs, float *groupFracs) bool BiomeSource::getIsMatch(float *fracs, float *groupFracs) { if (fracs[0] + fracs[24] > 0.15f) return false; - int varietyCount = 0; for (int i = 0; i < 8; i++) - { - if (groupFracs[i] > 0.0f) - { - varietyCount++; - } - } - + if (groupFracs[i] > 0.0f) varietyCount++; return varietyCount >= 5; } \ No newline at end of file diff --git a/Minecraft.World/Layer.cpp b/Minecraft.World/Layer.cpp index 62091d81..996be729 100644 --- a/Minecraft.World/Layer.cpp +++ b/Minecraft.World/Layer.cpp @@ -61,7 +61,8 @@ LayerArray Layer::getDefaultLayers(int64_t seed, LevelType* levelType, void* sup zoomLevel = 6; - shared_ptr riverInit = make_shared(seed, baseLayer, 0x64); + shared_ptr riverBase = ZoomLayer::zoom(seed, baseLayer, 0x3E8, 0); + shared_ptr riverInit = make_shared(seed, riverBase, 0x64); shared_ptr hillsNoise = ZoomLayer::zoom(seed, riverInit, 0x3E8, 2); diff --git a/Minecraft.World/Layer.h b/Minecraft.World/Layer.h index cfc3cf28..b82e7062 100644 --- a/Minecraft.World/Layer.h +++ b/Minecraft.World/Layer.h @@ -26,8 +26,8 @@ public: Layer(int64_t seedMixup); virtual void init(int64_t seed); - bool isOcean(int biomeId); - bool isSame(int biomeIdA, int biomeIdB); + static bool isOcean(int biomeId); + static bool isSame(int biomeIdA, int biomeIdB); virtual void initRandom(int64_t x, int64_t y); protected: diff --git a/Minecraft.World/RegionHillsLayer.cpp b/Minecraft.World/RegionHillsLayer.cpp index 81b3a49e..ff05cf09 100644 --- a/Minecraft.World/RegionHillsLayer.cpp +++ b/Minecraft.World/RegionHillsLayer.cpp @@ -3,8 +3,6 @@ #include "IntCache.h" #include "RegionHillsLayer.h" - - RegionHillsLayer::RegionHillsLayer(int64_t seed, shared_ptr parent) : Layer(seed) { this->parent = parent; @@ -27,7 +25,7 @@ void RegionHillsLayer::init(int64_t seed) bool RegionHillsLayer::biomesEqualOrMesaPlateau(int a, int b) { - return a == b; + return isSame(a, b); // was: a == b } @@ -125,7 +123,7 @@ intArray RegionHillsLayer::getArea(int xo, int yo, int w, int h) } else if (k == Biome::extremeHills->id) { - i1 = Biome::smallerExtremeHills->id; + i1 = Biome::extremeHills_plus->id; // NOT smallerExtremeHills } else if (k == Biome::savanna->id) { @@ -133,6 +131,10 @@ intArray RegionHillsLayer::getArea(int xo, int yo, int w, int h) i1 = Biome::savannaPlateau->id; } + else if (Layer::isSame(k, Biome::mesaPlateauF->id)) + { + i1 = Biome::mesa->id; + } else if (k == Biome::deepOcean->id && nextRandom(3) == 0) { diff --git a/Minecraft.World/ShoreLayer.cpp b/Minecraft.World/ShoreLayer.cpp index 511b2f70..08f5183a 100644 --- a/Minecraft.World/ShoreLayer.cpp +++ b/Minecraft.World/ShoreLayer.cpp @@ -4,78 +4,127 @@ ShoreLayer::ShoreLayer(int64_t seed, shared_ptr parent, int64_t seedMixup) : Layer(seedMixup) { - this->parent = parent; + this->parent = parent; +} + +bool ShoreLayer::isJungleCompatible(int id) +{ + if (id == Biome::jungle->id || id == Biome::jungleHills->id || id == Biome::jungleEdge->id || + id == Biome::jungleM->id || id == Biome::jungleEdgeM->id) + return true; + if (id == Biome::forest->id || id == Biome::taiga->id) + return true; + if (isOcean(id)) + return true; + return false; +} + +bool ShoreLayer::isMesaBiome(int id) +{ + return id == Biome::mesa->id || id == Biome::mesaPlateauF->id || id == Biome::mesaPlateau->id || + id == Biome::mesaBryce->id || id == Biome::mesaPlateauFM->id || id == Biome::mesaPlateauM->id; +} + +void ShoreLayer::replaceIfNeighborOcean(intArray& b, intArray& result, int x, int y, int w, int stride, int center, int target) +{ + if (!isOcean(center)) + { + int n = b[(x + 1) + (y + 0) * stride]; + int e = b[(x + 2) + (y + 1) * stride]; + int w1 = b[(x + 0) + (y + 1) * stride]; + int s = b[(x + 1) + (y + 2) * stride]; + if (isOcean(n) || isOcean(e) || isOcean(w1) || isOcean(s)) + { + result[x + y * w] = target; + return; + } + } + result[x + y * w] = center; } intArray ShoreLayer::getArea(int xo, int yo, int w, int h) { intArray b = parent->getArea(xo - 1, yo - 1, w + 2, h + 2); - intArray result = IntCache::allocate(w * h); + int stride = w + 2; + for (int y = 0; y < h; y++) - { + { for (int x = 0; x < w; x++) - { + { initRandom(x + xo, y + yo); - int old = b[(x + 1) + (y + 1) * (w + 2)]; + int old = b[(x + 1) + (y + 1) * stride]; + + int n = b[(x + 1) + (y + 0) * stride]; + int e = b[(x + 2) + (y + 1) * stride]; + int w1 = b[(x + 0) + (y + 1) * stride]; + int s = b[(x + 1) + (y + 2) * stride]; + if (old == Biome::mushroomIsland->id) - { - int _n = b[(x + 1) + (y + 1 - 1) * (w + 2)]; - int _e = b[(x + 1 + 1) + (y + 1) * (w + 2)]; - int _w = b[(x + 1 - 1) + (y + 1) * (w + 2)]; - int _s = b[(x + 1) + (y + 1 + 1) * (w + 2)]; - if (_n == Biome::ocean->id || _e == Biome::ocean->id || _w == Biome::ocean->id || _s == Biome::ocean->id || _n == Biome::deepOcean->id || _e == Biome::deepOcean->id || _w == Biome::deepOcean->id || _s == Biome::deepOcean->id) - { - result[x + y * w] = Biome::mushroomIslandShore->id; - } - else - { - result[x + y * w] = old; - } - } - else if (old != Biome::ocean->id && old != Biome::deepOcean->id && old != Biome::river->id && old != Biome::swampland->id && old != Biome::extremeHills->id) - { - int _n = b[(x + 1) + (y + 1 - 1) * (w + 2)]; - int _e = b[(x + 1 + 1) + (y + 1) * (w + 2)]; - int _w = b[(x + 1 - 1) + (y + 1) * (w + 2)]; - int _s = b[(x + 1) + (y + 1 + 1) * (w + 2)]; - if (_n == Biome::ocean->id || _e == Biome::ocean->id || _w == Biome::ocean->id || _s == Biome::ocean->id || _n == Biome::deepOcean->id || _e == Biome::deepOcean->id || _w == Biome::deepOcean->id || _s == Biome::deepOcean->id) - { - if (old == Biome::taiga->id || old == Biome::taigaHills->id || old == Biome::megaTaiga->id || old == Biome::megaTaigaHills->id || old == Biome::coldTaiga->id || old == Biome::coldTaigaHills->id) - { - result[x + y * w] = Biome::coldBeach->id; - } - else - { - result[x + y * w] = Biome::beaches->id; - } - } - else - { - result[x + y * w] = old; - } - } - else if (old == Biome::extremeHills->id) - { - int _n = b[(x + 1) + (y + 1 - 1) * (w + 2)]; - int _e = b[(x + 1 + 1) + (y + 1) * (w + 2)]; - int _w = b[(x + 1 - 1) + (y + 1) * (w + 2)]; - int _s = b[(x + 1) + (y + 1 + 1) * (w + 2)]; - if (_n != Biome::extremeHills->id || _e != Biome::extremeHills->id || _w != Biome::extremeHills->id || _s != Biome::extremeHills->id) - { - result[x + y * w] = Biome::smallerExtremeHills->id; - } - else - { - result[x + y * w] = old; - } - } - else - { - result[x + y * w] = old; + { + // decompile checks plain ocean only, NOT deepOcean, for this branch + bool nearOcean = (n == Biome::ocean->id || e == Biome::ocean->id || + w1 == Biome::ocean->id || s == Biome::ocean->id); + result[x + y * w] = nearOcean ? Biome::mushroomIslandShore->id : old; + continue; } + + if (old == Biome::jungle->id || old == Biome::jungleHills->id || + old == Biome::jungleM->id) + { + bool allCompatible = isJungleCompatible(n) && isJungleCompatible(e) && + isJungleCompatible(w1) && isJungleCompatible(s); + if (!allCompatible) + { + result[x + y * w] = Biome::jungleEdge->id; + } + else + { + bool nearOcean = (isOcean(n) || isOcean(e) || isOcean(w1) || isOcean(s)); + result[x + y * w] = nearOcean ? Biome::beaches->id : old; + } + continue; + } + + if (old == Biome::extremeHills->id || old == Biome::extremeHills_plus->id || + old == Biome::smallerExtremeHills->id) + { + replaceIfNeighborOcean(b, result, x, y, w, stride, old, Biome::stoneBeach->id); + continue; + } + + Biome* biome = Biome::getBiome(old); + if (biome != nullptr && biome->hasSnow()) + { + replaceIfNeighborOcean(b, result, x, y, w, stride, old, Biome::coldBeach->id); + continue; + } + + if (old == Biome::mesa->id || old == Biome::mesaPlateauF->id) + { + bool nearOcean = (isOcean(n) || isOcean(e) || isOcean(w1) || isOcean(s)); + if (nearOcean) + { + result[x + y * w] = Biome::beaches->id; + } + else + { + bool allMesa = isMesaBiome(n) && isMesaBiome(e) && isMesaBiome(w1) && isMesaBiome(s); + result[x + y * w] = allMesa ? old : Biome::desert->id; + } + continue; + } + + if (old != Biome::ocean->id && old != Biome::deepOcean->id && + old != Biome::river->id && old != Biome::swampland->id) + { + bool nearOcean = (isOcean(n) || isOcean(e) || isOcean(w1) || isOcean(s)); + result[x + y * w] = nearOcean ? Biome::beaches->id : old; + continue; + } + + result[x + y * w] = old; } } - return result; -} \ No newline at end of file +} diff --git a/Minecraft.World/ShoreLayer.h b/Minecraft.World/ShoreLayer.h index cbae390f..75140a42 100644 --- a/Minecraft.World/ShoreLayer.h +++ b/Minecraft.World/ShoreLayer.h @@ -3,6 +3,10 @@ class ShoreLayer : public Layer { +private: + static bool isJungleCompatible(int id); + static bool isMesaBiome(int id); + void replaceIfNeighborOcean(intArray& b, intArray& result, int x, int y, int w, int stride, int center, int target); public: ShoreLayer(int64_t seed, shared_ptr parent, int64_t seedMixup); virtual intArray getArea(int xo, int yo, int w, int h); diff --git a/Minecraft.World/StoneBeachBiome.cpp b/Minecraft.World/StoneBeachBiome.cpp new file mode 100644 index 00000000..fcd08c57 --- /dev/null +++ b/Minecraft.World/StoneBeachBiome.cpp @@ -0,0 +1,19 @@ +#include "stdafx.h" +#include "StoneBeachBiome.h" +#include "net.minecraft.world.level.tile.h" +#include "BiomeDecorator.h" + +StoneBeachBiome::StoneBeachBiome(int id) : Biome(id) +{ + this->topMaterial = static_cast(Tile::stone_Id); + this->topMaterialData = 0; + this->material = static_cast(Tile::stone_Id); + this->materialData = 0; + + if (decorator != nullptr) + { + decorator->treeCount = 0; + decorator->grassCount = 0; + decorator->flowerCount = 0; + } +} \ No newline at end of file diff --git a/Minecraft.World/StoneBeachBiome.h b/Minecraft.World/StoneBeachBiome.h new file mode 100644 index 00000000..c4302bb1 --- /dev/null +++ b/Minecraft.World/StoneBeachBiome.h @@ -0,0 +1,10 @@ +#pragma once +#include "Biome.h" + +class StoneBeachBiome : public Biome +{ +public: + StoneBeachBiome(int id); + virtual bool isFoggy() const { return false; } + virtual bool isNatural() const { return true; } +}; \ No newline at end of file diff --git a/Minecraft.World/ZoomLayer.cpp b/Minecraft.World/ZoomLayer.cpp index 88f3e0b3..ce68c2f4 100644 --- a/Minecraft.World/ZoomLayer.cpp +++ b/Minecraft.World/ZoomLayer.cpp @@ -11,8 +11,8 @@ intArray ZoomLayer::getArea(int xo, int yo, int w, int h) { int px = xo >> 1; int py = yo >> 1; - int pw = (w >> 1) + 3; - int ph = (h >> 1) + 3; + int pw = (w >> 1) + 2; + int ph = (h >> 1) + 2; intArray p = parent->getArea(px, py, pw, ph); intArray tmp = IntCache::allocate((pw * 2) * (ph * 2)); diff --git a/Minecraft.World/cmake/sources/Common.cmake b/Minecraft.World/cmake/sources/Common.cmake index 197ed4d9..a54e2c99 100644 --- a/Minecraft.World/cmake/sources/Common.cmake +++ b/Minecraft.World/cmake/sources/Common.cmake @@ -1367,6 +1367,8 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_LEVEL_BIOME "${CMAKE_CURRENT_SOURCE_DIR}/RainforestBiome.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RainforestBiome.h" "${CMAKE_CURRENT_SOURCE_DIR}/RiverBiome.h" + "${CMAKE_CURRENT_SOURCE_DIR}/StoneBeachBiome.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/StoneBeachBiome.h" "${CMAKE_CURRENT_SOURCE_DIR}/SwampBiome.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/SwampBiome.h" "${CMAKE_CURRENT_SOURCE_DIR}/TaigaBiome.cpp" diff --git a/Minecraft.World/net.minecraft.world.level.biome.h b/Minecraft.World/net.minecraft.world.level.biome.h index b7e0bc60..64dbaea2 100644 --- a/Minecraft.World/net.minecraft.world.level.biome.h +++ b/Minecraft.World/net.minecraft.world.level.biome.h @@ -34,4 +34,5 @@ //TU31 #include "SavannaBiome.h" -#include "MesaBiome.h" \ No newline at end of file +#include "MesaBiome.h" +#include "StoneBeachBiome.h" \ No newline at end of file