From 3fa28df4dac3fd5262d90c303c0efce58bf1be07 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+tropicaaal@users.noreply.github.com> Date: Sun, 22 Mar 2026 01:27:23 -0500 Subject: [PATCH] TU19: merge Minecraft.Client/Platform/Common/GameRules --- .../GameRules/ConsoleGenerateStructure.h | 6 +- .../Common/GameRules/ConsoleSchematicFile.cpp | 28 ++- .../Common/GameRules/GameRuleManager.cpp | 107 +++----- .../GameRules/LevelGenerationOptions.cpp | 237 +++++++++++++++++- .../Common/GameRules/LevelGenerationOptions.h | 18 +- .../Common/GameRules/StartFeature.cpp | 14 +- .../Platform/Common/GameRules/StartFeature.h | 7 +- .../XboxStructureActionPlaceContainer.cpp | 11 +- .../XboxStructureActionPlaceContainer.h | 3 +- .../XboxStructureActionPlaceSpawner.cpp | 6 +- 10 files changed, 328 insertions(+), 109 deletions(-) diff --git a/Minecraft.Client/Platform/Common/GameRules/ConsoleGenerateStructure.h b/Minecraft.Client/Platform/Common/GameRules/ConsoleGenerateStructure.h index d65be8049..c65280d56 100644 --- a/Minecraft.Client/Platform/Common/GameRules/ConsoleGenerateStructure.h +++ b/Minecraft.Client/Platform/Common/GameRules/ConsoleGenerateStructure.h @@ -42,4 +42,8 @@ public: bool checkIntersects(int x0, int y0, int z0, int x1, int y1, int z1); virtual int getMinY(); -}; + + EStructurePiece GetType() { return (EStructurePiece)0; } + void addAdditonalSaveData(CompoundTag* tag) {} + void readAdditonalSaveData(CompoundTag* tag) {} +}; \ No newline at end of file diff --git a/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.cpp b/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.cpp index e4ec51441..04d7015c9 100644 --- a/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.cpp +++ b/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.cpp @@ -744,19 +744,24 @@ void ConsoleSchematicFile::generateSchematicFile( bool mobCanBeSaved = false; if (bSaveMobs) { - if ((e->GetType() & eTYPE_MONSTER) || - (e->GetType() & eTYPE_WATERANIMAL) || - (e->GetType() & eTYPE_ANIMAL) || - (e->GetType() == eTYPE_CHICKEN) || - (e->GetType() == eTYPE_WOLF) || - (e->GetType() == eTYPE_VILLAGER) || - (e->GetType() == eTYPE_MUSHROOMCOW)) { + if (e->instanceof(eTYPE_MONSTER) || + e->instanceof(eTYPE_WATERANIMAL) || + e->instanceof(eTYPE_ANIMAL) || (e->GetType() == eTYPE_VILLAGER)) + + // 4J-JEV: All these are derived from eTYPE_ANIMAL and true + // implicitly. + //|| ( e->GetType() == eTYPE_CHICKEN ) || ( e->GetType() == + // eTYPE_WOLF ) || ( e->GetType() == eTYPE_MUSHROOMCOW ) ) + { mobCanBeSaved = true; } } - if (mobCanBeSaved || e->GetType() == eTYPE_MINECART || - e->GetType() == eTYPE_BOAT || e->GetType() == eTYPE_PAINTING || - e->GetType() == eTYPE_ITEM_FRAME) { + + // 4J-JEV: Changed to check for instances of minecarts and + // hangingEntities instead of just eTYPE_PAINTING, eTYPE_ITEM_FRAME and + // eTYPE_MINECART + if (mobCanBeSaved || e->instanceof(eTYPE_MINECART) || + e->GetType() == eTYPE_BOAT || e->instanceof(eTYPE_HANGING_ENTITY)) { CompoundTag* eTag = new CompoundTag(); if (e->save(eTag)) { ListTag* pos = @@ -766,8 +771,7 @@ void ConsoleSchematicFile::generateSchematicFile( pos->get(1)->data -= yStart; pos->get(2)->data -= zStart; - if (e->GetType() == eTYPE_PAINTING || - e->GetType() == eTYPE_ITEM_FRAME) { + if (e->instanceof(eTYPE_HANGING_ENTITY)) { ((IntTag*)eTag->get(L"TileX"))->data -= xStart; ((IntTag*)eTag->get(L"TileY"))->data -= yStart; ((IntTag*)eTag->get(L"TileZ"))->data -= zStart; diff --git a/Minecraft.Client/Platform/Common/GameRules/GameRuleManager.cpp b/Minecraft.Client/Platform/Common/GameRules/GameRuleManager.cpp index 8acdd2b1b..1b7c8c5a6 100644 --- a/Minecraft.Client/Platform/Common/GameRules/GameRuleManager.cpp +++ b/Minecraft.Client/Platform/Common/GameRules/GameRuleManager.cpp @@ -106,18 +106,15 @@ void GameRuleManager::loadGameRules(DLCPack* pack) { uint8_t* dData = dlcHeader->getData(dSize); LevelGenerationOptions* createdLevelGenerationOptions = - new LevelGenerationOptions(); + new LevelGenerationOptions(pack); // = loadGameRules(dData, dSize); //, strings); createdLevelGenerationOptions->setGrSource(dlcHeader); - - readRuleFile(createdLevelGenerationOptions, dData, dSize, strings); - createdLevelGenerationOptions->setSrc( LevelGenerationOptions::eSrc_fromDLC); - // createdLevelGenerationOptions->setSrc( - // LevelGenerationOptions::eSrc_fromDLC ); + readRuleFile(createdLevelGenerationOptions, dData, dSize, strings); + dlcHeader->lgo = createdLevelGenerationOptions; } @@ -130,16 +127,14 @@ void GameRuleManager::loadGameRules(DLCPack* pack) { uint8_t* dData = dlcFile->getData(dSize); LevelGenerationOptions* createdLevelGenerationOptions = - new LevelGenerationOptions(); + new LevelGenerationOptions(pack); // = loadGameRules(dData, dSize); //, strings); createdLevelGenerationOptions->setGrSource(new JustGrSource()); - readRuleFile(createdLevelGenerationOptions, dData, dSize, strings); - createdLevelGenerationOptions->setSrc( LevelGenerationOptions::eSrc_tutorial); - // createdLevelGenerationOptions->set_DLCGameRulesFile( dlcFile ); + readRuleFile(createdLevelGenerationOptions, dData, dSize, strings); createdLevelGenerationOptions->setLoadedData(); } @@ -661,67 +656,46 @@ void GameRuleManager::loadDefaultGameRules() { #else // _XBOX - std::wstring fpTutorial = L"Tutorial.pck"; - if (app.getArchiveFileSize(fpTutorial) >= 0) { - DLCPack* pack = new DLCPack(L"", 0xffffffff); - unsigned int dwFilesProcessed = 0; - if (app.m_dlcManager.readDLCDataFile(dwFilesProcessed, fpTutorial, pack, - true)) { - app.m_dlcManager.addPack(pack); - if (!m_levelGenerators.getLevelGenerators()->empty()) { - m_levelGenerators.getLevelGenerators()->at(0)->setWorldName( - app.GetString(IDS_PLAY_TUTORIAL)); - m_levelGenerators.getLevelGenerators() - ->at(0) - ->setDefaultSaveName(app.GetString(IDS_TUTORIALSAVENAME)); - } else { - app.DebugPrintf( - "loadDefaultGameRules: Tutorial.pck parsed OK but no level " - "generators were added (missing " - "GameRules/LevelGenerationOptions tag?)\n"); - } - } else { - app.DebugPrintf( - "loadDefaultGameRules: readDLCDataFile failed for Tutorial.pck " - "(version too old, IO error, or DLC_TYPE_GameRules not " - "found)\n"); - delete pack; - } - } else { - app.DebugPrintf( - "loadDefaultGameRules: Tutorial.pck not found in archive\n"); +#ifdef _WINDOWS64 + File packedTutorialFile(L"Windows64Media\\Tutorial\\Tutorial.pck"); + if (!packedTutorialFile.exists()) + packedTutorialFile = File(L"Windows64\\Tutorial\\Tutorial.pck"); +#elif defined(__ORBIS__) + File packedTutorialFile(L"/app0/orbis/Tutorial/Tutorial.pck"); +#elif defined(__PSVITA__) + File packedTutorialFile(L"PSVita/Tutorial/Tutorial.pck"); +#elif defined(__PS3__) + File packedTutorialFile(L"PS3/Tutorial/Tutorial.pck"); +#else + File packedTutorialFile(L"Tutorial\\Tutorial.pck"); +#endif + if (loadGameRulesPack(&packedTutorialFile)) { + m_levelGenerators.getLevelGenerators()->at(0)->setWorldName( + app.GetString(IDS_PLAY_TUTORIAL)); + // m_levelGenerators.getLevelGenerators()->at(0)->setDefaultSaveName(L"Tutorial"); + m_levelGenerators.getLevelGenerators()->at(0)->setDefaultSaveName( + app.GetString(IDS_TUTORIALSAVENAME)); } - - // Linux/PC port fallback: if Tutorial.pck parsing didn't populate level - // generators (e.g. DLC version mismatch, missing GameRules tag), create a - // minimal placeholder so the game doesn't crash with vector::at(0) in - // LoadTrial(). - if (m_levelGenerators.getLevelGenerators()->empty()) { - app.DebugPrintf( - "loadDefaultGameRules: creating minimal fallback " - "LevelGenerationOptions\n"); - LevelGenerationOptions* lgo = new LevelGenerationOptions(); - lgo->setGrSource(new JustGrSource()); - lgo->setSrc(LevelGenerationOptions::eSrc_tutorial); - lgo->setWorldName(app.GetString(IDS_PLAY_TUTORIAL)); - lgo->setDefaultSaveName(app.GetString(IDS_TUTORIALSAVENAME)); - lgo->setLoadedData(); - addLevelGenerationOptions(lgo); - } - - /*StringTable *strings = new StringTable(baStrings.data, baStrings.length); - LevelGenerationOptions *lgo = new LevelGenerationOptions(); - lgo->setGrSource( new JustGrSource() ); - lgo->setSrc( LevelGenerationOptions::eSrc_tutorial ); - readRuleFile(lgo, tutorial.data, tutorial.length, strings); - lgo->setLoadedData();*/ - +#if 0 + std::wstring fpTutorial = L"Tutorial.pck"; + if(app.getArchiveFileSize(fpTutorial) >= 0) + { + DLCPack *pack = new DLCPack(L"",0xffffffff); + DWORD dwFilesProcessed = 0; + if ( app.m_dlcManager.readDLCDataFile(dwFilesProcessed,fpTutorial,pack,true) ) + { + app.m_dlcManager.addPack(pack); + //m_levelGenerators.getLevelGenerators()->at(0)->setWorldName(app.GetString(IDS_PLAY_TUTORIAL)); + //m_levelGenerators.getLevelGenerators()->at(0)->setDefaultSaveName(app.GetString(IDS_TUTORIALSAVENAME)); + } + else delete pack; + } +#endif #endif } bool GameRuleManager::loadGameRulesPack(File* path) { bool success = false; -#ifdef _XBOX if (path->exists()) { DLCPack* pack = new DLCPack(L"", 0xffffffff); unsigned int dwFilesProcessed = 0; @@ -733,12 +707,13 @@ bool GameRuleManager::loadGameRulesPack(File* path) { delete pack; } } -#endif return success; } void GameRuleManager::setLevelGenerationOptions( LevelGenerationOptions* levelGen) { + unloadCurrentGameRules(); + m_currentGameRuleDefinitions = NULL; m_currentLevelGenerationOptions = levelGen; diff --git a/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp b/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp index 47b1f225a..24bea274c 100644 --- a/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp +++ b/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp @@ -51,20 +51,24 @@ void JustGrSource::setBaseSavePath(const std::wstring& x) { bool JustGrSource::ready() { return true; } -LevelGenerationOptions::LevelGenerationOptions() { +LevelGenerationOptions::LevelGenerationOptions(DLCPack* parentPack) { m_spawnPos = NULL; m_stringTable = NULL; m_hasLoadedData = false; m_seed = 0; + m_bHasBeenInCreative = true; m_useFlatWorld = false; m_bHaveMinY = false; m_minY = INT_MAX; m_bRequiresGameRules = false; m_pbBaseSaveData = NULL; - m_baseSaveSize = 0; + m_dwBaseSaveSize = 0; + + m_parentDLCPack = parentPack; + m_bLoadingData = false; } LevelGenerationOptions::~LevelGenerationOptions() { @@ -235,6 +239,12 @@ void LevelGenerationOptions::addAttribute(const std::wstring& attributeName, app.DebugPrintf( "LevelGenerationOptions: Adding parameter baseSaveName=%ls\n", getBaseSavePath().c_str()); + } else if (attributeName.compare(L"hasBeenInCreative") == 0) { + bool value = _fromString(attributeValue); + m_bHasBeenInCreative = value; + app.DebugPrintf( + "LevelGenerationOptions: Adding parameter gameMode=%d\n", + m_bHasBeenInCreative); } else { GameRuleDefinition::addAttribute(attributeName, attributeValue); } @@ -252,9 +262,8 @@ void LevelGenerationOptions::processSchematics(LevelChunk* chunk) { rule->processSchematic(chunkBox, chunk); } - // 4jcraft added cast to unsigned - int cx = ((unsigned)chunk->x << 4); - int cz = ((unsigned)chunk->z << 4); + int cx = (chunk->x << 4); + int cz = (chunk->z << 4); for (AUTO_VAR(it, m_structureRules.begin()); it != m_structureRules.end(); it++) { @@ -420,12 +429,13 @@ void LevelGenerationOptions::getBiomeOverride(int biomeId, std::uint8_t& tile, } bool LevelGenerationOptions::isFeatureChunk( - int chunkX, int chunkZ, StructureFeature::EFeatureTypes feature) { + int chunkX, int chunkZ, StructureFeature::EFeatureTypes feature, + int* orientation) { bool isFeature = false; for (AUTO_VAR(it, m_features.begin()); it != m_features.end(); ++it) { StartFeature* sf = *it; - if (sf->isFeatureChunk(chunkX, chunkZ, feature)) { + if (sf->isFeatureChunk(chunkX, chunkZ, feature, orientation)) { isFeature = true; break; } @@ -452,6 +462,180 @@ LevelGenerationOptions::getUnfinishedSchematicFiles() { return out; } +void LevelGenerationOptions::loadBaseSaveData() { + int mountIndex = -1; + if (m_parentDLCPack != NULL) + mountIndex = m_parentDLCPack->GetDLCMountIndex(); + + if (mountIndex > -1) { +#ifdef _DURANGO + if (StorageManager.MountInstalledDLC( + ProfileManager.GetPrimaryPad(), mountIndex, + &LevelGenerationOptions::packMounted, this, + L"WPACK") != ERROR_IO_PENDING) +#else + if (StorageManager.MountInstalledDLC( + ProfileManager.GetPrimaryPad(), mountIndex, + &LevelGenerationOptions::packMounted, this, + "WPACK") != ERROR_IO_PENDING) +#endif + { + // corrupt DLC + setLoadedData(); + app.DebugPrintf("Failed to mount LGO DLC %d for pad %d\n", + mountIndex, ProfileManager.GetPrimaryPad()); + } else { + m_bLoadingData = true; + app.DebugPrintf("Attempted to mount DLC data for LGO %d\n", + mountIndex); + } + } else { + setLoadedData(); + app.SetAction(ProfileManager.GetPrimaryPad(), + eAppAction_ReloadTexturePack); + } +} + +int LevelGenerationOptions::packMounted(LPVOID pParam, int iPad, DWORD dwErr, + DWORD dwLicenceMask) { + LevelGenerationOptions* lgo = (LevelGenerationOptions*)pParam; + lgo->m_bLoadingData = false; + if (dwErr != ERROR_SUCCESS) { + // corrupt DLC + app.DebugPrintf("Failed to mount LGO DLC for pad %d: %d\n", iPad, + dwErr); + } else { + app.DebugPrintf("Mounted DLC for LGO, attempting to load data\n"); + DWORD dwFilesProcessed = 0; + int gameRulesCount = lgo->m_parentDLCPack->getDLCItemsCount( + DLCManager::e_DLCType_GameRulesHeader); + for (int i = 0; i < gameRulesCount; ++i) { + DLCGameRulesHeader* dlcFile = + (DLCGameRulesHeader*)lgo->m_parentDLCPack->getFile( + DLCManager::e_DLCType_GameRulesHeader, i); + + if (!dlcFile->getGrfPath().empty()) { + File grf(app.getFilePath(lgo->m_parentDLCPack->GetPackID(), + dlcFile->getGrfPath(), true, + L"WPACK:")); + if (grf.exists()) { +#ifdef _UNICODE + std::wstring path = grf.getPath(); + const WCHAR* pchFilename = path.c_str(); + HANDLE fileHandle = CreateFile( + pchFilename, // file name + GENERIC_READ, // access mode + 0, // share mode // TODO 4J Stu - Will we need to share + // file? Probably not but... + NULL, // Unused + OPEN_EXISTING, // how to create // TODO 4J Stu - + // Assuming that the file already exists + // if we are opening to read from it + FILE_FLAG_SEQUENTIAL_SCAN, // file attributes + NULL // Unsupported + ); +#else + const char* pchFilename = wstringtofilename(grf.getPath()); + HANDLE fileHandle = CreateFile( + pchFilename, // file name + GENERIC_READ, // access mode + 0, // share mode // TODO 4J Stu - Will we need to share + // file? Probably not but... + NULL, // Unused + OPEN_EXISTING, // how to create // TODO 4J Stu - + // Assuming that the file already exists + // if we are opening to read from it + FILE_FLAG_SEQUENTIAL_SCAN, // file attributes + NULL // Unsupported + ); +#endif + + if (fileHandle != INVALID_HANDLE_VALUE) { + DWORD dwFileSize = grf.length(); + DWORD bytesRead; + PBYTE pbData = (PBYTE) new BYTE[dwFileSize]; + BOOL bSuccess = ReadFile(fileHandle, pbData, dwFileSize, + &bytesRead, NULL); + if (bSuccess == FALSE) { + app.FatalLoadError(); + } + CloseHandle(fileHandle); + + // 4J-PB - is it possible that we can get here after a + // read fail and it's not an error? + dlcFile->setGrfData(pbData, dwFileSize, + lgo->m_stringTable); + + delete[] pbData; + + app.m_gameRules.setLevelGenerationOptions(dlcFile->lgo); + } + } + } + } + if (lgo->requiresBaseSave() && !lgo->getBaseSavePath().empty()) { + File save(app.getFilePath(lgo->m_parentDLCPack->GetPackID(), + lgo->getBaseSavePath(), true, L"WPACK:")); + if (save.exists()) { +#ifdef _UNICODE + std::wstring path = save.getPath(); + const WCHAR* pchFilename = path.c_str(); + HANDLE fileHandle = CreateFile( + pchFilename, // file name + GENERIC_READ, // access mode + 0, // share mode // TODO 4J Stu - Will we need to share + // file? Probably not but... + NULL, // Unused + OPEN_EXISTING, // how to create // TODO 4J Stu - Assuming + // that the file already exists if we are + // opening to read from it + FILE_FLAG_SEQUENTIAL_SCAN, // file attributes + NULL // Unsupported + ); +#else + const char* pchFilename = wstringtofilename(save.getPath()); + HANDLE fileHandle = CreateFile( + pchFilename, // file name + GENERIC_READ, // access mode + 0, // share mode // TODO 4J Stu - Will we need to share + // file? Probably not but... + NULL, // Unused + OPEN_EXISTING, // how to create // TODO 4J Stu - Assuming + // that the file already exists if we are + // opening to read from it + FILE_FLAG_SEQUENTIAL_SCAN, // file attributes + NULL // Unsupported + ); +#endif + + if (fileHandle != INVALID_HANDLE_VALUE) { + DWORD bytesRead, dwFileSize = GetFileSize(fileHandle, NULL); + PBYTE pbData = (PBYTE) new BYTE[dwFileSize]; + BOOL bSuccess = ReadFile(fileHandle, pbData, dwFileSize, + &bytesRead, NULL); + if (bSuccess == FALSE) { + app.FatalLoadError(); + } + CloseHandle(fileHandle); + + // 4J-PB - is it possible that we can get here after a read + // fail and it's not an error? + lgo->setBaseSaveData(pbData, dwFileSize); + } + } + } +#ifdef _DURANGO + DWORD result = StorageManager.UnmountInstalledDLC(L"WPACK"); +#else + DWORD result = StorageManager.UnmountInstalledDLC("WPACK"); +#endif + } + + lgo->setLoadedData(); + + return 0; +} + void LevelGenerationOptions::reset_start() { for (AUTO_VAR(it, m_schematicRules.begin()); it != m_schematicRules.end(); it++) { @@ -484,13 +668,37 @@ std::uint32_t LevelGenerationOptions::getRequiredTexturePackId() { return info()->getRequiredTexturePackId(); } std::wstring LevelGenerationOptions::getDefaultSaveName() { - return info()->getDefaultSaveName(); + switch (getSrc()) { + case eSrc_fromSave: + return getString(info()->getDefaultSaveName()); + case eSrc_fromDLC: + return getString(info()->getDefaultSaveName()); + case eSrc_tutorial: + return app.GetString(IDS_TUTORIALSAVENAME); + } + return L""; } -const wchar_t* LevelGenerationOptions::getWorldName() { - return info()->getWorldName(); +LPCWSTR LevelGenerationOptions::getWorldName() { + switch (getSrc()) { + case eSrc_fromSave: + return getString(info()->getWorldName()); + case eSrc_fromDLC: + return getString(info()->getWorldName()); + case eSrc_tutorial: + return app.GetString(IDS_PLAY_TUTORIAL); + } + return L""; } -const wchar_t* LevelGenerationOptions::getDisplayName() { - return info()->getDisplayName(); +LPCWSTR LevelGenerationOptions::getDisplayName() { + switch (getSrc()) { + case eSrc_fromSave: + return getString(info()->getDisplayName()); + case eSrc_fromDLC: + return getString(info()->getDisplayName()); + case eSrc_tutorial: + return L""; + } + return L""; } std::wstring LevelGenerationOptions::getGrfPath() { return info()->getGrfPath(); @@ -549,7 +757,10 @@ void LevelGenerationOptions::deleteBaseSaveData() { bool LevelGenerationOptions::hasLoadedData() { return m_hasLoadedData; } void LevelGenerationOptions::setLoadedData() { m_hasLoadedData = true; } -__int64 LevelGenerationOptions::getLevelSeed() { return m_seed; } +int64_t LevelGenerationOptions::getLevelSeed() { return m_seed; } +int LevelGenerationOptions::getLevelHasBeenInCreative() { + return m_bHasBeenInCreative; +} Pos* LevelGenerationOptions::getSpawnPos() { return m_spawnPos; } bool LevelGenerationOptions::getuseFlatWorld() { return m_useFlatWorld; } diff --git a/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.h b/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.h index a690dcbc2..0777d85dd 100644 --- a/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.h +++ b/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.h @@ -146,9 +146,10 @@ public: private: // This should match the "MapOptionsRule" definition in the XML schema - __int64 m_seed; + int64_t m_seed; bool m_useFlatWorld; Pos* m_spawnPos; + int m_bHasBeenInCreative; std::vector m_schematicRules; std::vector m_structureRules; bool m_bHaveMinY; @@ -162,8 +163,11 @@ private: StringTable* m_stringTable; + DLCPack* m_parentDLCPack; + bool m_bLoadingData; + public: - LevelGenerationOptions(); + LevelGenerationOptions(DLCPack* parentPack = NULL); ~LevelGenerationOptions(); virtual ConsoleGameRules::EGameRuleType getActionType(); @@ -176,7 +180,8 @@ public: virtual void addAttribute(const std::wstring& attributeName, const std::wstring& attributeValue); - __int64 getLevelSeed(); + int64_t getLevelSeed(); + int getLevelHasBeenInCreative(); Pos* getSpawnPos(); bool getuseFlatWorld(); @@ -204,7 +209,8 @@ public: void getBiomeOverride(int biomeId, std::uint8_t& tile, std::uint8_t& topTile); bool isFeatureChunk(int chunkX, int chunkZ, - StructureFeature::EFeatureTypes feature); + StructureFeature::EFeatureTypes feature, + int* orientation = NULL); void loadStringTable(StringTable* table); const wchar_t* getString(const std::wstring& key); @@ -212,6 +218,10 @@ public: std::unordered_map* getUnfinishedSchematicFiles(); + void loadBaseSaveData(); + static int packMounted(LPVOID pParam, int iPad, DWORD dwErr, + DWORD dwLicenceMask); + // 4J-JEV: // ApplySchematicRules contain limited state // which needs to be reset BEFORE a new game starts. diff --git a/Minecraft.Client/Platform/Common/GameRules/StartFeature.cpp b/Minecraft.Client/Platform/Common/GameRules/StartFeature.cpp index 20c7f0b5b..e1d316ea4 100644 --- a/Minecraft.Client/Platform/Common/GameRules/StartFeature.cpp +++ b/Minecraft.Client/Platform/Common/GameRules/StartFeature.cpp @@ -5,12 +5,13 @@ StartFeature::StartFeature() { m_chunkX = 0; m_chunkZ = 0; + m_orientation = 0; m_feature = StructureFeature::eFeature_Temples; } void StartFeature::writeAttributes(DataOutputStream* dos, unsigned int numAttrs) { - GameRuleDefinition::writeAttributes(dos, numAttrs + 3); + GameRuleDefinition::writeAttributes(dos, numAttrs + 4); ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_chunkX); dos->writeUTF(_toString(m_chunkX)); @@ -18,6 +19,8 @@ void StartFeature::writeAttributes(DataOutputStream* dos, dos->writeUTF(_toString(m_chunkZ)); ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_feature); dos->writeUTF(_toString((int)m_feature)); + ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_orientation); + dos->writeUTF(_toString(m_orientation)); } void StartFeature::addAttribute(const std::wstring& attributeName, @@ -30,6 +33,11 @@ void StartFeature::addAttribute(const std::wstring& attributeName, int value = _fromString(attributeValue); m_chunkZ = value; app.DebugPrintf("StartFeature: Adding parameter chunkZ=%d\n", m_chunkZ); + } else if (attributeName.compare(L"orientation") == 0) { + int value = _fromString(attributeValue); + m_orientation = value; + app.DebugPrintf("StartFeature: Adding parameter orientation=%d\n", + m_orientation); } else if (attributeName.compare(L"feature") == 0) { int value = _fromString(attributeValue); m_feature = (StructureFeature::EFeatureTypes)value; @@ -41,6 +49,8 @@ void StartFeature::addAttribute(const std::wstring& attributeName, } bool StartFeature::isFeatureChunk(int chunkX, int chunkZ, - StructureFeature::EFeatureTypes feature) { + StructureFeature::EFeatureTypes feature, + int* orientation) { + if (orientation != NULL) *orientation = m_orientation; return chunkX == m_chunkX && chunkZ == m_chunkZ && feature == m_feature; } \ No newline at end of file diff --git a/Minecraft.Client/Platform/Common/GameRules/StartFeature.h b/Minecraft.Client/Platform/Common/GameRules/StartFeature.h index c7fccf882..d2c7c9d24 100644 --- a/Minecraft.Client/Platform/Common/GameRules/StartFeature.h +++ b/Minecraft.Client/Platform/Common/GameRules/StartFeature.h @@ -6,7 +6,7 @@ class StartFeature : public GameRuleDefinition { private: - int m_chunkX, m_chunkZ; + int m_chunkX, m_chunkZ, m_orientation; StructureFeature::EFeatureTypes m_feature; public: @@ -21,5 +21,6 @@ public: const std::wstring& attributeValue); bool isFeatureChunk(int chunkX, int chunkZ, - StructureFeature::EFeatureTypes feature); -}; + StructureFeature::EFeatureTypes feature, + int* orientation); +}; \ No newline at end of file diff --git a/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceContainer.cpp b/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceContainer.cpp index ba7af8415..2a8f5950b 100644 --- a/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceContainer.cpp +++ b/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceContainer.cpp @@ -19,7 +19,7 @@ XboxStructureActionPlaceContainer::~XboxStructureActionPlaceContainer() { // 4J-JEV: Super class handles attr-facing fine. // void XboxStructureActionPlaceContainer::writeAttributes(DataOutputStream -// *dos, unsigned int numAttrs) +// *dos, UINT numAttrs) void XboxStructureActionPlaceContainer::getChildren( std::vector* children) { @@ -69,10 +69,12 @@ bool XboxStructureActionPlaceContainer::placeContainerInLevel( if (level->getTileEntity(worldX, worldY, worldZ) != NULL) { // Remove the current tile entity level->removeTileEntity(worldX, worldY, worldZ); - level->setTile(worldX, worldY, worldZ, 0); + level->setTileAndData(worldX, worldY, worldZ, 0, 0, + Tile::UPDATE_ALL); } - level->setTile(worldX, worldY, worldZ, m_tile); + level->setTileAndData(worldX, worldY, worldZ, m_tile, 0, + Tile::UPDATE_ALL); std::shared_ptr container = std::dynamic_pointer_cast( level->getTileEntity(worldX, worldY, worldZ)); @@ -82,7 +84,8 @@ bool XboxStructureActionPlaceContainer::placeContainerInLevel( "(%d,%d,%d)\n", worldX, worldY, worldZ); if (container != NULL) { - level->setData(worldX, worldY, worldZ, m_data); + level->setData(worldX, worldY, worldZ, m_data, + Tile::UPDATE_CLIENTS); // Add items int slotId = 0; for (AUTO_VAR(it, m_items.begin()); diff --git a/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceContainer.h b/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceContainer.h index 7d2265b98..7168a3ff1 100644 --- a/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceContainer.h +++ b/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceContainer.h @@ -24,8 +24,7 @@ public: ConsoleGameRules::EGameRuleType ruleType); // 4J-JEV: Super class handles attr-facing fine. - // virtual void writeAttributes(DataOutputStream *dos, unsigned int - // numAttributes); + // virtual void writeAttributes(DataOutputStream *dos, UINT numAttributes); virtual void addAttribute(const std::wstring& attributeName, const std::wstring& attributeValue); diff --git a/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceSpawner.cpp b/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceSpawner.cpp index e129ef5e0..843f0e8f2 100644 --- a/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceSpawner.cpp +++ b/Minecraft.Client/Platform/Common/GameRules/XboxStructureActionPlaceSpawner.cpp @@ -45,10 +45,12 @@ bool XboxStructureActionPlaceSpawner::placeSpawnerInLevel( if (level->getTileEntity(worldX, worldY, worldZ) != NULL) { // Remove the current tile entity level->removeTileEntity(worldX, worldY, worldZ); - level->setTile(worldX, worldY, worldZ, 0); + level->setTileAndData(worldX, worldY, worldZ, 0, 0, + Tile::UPDATE_ALL); } - level->setTile(worldX, worldY, worldZ, m_tile); + level->setTileAndData(worldX, worldY, worldZ, m_tile, 0, + Tile::UPDATE_ALL); std::shared_ptr entity = std::dynamic_pointer_cast( level->getTileEntity(worldX, worldY, worldZ));