diff --git a/.gitattributes b/.gitattributes index 2a377d08ab..e69de29bb2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,8 +0,0 @@ -*.png filter=lfs diff=lfs merge=lfs -text -*.jpg filter=lfs diff=lfs merge=lfs -text -*.ogg filter=lfs diff=lfs merge=lfs -text -*.binka filter=lfs diff=lfs merge=lfs -text -*.arc filter=lfs diff=lfs merge=lfs -text -*.ttf filter=lfs diff=lfs merge=lfs -text -*.bin filter=lfs diff=lfs merge=lfs -text -*.ico filter=lfs diff=lfs merge=lfs -text diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c75279d7d5..855491da1d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,6 +46,13 @@ However, we would accept changes that... - Having workable multi-platform compilation for ARM, Consoles, Linux - Being a good base for further expansion and modding of LCE, such as backports and "modpacks". +# Scope of PRs +All Pull Requests should fully document the changes they include in their file changes. They should also be limited to one general topic and not touch all over the codebase unless its justifiable. + +For example, we would not accept a PR that reworks UI, multiplayer code, and furnace ticking even if its a "fixup" PR as its too difficult to review a ton of code changes that are all irrelevant from each other. However, a PR focused on adding a bunch of commands or fixes several crashes that are otherwise irrelevant to each other would be accepted. + +If your PR includes any undocumented changes it will be closed. + # Use of AI and LLMs We currently do not accept any new code into the project that was written largely, entirely, or even noticably by an LLM. All contributions should be made by humans that understand the codebase. diff --git a/Minecraft.Client/ArrowRenderer.h b/Minecraft.Client/ArrowRenderer.h index 95867f5e5e..2331a94694 100644 --- a/Minecraft.Client/ArrowRenderer.h +++ b/Minecraft.Client/ArrowRenderer.h @@ -7,6 +7,6 @@ class ArrowRenderer : public EntityRenderer static ResourceLocation ARROW_LOCATION; public: - virtual void render(shared_ptr _arrow, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _arrow, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); }; diff --git a/Minecraft.Client/BatRenderer.h b/Minecraft.Client/BatRenderer.h index 882050468f..e347bd5c49 100644 --- a/Minecraft.Client/BatRenderer.h +++ b/Minecraft.Client/BatRenderer.h @@ -10,7 +10,7 @@ class BatRenderer : public MobRenderer public: BatRenderer(); - virtual void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); protected: virtual ResourceLocation *getTextureLocation(shared_ptr mob); diff --git a/Minecraft.Client/BlazeRenderer.h b/Minecraft.Client/BlazeRenderer.h index 5a009b741f..cc7687360e 100644 --- a/Minecraft.Client/BlazeRenderer.h +++ b/Minecraft.Client/BlazeRenderer.h @@ -10,6 +10,6 @@ class BlazeRenderer : public MobRenderer public: BlazeRenderer(); - virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); }; \ No newline at end of file diff --git a/Minecraft.Client/BoatRenderer.h b/Minecraft.Client/BoatRenderer.h index 9396b477a5..ee17127590 100644 --- a/Minecraft.Client/BoatRenderer.h +++ b/Minecraft.Client/BoatRenderer.h @@ -11,6 +11,6 @@ class BoatRenderer : public EntityRenderer public: BoatRenderer(); - virtual void render(shared_ptr boat, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr boat, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); }; \ No newline at end of file diff --git a/Minecraft.Client/ChickenRenderer.h b/Minecraft.Client/ChickenRenderer.h index 7e0a5d9a6a..463c059188 100644 --- a/Minecraft.Client/ChickenRenderer.h +++ b/Minecraft.Client/ChickenRenderer.h @@ -8,7 +8,7 @@ class ChickenRenderer : public MobRenderer public: ChickenRenderer(Model *model, float shadow); - virtual void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); protected: diff --git a/Minecraft.Client/ClientConnection.cpp b/Minecraft.Client/ClientConnection.cpp index ba40b43eed..325e949bbf 100644 --- a/Minecraft.Client/ClientConnection.cpp +++ b/Minecraft.Client/ClientConnection.cpp @@ -149,8 +149,56 @@ bool ClientConnection::isPrimaryConnection() const return g_NetworkManager.IsHost() || m_userIndex == ProfileManager.GetPrimaryPad(); } +ClientConnection* ClientConnection::findPrimaryConnection() const +{ + if (level == nullptr) return nullptr; + int primaryPad = ProfileManager.GetPrimaryPad(); + MultiPlayerLevel* mpLevel = (MultiPlayerLevel*)level; + for (ClientConnection* conn : mpLevel->connections) + { + if (conn != this && conn->m_userIndex == primaryPad) + return conn; + } + return nullptr; +} + +bool ClientConnection::shouldProcessForEntity(int entityId) const +{ + if (g_NetworkManager.IsHost()) return true; + if (m_userIndex == ProfileManager.GetPrimaryPad()) return true; + + ClientConnection* primary = findPrimaryConnection(); + if (primary == nullptr) return true; + return !primary->isTrackingEntity(entityId); +} + +bool ClientConnection::shouldProcessForPosition(int blockX, int blockZ) const +{ + if (g_NetworkManager.IsHost()) return true; + if (m_userIndex == ProfileManager.GetPrimaryPad()) return true; + + ClientConnection* primary = findPrimaryConnection(); + if (primary == nullptr) return true; + return !primary->m_visibleChunks.count(chunkKey(blockX >> 4, blockZ >> 4)); +} + +bool ClientConnection::anyOtherConnectionHasChunk(int x, int z) const +{ + if (level == nullptr) return false; + MultiPlayerLevel* mpLevel = (MultiPlayerLevel*)level; + int64_t key = chunkKey(x, z); + for (ClientConnection* conn : mpLevel->connections) + { + if (conn != this && conn->m_visibleChunks.count(key)) + return true; + } + return false; +} + ClientConnection::~ClientConnection() { + m_trackedEntityIds.clear(); + m_visibleChunks.clear(); delete connection; delete random; delete savedDataStorage; @@ -664,6 +712,7 @@ void ClientConnection::handleAddEntity(shared_ptr packet) } e->entityId = packet->id; level->putEntity(packet->id, e); + m_trackedEntityIds.insert(packet->id); if (packet->data > -1) // 4J - changed "no data" value to be -1, we can have a valid entity id of 0 { @@ -712,6 +761,7 @@ void ClientConnection::handleAddExperienceOrb(shared_ptr e->xRot = 0; e->entityId = packet->id; level->putEntity(packet->id, e); + m_trackedEntityIds.insert(packet->id); } void ClientConnection::handleAddGlobalEntity(shared_ptr packet) @@ -738,13 +788,13 @@ void ClientConnection::handleAddPainting(shared_ptr packet) { shared_ptr painting = std::make_shared(level, packet->x, packet->y, packet->z, packet->dir, packet->motive); level->putEntity(packet->id, painting); + m_trackedEntityIds.insert(packet->id); } void ClientConnection::handleSetEntityMotion(shared_ptr packet) { - if (!isPrimaryConnection()) + if (!shouldProcessForEntity(packet->id)) { - // Secondary connection: only accept motion for our own local player (knockback) if (minecraft->localplayers[m_userIndex] == NULL || packet->id != minecraft->localplayers[m_userIndex]->entityId) return; @@ -939,6 +989,7 @@ void ClientConnection::handleAddPlayer(shared_ptr packet) app.DebugPrintf("Custom cape for player %ls is %ls\n",player->name.c_str(),player->customTextureUrl2.c_str()); level->putEntity(packet->id, player); + m_trackedEntityIds.insert(packet->id); vector > *unpackedData = packet->getUnpackedData(); if (unpackedData != nullptr) @@ -979,7 +1030,7 @@ void ClientConnection::handleSetCarriedItem(shared_ptr pac void ClientConnection::handleMoveEntity(shared_ptr packet) { - if (!isPrimaryConnection()) return; + if (!shouldProcessForEntity(packet->id)) return; shared_ptr e = getEntity(packet->id); if (e == nullptr) return; e->xp += packet->xa; @@ -1009,7 +1060,7 @@ void ClientConnection::handleRotateMob(shared_ptr packet) void ClientConnection::handleMoveEntitySmall(shared_ptr packet) { - if (!isPrimaryConnection()) return; + if (!shouldProcessForEntity(packet->id)) return; shared_ptr e = getEntity(packet->id); if (e == nullptr) return; e->xp += packet->xa; @@ -1068,6 +1119,7 @@ void ClientConnection::handleRemoveEntity(shared_ptr packe #endif for (int i = 0; i < packet->ids.length; i++) { + m_trackedEntityIds.erase(packet->ids[i]); level->removeEntity(packet->ids[i]); } } @@ -1136,19 +1188,35 @@ void ClientConnection::handleChunkVisibilityArea(shared_ptrm_minZ; z <= packet->m_maxZ; ++z) + { for(int x = packet->m_minX; x <= packet->m_maxX; ++x) + { + m_visibleChunks.insert(chunkKey(x, z)); level->setChunkVisible(x, z, true); + } + } } void ClientConnection::handleChunkVisibility(shared_ptr packet) { if (level == NULL) return; - level->setChunkVisible(packet->x, packet->z, packet->visible); + if (packet->visible) + { + m_visibleChunks.insert(chunkKey(packet->x, packet->z)); + level->setChunkVisible(packet->x, packet->z, true); + } + else + { + m_visibleChunks.erase(chunkKey(packet->x, packet->z)); + if (!anyOtherConnectionHasChunk(packet->x, packet->z)) + { + level->setChunkVisible(packet->x, packet->z, false); + } + } } void ClientConnection::handleChunkTilesUpdate(shared_ptr packet) { - if (!isPrimaryConnection()) return; // 4J - changed to encode level in packet MultiPlayerLevel *dimensionLevel = (MultiPlayerLevel *)minecraft->levels[packet->levelIdx]; if( dimensionLevel ) @@ -1218,7 +1286,6 @@ void ClientConnection::handleChunkTilesUpdate(shared_ptr void ClientConnection::handleBlockRegionUpdate(shared_ptr packet) { - if (!isPrimaryConnection()) return; // 4J - changed to encode level in packet MultiPlayerLevel *dimensionLevel = (MultiPlayerLevel *)minecraft->levels[packet->levelIdx]; if( dimensionLevel ) @@ -1279,7 +1346,6 @@ void ClientConnection::handleBlockRegionUpdate(shared_ptr packet) { - if (!isPrimaryConnection()) return; // 4J added - using a block of 255 to signify that this is a packet for destroying a tile, where we need to inform the level renderer that we are about to do so. // This is used in creative mode as the point where a tile is first destroyed at the client end of things. Packets formed like this are potentially sent from // ServerPlayerGameMode::destroyBlock @@ -1394,7 +1460,7 @@ void ClientConnection::send(shared_ptr packet) void ClientConnection::handleTakeItemEntity(shared_ptr packet) { - if (!isPrimaryConnection()) return; + if (!shouldProcessForEntity(packet->itemId)) return; shared_ptr from = getEntity(packet->itemId); shared_ptr to = dynamic_pointer_cast(getEntity(packet->playerId)); @@ -2414,6 +2480,8 @@ void ClientConnection::close() // If it's already done, then we don't need to do anything here. And in fact trying to do something could cause a crash if(done) return; done = true; + m_trackedEntityIds.clear(); + m_visibleChunks.clear(); connection->flush(); connection->close(DisconnectPacket::eDisconnect_Closed); } @@ -2453,6 +2521,7 @@ void ClientConnection::handleAddMob(shared_ptr packet) mob->yd = packet->yd / 8000.0f; mob->zd = packet->zd / 8000.0f; level->putEntity(packet->id, mob); + m_trackedEntityIds.insert(packet->id); vector > *unpackedData = packet->getUnpackedData(); if (unpackedData != nullptr) @@ -2792,6 +2861,9 @@ void ClientConnection::handleRespawn(shared_ptr packet) // so it doesn't leak into the new dimension level->playStreamingMusic(L"", 0, 0, 0); + m_trackedEntityIds.clear(); + m_visibleChunks.clear(); + // Remove client connection from this level level->removeClientConnection(this, false); @@ -2899,8 +2971,7 @@ void ClientConnection::handleRespawn(shared_ptr packet) void ClientConnection::handleExplosion(shared_ptr packet) { - // World modification (block destruction) must only happen once - if (isPrimaryConnection()) + if (shouldProcessForPosition((int)packet->x, (int)packet->z)) { if(!packet->m_bKnockbackOnly) { @@ -3244,7 +3315,6 @@ void ClientConnection::handleTileEditorOpen(shared_ptr pac void ClientConnection::handleSignUpdate(shared_ptr packet) { - if (!isPrimaryConnection()) return; app.DebugPrintf("ClientConnection::handleSignUpdate - "); if (minecraft->level->hasChunkAt(packet->x, packet->y, packet->z)) { @@ -3278,7 +3348,6 @@ void ClientConnection::handleSignUpdate(shared_ptr packet) void ClientConnection::handleTileEntityData(shared_ptr packet) { - if (!isPrimaryConnection()) return; if (minecraft->level->hasChunkAt(packet->x, packet->y, packet->z)) { shared_ptr te = minecraft->level->getTileEntity(packet->x, packet->y, packet->z); @@ -3331,7 +3400,6 @@ void ClientConnection::handleContainerClose(shared_ptr pac void ClientConnection::handleTileEvent(shared_ptr packet) { - if (!isPrimaryConnection()) return; PIXBeginNamedEvent(0,"Handle tile event\n"); minecraft->level->tileEvent(packet->x, packet->y, packet->z, packet->tile, packet->b0, packet->b1); PIXEndNamedEvent(); @@ -3339,7 +3407,6 @@ void ClientConnection::handleTileEvent(shared_ptr packet) void ClientConnection::handleTileDestruction(shared_ptr packet) { - if (!isPrimaryConnection()) return; minecraft->level->destroyTileProgress(packet->getEntityId(), packet->getX(), packet->getY(), packet->getZ(), packet->getState()); } @@ -3421,7 +3488,6 @@ void ClientConnection::handleGameEvent(shared_ptr gameEventPack void ClientConnection::handleComplexItemData(shared_ptr packet) { - if (!isPrimaryConnection()) return; if (packet->itemType == Item::map->id) { MapItem::getSavedData(packet->itemId, minecraft->level)->handleComplexItemData(packet->data); @@ -3436,7 +3502,7 @@ void ClientConnection::handleComplexItemData(shared_ptr p void ClientConnection::handleLevelEvent(shared_ptr packet) { - if (!isPrimaryConnection()) return; + if (!shouldProcessForPosition(packet->x, packet->z)) return; if (packet->type == LevelEvent::SOUND_DRAGON_DEATH) { for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) @@ -3456,8 +3522,6 @@ void ClientConnection::handleLevelEvent(shared_ptr packet) { minecraft->level->levelEvent(packet->type, packet->x, packet->y, packet->z, packet->data); } - - minecraft->level->levelEvent(packet->type, packet->x, packet->y, packet->z, packet->data); } void ClientConnection::handleAwardStat(shared_ptr packet) @@ -3660,7 +3724,6 @@ void ClientConnection::handlePlayerAbilities(shared_ptr p void ClientConnection::handleSoundEvent(shared_ptr packet) { - if (!isPrimaryConnection()) return; minecraft->level->playLocalSound(packet->getX(), packet->getY(), packet->getZ(), packet->getSound(), packet->getVolume(), packet->getPitch(), false); } @@ -3973,7 +4036,6 @@ void ClientConnection::handleSetPlayerTeamPacket(shared_ptr void ClientConnection::handleParticleEvent(shared_ptr packet) { - if (!isPrimaryConnection()) return; for (int i = 0; i < packet->getCount(); i++) { double xVarience = random->nextGaussian() * packet->getXDist(); diff --git a/Minecraft.Client/ClientConnection.h b/Minecraft.Client/ClientConnection.h index f13b93e7fb..3448496d07 100644 --- a/Minecraft.Client/ClientConnection.h +++ b/Minecraft.Client/ClientConnection.h @@ -1,4 +1,5 @@ #pragma once +#include #include "..\Minecraft.World\net.minecraft.network.h" class Minecraft; class MultiPlayerLevel; @@ -44,6 +45,20 @@ class ClientConnection : public PacketListener private: DWORD m_userIndex; // 4J Added bool isPrimaryConnection() const; + + std::unordered_set m_trackedEntityIds; + std::unordered_set m_visibleChunks; + + static int64_t chunkKey(int x, int z) { return ((int64_t)x << 32) | ((int64_t)z & 0xFFFFFFFF); } + + ClientConnection* findPrimaryConnection() const; + bool shouldProcessForEntity(int entityId) const; + bool shouldProcessForPosition(int blockX, int blockZ) const; + bool anyOtherConnectionHasChunk(int x, int z) const; + +public: + bool isTrackingEntity(int entityId) const { return m_trackedEntityIds.count(entityId) > 0; } + public: SavedDataStorage *savedDataStorage; ClientConnection(Minecraft *minecraft, const wstring& ip, int port); diff --git a/Minecraft.Client/Common/App_Defines.h b/Minecraft.Client/Common/App_Defines.h index 7e96896c92..88745b11e8 100644 --- a/Minecraft.Client/Common/App_Defines.h +++ b/Minecraft.Client/Common/App_Defines.h @@ -55,7 +55,8 @@ enum EGameHostOptionWorldSize e_worldSize_Classic, e_worldSize_Small, e_worldSize_Medium, - e_worldSize_Large + e_worldSize_Large, + e_worldSize_Infinite }; diff --git a/Minecraft.Client/Common/Audio/SoundEngine.cpp b/Minecraft.Client/Common/Audio/SoundEngine.cpp index 24cb7bf45b..cf140c7806 100644 --- a/Minecraft.Client/Common/Audio/SoundEngine.cpp +++ b/Minecraft.Client/Common/Audio/SoundEngine.cpp @@ -260,9 +260,9 @@ void SoundEngine::updateMiniAudio() continue; } - float finalVolume = s->info.volume * m_MasterEffectsVolume; - if (finalVolume > 1.0f) - finalVolume = 1.0f; + float finalVolume = s->info.volume * m_MasterEffectsVolume * SFX_VOLUME_MULTIPLIER; + if (finalVolume > SFX_MAX_GAIN) + finalVolume = SFX_MAX_GAIN; ma_sound_set_volume(&s->sound, finalVolume); ma_sound_set_pitch(&s->sound, s->info.pitch); @@ -557,10 +557,13 @@ void SoundEngine::play(int iSound, float x, float y, float z, float volume, floa } ma_sound_set_spatialization_enabled(&s->sound, MA_TRUE); + ma_sound_set_min_distance(&s->sound, SFX_3D_MIN_DISTANCE); + ma_sound_set_max_distance(&s->sound, SFX_3D_MAX_DISTANCE); + ma_sound_set_rolloff(&s->sound, SFX_3D_ROLLOFF); - float finalVolume = volume * m_MasterEffectsVolume; - if (finalVolume > 1.0f) - finalVolume = 1.0f; + float finalVolume = volume * m_MasterEffectsVolume * SFX_VOLUME_MULTIPLIER; + if (finalVolume > SFX_MAX_GAIN) + finalVolume = SFX_MAX_GAIN; ma_sound_set_volume(&s->sound, finalVolume); ma_sound_set_pitch(&s->sound, pitch); diff --git a/Minecraft.Client/Common/Audio/SoundEngine.h b/Minecraft.Client/Common/Audio/SoundEngine.h index 2134c491c9..38d70d414d 100644 --- a/Minecraft.Client/Common/Audio/SoundEngine.h +++ b/Minecraft.Client/Common/Audio/SoundEngine.h @@ -6,6 +6,12 @@ using namespace std; #include "miniaudio.h" +constexpr float SFX_3D_MIN_DISTANCE = 1.0f; +constexpr float SFX_3D_MAX_DISTANCE = 16.0f; +constexpr float SFX_3D_ROLLOFF = 0.5f; +constexpr float SFX_VOLUME_MULTIPLIER = 1.5f; +constexpr float SFX_MAX_GAIN = 1.5f; + enum eMUSICFILES { eStream_Overworld_Calm1 = 0, diff --git a/Minecraft.Client/Common/GameRules/GameRuleManager.cpp b/Minecraft.Client/Common/GameRules/GameRuleManager.cpp index ff294a6503..95434c08cc 100644 --- a/Minecraft.Client/Common/GameRules/GameRuleManager.cpp +++ b/Minecraft.Client/Common/GameRules/GameRuleManager.cpp @@ -344,6 +344,7 @@ void GameRuleManager::writeRuleFile(DataOutputStream *dos) // Write schematic files. unordered_map *files; files = getLevelGenerationOptions()->getUnfinishedSchematicFiles(); + dos->writeInt((int)files->size()); for ( auto& it : *files ) { const wstring& filename = it.first; @@ -497,17 +498,36 @@ bool GameRuleManager::readRuleFile(LevelGenerationOptions *lgo, byte *dIn, UINT }*/ // subfile + // Old saves didn't write a numFiles count before the schematic entries. + // Detect this: a real count is small, but a UTF filename prefix reads as a large int. UINT numFiles = contentDis->readInt(); - for (UINT i = 0; i < numFiles; i++) - { - wstring sFilename = contentDis->readUTF(); - int length = contentDis->readInt(); - byteArray ba( length ); - - contentDis->read(ba); - - levelGenerator->loadSchematicFile(sFilename, ba.data, ba.length); + if (lgo->isFromSave() && numFiles > 100) + { + contentDis->skip(-4); + while (true) + { + int peek = contentDis->readInt(); + if (peek <= 100) { contentDis->skip(-4); break; } + contentDis->skip(-4); + + wstring sFilename = contentDis->readUTF(); + int length = contentDis->readInt(); + byteArray ba( length ); + contentDis->read(ba); + levelGenerator->loadSchematicFile(sFilename, ba.data, ba.length); + } + } + else + { + for (UINT i = 0; i < numFiles; i++) + { + wstring sFilename = contentDis->readUTF(); + int length = contentDis->readInt(); + byteArray ba( length ); + contentDis->read(ba); + levelGenerator->loadSchematicFile(sFilename, ba.data, ba.length); + } } LEVEL_GEN_ID lgoID = LEVEL_GEN_ID_NULL; diff --git a/Minecraft.Client/Common/GameRules/LevelGenerationOptions.cpp b/Minecraft.Client/Common/GameRules/LevelGenerationOptions.cpp index 2f121f4f94..2af1826cf1 100644 --- a/Minecraft.Client/Common/GameRules/LevelGenerationOptions.cpp +++ b/Minecraft.Client/Common/GameRules/LevelGenerationOptions.cpp @@ -455,6 +455,74 @@ unordered_map *LevelGenerationOptions::getUnfin void LevelGenerationOptions::loadBaseSaveData() { +#ifdef _WINDOWS64 + + int gameRulesCount = m_parentDLCPack ? m_parentDLCPack->getDLCItemsCount(DLCManager::e_DLCType_GameRulesHeader) : 0; + + wstring baseSave = getBaseSavePath(); + wstring packName = baseSave.substr(0, baseSave.find(L'.')); + + for (int i = 0; i < gameRulesCount; ++i) + { + DLCGameRulesHeader* dlcFile = static_cast(m_parentDLCPack->getFile(DLCManager::e_DLCType_GameRulesHeader, i)); + + if (!dlcFile->getGrfPath().empty()) + { + File grf(L"Windows64Media\\DLC\\" + packName + L"\\Data\\" + dlcFile->getGrfPath()); + + if (grf.exists()) + { + wstring path = grf.getPath(); + HANDLE fileHandle = CreateFileW(path.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr); + + if (fileHandle != INVALID_HANDLE_VALUE) + { + DWORD dwFileSize = grf.length(); + DWORD bytesRead; + PBYTE pbData = new BYTE[dwFileSize]; + BOOL bSuccess = ReadFile(fileHandle, pbData, dwFileSize, &bytesRead, nullptr); + CloseHandle(fileHandle); + + if (bSuccess) + { + dlcFile->setGrfData(pbData, dwFileSize, m_stringTable); + app.m_gameRules.setLevelGenerationOptions(dlcFile->lgo); + } + delete[] pbData; + } + } + } + } + + if (requiresBaseSave() && !getBaseSavePath().empty()) + { + File save(L"Windows64Media\\DLC\\" + packName + L"\\Data\\" + baseSave); + + if (save.exists()) + { + wstring path = save.getPath(); + HANDLE fileHandle = CreateFileW(path.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr); + + if (fileHandle != INVALID_HANDLE_VALUE) + { + DWORD dwFileSize = GetFileSize(fileHandle, nullptr); + DWORD bytesRead; + PBYTE pbData = new BYTE[dwFileSize]; + BOOL bSuccess = ReadFile(fileHandle, pbData, dwFileSize, &bytesRead, nullptr); + CloseHandle(fileHandle); + + if (bSuccess) + setBaseSaveData(pbData, dwFileSize); + else + delete[] pbData; + } + } + } + + setLoadedData(); + app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_ReloadTexturePack); + +#else int mountIndex = -1; if(m_parentDLCPack != nullptr) mountIndex = m_parentDLCPack->GetDLCMountIndex(); @@ -481,6 +549,7 @@ void LevelGenerationOptions::loadBaseSaveData() setLoadedData(); app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_ReloadTexturePack); } +#endif } int LevelGenerationOptions::packMounted(LPVOID pParam,int iPad,DWORD dwErr,DWORD dwLicenceMask) diff --git a/Minecraft.Client/Common/Media/MediaWindows64.arc b/Minecraft.Client/Common/Media/MediaWindows64.arc index 6ce552c53e..5992285036 100644 Binary files a/Minecraft.Client/Common/Media/MediaWindows64.arc and b/Minecraft.Client/Common/Media/MediaWindows64.arc differ diff --git a/Minecraft.Client/Common/Media/SettingsGraphicsMenu1080.swf b/Minecraft.Client/Common/Media/SettingsGraphicsMenu1080.swf index f6866abf1c..2495b4342f 100644 Binary files a/Minecraft.Client/Common/Media/SettingsGraphicsMenu1080.swf and b/Minecraft.Client/Common/Media/SettingsGraphicsMenu1080.swf differ diff --git a/Minecraft.Client/Common/Media/SettingsGraphicsMenu480.swf b/Minecraft.Client/Common/Media/SettingsGraphicsMenu480.swf index c360db92d3..aae01e78cd 100644 Binary files a/Minecraft.Client/Common/Media/SettingsGraphicsMenu480.swf and b/Minecraft.Client/Common/Media/SettingsGraphicsMenu480.swf differ diff --git a/Minecraft.Client/Common/Media/SettingsGraphicsMenu720.swf b/Minecraft.Client/Common/Media/SettingsGraphicsMenu720.swf index 418b1ba2bb..4e860fb1f0 100644 Binary files a/Minecraft.Client/Common/Media/SettingsGraphicsMenu720.swf and b/Minecraft.Client/Common/Media/SettingsGraphicsMenu720.swf differ diff --git a/Minecraft.Client/Common/Network/GameNetworkManager.cpp b/Minecraft.Client/Common/Network/GameNetworkManager.cpp index 3c032bf973..a502dbfb7a 100644 --- a/Minecraft.Client/Common/Network/GameNetworkManager.cpp +++ b/Minecraft.Client/Common/Network/GameNetworkManager.cpp @@ -942,13 +942,18 @@ int CGameNetworkManager::ServerThreadProc( void* lpParameter ) app.SetGameHostOption(eGameHostOption_All,param->settings); // 4J Stu - If we are loading a DLC save that's separate from the texture pack, load - if( param->levelGen != nullptr && (param->texturePackId == 0 || param->levelGen->getRequiredTexturePackId() != param->texturePackId) ) + if (param != nullptr && param->levelGen != nullptr && param->levelGen->isFromDLC()) { while((Minecraft::GetInstance()->skins->needsUIUpdate() || ui.IsReloadingSkin())) { Sleep(1); } param->levelGen->loadBaseSaveData(); + + while (!param->levelGen->hasLoadedData()) + { + Sleep(1); + } } } diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp index b32cc9346f..7340a7e0e7 100644 --- a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp +++ b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp @@ -240,7 +240,7 @@ void CPlatformNetworkManagerStub::DoWork() qnetPlayer->m_resolvedXuid = INVALID_XUID; qnetPlayer->m_gamertag[0] = 0; qnetPlayer->SetCustomDataValue(0); - if (IQNet::s_playerCount > 1) + while (IQNet::s_playerCount > 1 && IQNet::m_player[IQNet::s_playerCount - 1].GetCustomDataValue() == 0) IQNet::s_playerCount--; } // NOTE: Do NOT call PushFreeSmallId here. The old PlayerConnection's diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp index d18bfd8fcc..7502d6bf22 100644 --- a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp @@ -1298,10 +1298,8 @@ void IUIScene_AbstractContainerMenu::onMouseTick() } } - vPointerPos.x = floor(vPointerPos.x); - vPointerPos.x += ( static_cast(vPointerPos.x)%2); - vPointerPos.y = floor(vPointerPos.y); - vPointerPos.y += ( static_cast(vPointerPos.y)%2); + vPointerPos.x = static_cast(floor(vPointerPos.x + 0.5f)); + vPointerPos.y = static_cast(floor(vPointerPos.y + 0.5f)); m_pointerPos = vPointerPos; adjustPointerForSafeZone(); diff --git a/Minecraft.Client/Common/UI/IUIScene_HUD.cpp b/Minecraft.Client/Common/UI/IUIScene_HUD.cpp index fd97796659..d2754789c7 100644 --- a/Minecraft.Client/Common/UI/IUIScene_HUD.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_HUD.cpp @@ -195,8 +195,8 @@ void IUIScene_HUD::renderPlayerHealth() // Update health bool blink = pMinecraft->localplayers[iPad]->invulnerableTime / 3 % 2 == 1; if (pMinecraft->localplayers[iPad]->invulnerableTime < 10) blink = false; - int currentHealth = pMinecraft->localplayers[iPad]->getHealth(); - int oldHealth = pMinecraft->localplayers[iPad]->lastHealth; + int currentHealth = static_cast(ceil(pMinecraft->localplayers[iPad]->getHealth())); + int oldHealth = static_cast(ceil(pMinecraft->localplayers[iPad]->lastHealth)); bool bHasPoison = pMinecraft->localplayers[iPad]->hasEffect(MobEffect::poison); bool bHasWither = pMinecraft->localplayers[iPad]->hasEffect(MobEffect::wither); AttributeInstance *maxHealthAttribute = pMinecraft->localplayers[iPad]->getAttribute(SharedMonsterAttributes::MAX_HEALTH); diff --git a/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp b/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp index 418546b702..4f60de5fd5 100644 --- a/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp +++ b/Minecraft.Client/Common/UI/UIComponent_Tooltips.cpp @@ -93,18 +93,22 @@ void UIComponent_Tooltips::updateSafeZone() case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: safeTop = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); + break; case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: - safeBottom = getSafeZoneHalfHeight(); + safeTop = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); + break; case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: - safeLeft = getSafeZoneHalfWidth(); + safeTop = getSafeZoneHalfHeight(); safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); break; case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: - safeRight = getSafeZoneHalfWidth(); + safeTop = getSafeZoneHalfHeight(); safeBottom = getSafeZoneHalfHeight(); + break; case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: safeTop = getSafeZoneHalfHeight(); @@ -112,22 +116,22 @@ void UIComponent_Tooltips::updateSafeZone() break; case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: safeTop = getSafeZoneHalfHeight(); - safeRight = getSafeZoneHalfWidth(); + break; case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: - safeBottom = getSafeZoneHalfHeight(); + safeTop = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); break; case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: - safeBottom = getSafeZoneHalfHeight(); - safeRight = getSafeZoneHalfWidth(); + safeTop = getSafeZoneHalfHeight(); + break; case C4JRender::VIEWPORT_TYPE_FULLSCREEN: default: safeTop = getSafeZoneHalfHeight(); safeBottom = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); - safeRight = getSafeZoneHalfWidth(); + break; } setSafeZone(safeTop, safeBottom, safeLeft, safeRight); diff --git a/Minecraft.Client/Common/UI/UIComponent_TutorialPopup.cpp b/Minecraft.Client/Common/UI/UIComponent_TutorialPopup.cpp index fcbd17f344..76d3babfbc 100644 --- a/Minecraft.Client/Common/UI/UIComponent_TutorialPopup.cpp +++ b/Minecraft.Client/Common/UI/UIComponent_TutorialPopup.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "UI.h" #include "UIComponent_TutorialPopup.h" +#include "UISplitScreenHelpers.h" #include "..\..\Common\Tutorial\Tutorial.h" #include "..\..\..\Minecraft.World\StringHelpers.h" #include "..\..\MultiplayerLocalPlayer.h" @@ -474,27 +475,17 @@ void UIComponent_TutorialPopup::render(S32 width, S32 height, C4JRender::eViewpo { if(viewport != C4JRender::VIEWPORT_TYPE_FULLSCREEN) { - S32 xPos = 0; - S32 yPos = 0; - switch( viewport ) - { - case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: - xPos = static_cast(ui.getScreenWidth() / 2); - yPos = static_cast(ui.getScreenHeight() / 2); - break; - case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: - yPos = static_cast(ui.getScreenHeight() / 2); - break; - case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: - case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: - case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: - xPos = static_cast(ui.getScreenWidth() / 2); - break; - case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: - xPos = static_cast(ui.getScreenWidth() / 2); - yPos = static_cast(ui.getScreenHeight() / 2); - break; - } + // Derive the viewport origin and fit a 16:9 box inside it (same as UIScene::render), + // then apply safezone nudges so the popup stays clear of screen edges. + F32 originX, originY, viewW, viewH; + GetViewportRect(ui.getScreenWidth(), ui.getScreenHeight(), viewport, originX, originY, viewW, viewH); + + S32 fitW, fitH, offsetX, offsetY; + Fit16x9(viewW, viewH, fitW, fitH, offsetX, offsetY); + + S32 xPos = static_cast(originX) + offsetX; + S32 yPos = static_cast(originY) + offsetY; + //Adjust for safezone switch( viewport ) { @@ -505,6 +496,7 @@ void UIComponent_TutorialPopup::render(S32 width, S32 height, C4JRender::eViewpo case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: yPos += getSafeZoneHalfHeight(); break; + default: break; } switch( viewport ) { @@ -515,10 +507,11 @@ void UIComponent_TutorialPopup::render(S32 width, S32 height, C4JRender::eViewpo case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: xPos -= getSafeZoneHalfWidth(); break; + default: break; } ui.setupRenderPosition(xPos, yPos); - IggyPlayerSetDisplaySize( getMovie(), width, height ); + IggyPlayerSetDisplaySize( getMovie(), fitW, fitH ); IggyPlayerDraw( getMovie() ); } else diff --git a/Minecraft.Client/Common/UI/UIScene.cpp b/Minecraft.Client/Common/UI/UIScene.cpp index 5630e9726c..303897a7f1 100644 --- a/Minecraft.Client/Common/UI/UIScene.cpp +++ b/Minecraft.Client/Common/UI/UIScene.cpp @@ -172,15 +172,22 @@ void UIScene::updateSafeZone() { case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: - safeBottom = getSafeZoneHalfHeight(); + // safeTop mirrors SPLIT_TOP for visual symmetry. safeBottom omitted. + safeTop = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); + break; case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + safeTop = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); break; case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: - safeRight = getSafeZoneHalfWidth(); + safeTop = getSafeZoneHalfHeight(); + break; case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: safeTop = getSafeZoneHalfHeight(); @@ -188,22 +195,22 @@ void UIScene::updateSafeZone() break; case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: safeTop = getSafeZoneHalfHeight(); - safeRight = getSafeZoneHalfWidth(); + break; case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: - safeBottom = getSafeZoneHalfHeight(); + safeTop = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); break; case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: - safeBottom = getSafeZoneHalfHeight(); - safeRight = getSafeZoneHalfWidth(); + safeTop = getSafeZoneHalfHeight(); + break; case C4JRender::VIEWPORT_TYPE_FULLSCREEN: default: safeTop = getSafeZoneHalfHeight(); safeBottom = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); - safeRight = getSafeZoneHalfWidth(); + break; } setSafeZone(safeTop, safeBottom, safeLeft, safeRight); @@ -578,9 +585,12 @@ bool UIScene::handleMouseClick(F32 x, F32 y) if (bestCtrl->getControlType() == UIControl::eCheckBox) { UIControl_CheckBox *cb = static_cast(bestCtrl); - bool newState = !cb->IsChecked(); - cb->setChecked(newState); - handleCheckboxToggled((F64)bestId, newState); + if (cb->IsEnabled()) + { + bool newState = !cb->IsChecked(); + cb->setChecked(newState); + handleCheckboxToggled((F64)bestId, newState); + } } else { diff --git a/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp b/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp index ef72ec163f..2561d71792 100644 --- a/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp @@ -1240,6 +1240,10 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD param->xzSize = LEVEL_WIDTH_LARGE; param->hellScale = HELL_LEVEL_SCALE_LARGE; // hellsize = ceil(5*64/8) = 40 break; + case 4: // Infinite + param->xzSize = LEVEL_WIDTH_INFINITE; + param->hellScale = HELL_LEVEL_SCALE_INFINITE; + break; }; #else param->xzSize = LEVEL_MAX_WIDTH; diff --git a/Minecraft.Client/Common/UI/UIScene_FullscreenProgress.cpp b/Minecraft.Client/Common/UI/UIScene_FullscreenProgress.cpp index e89c062615..6a4ea09668 100644 --- a/Minecraft.Client/Common/UI/UIScene_FullscreenProgress.cpp +++ b/Minecraft.Client/Common/UI/UIScene_FullscreenProgress.cpp @@ -278,7 +278,7 @@ void UIScene_FullscreenProgress::handleInput(int iPad, int key, bool repeat, boo #ifdef __ORBIS__ case ACTION_MENU_TOUCHPAD_PRESS: #endif - if(pressed) + if(pressed && m_threadCompleted) { sendInputToMovie(key, repeat, pressed, released); } @@ -292,6 +292,7 @@ void UIScene_FullscreenProgress::handleInput(int iPad, int key, bool repeat, boo } break; } + handled = true; } } diff --git a/Minecraft.Client/Common/UI/UIScene_HUD.cpp b/Minecraft.Client/Common/UI/UIScene_HUD.cpp index 0d8adcb246..213caa8dc6 100644 --- a/Minecraft.Client/Common/UI/UIScene_HUD.cpp +++ b/Minecraft.Client/Common/UI/UIScene_HUD.cpp @@ -65,22 +65,26 @@ void UIScene_HUD::updateSafeZone() case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: safeTop = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); - safeRight = getSafeZoneHalfWidth(); + break; case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: - safeBottom = getSafeZoneHalfHeight(); + // safeTop mirrors SPLIT_TOP so both players have the same vertical inset + // from their viewport's top edge (split divider), keeping GUI symmetrical. + // safeBottom is intentionally omitted: it would shift m_Hud.y upward in + // ActionScript, placing the hotbar too high relative to SPLIT_TOP. + safeTop = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); - safeRight = getSafeZoneHalfWidth(); + break; case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: - safeLeft = getSafeZoneHalfWidth(); safeTop = getSafeZoneHalfHeight(); safeBottom = getSafeZoneHalfHeight(); + safeLeft = getSafeZoneHalfWidth(); break; case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: - safeRight = getSafeZoneHalfWidth(); safeTop = getSafeZoneHalfHeight(); safeBottom = getSafeZoneHalfHeight(); + break; case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: safeTop = getSafeZoneHalfHeight(); @@ -88,22 +92,22 @@ void UIScene_HUD::updateSafeZone() break; case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: safeTop = getSafeZoneHalfHeight(); - safeRight = getSafeZoneHalfWidth(); + break; case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: - safeBottom = getSafeZoneHalfHeight(); + safeTop = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); break; case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: - safeBottom = getSafeZoneHalfHeight(); - safeRight = getSafeZoneHalfWidth(); + safeTop = getSafeZoneHalfHeight(); + break; case C4JRender::VIEWPORT_TYPE_FULLSCREEN: default: safeTop = getSafeZoneHalfHeight(); safeBottom = getSafeZoneHalfHeight(); safeLeft = getSafeZoneHalfWidth(); - safeRight = getSafeZoneHalfWidth(); + break; } setSafeZone(safeTop, safeBottom, safeLeft, safeRight); @@ -734,7 +738,7 @@ void UIScene_HUD::render(S32 width, S32 height, C4JRender::eViewportType viewpor IggyPlayerSetDisplaySize( getMovie(), (S32)(m_movieWidth * scale), (S32)(m_movieHeight * scale) ); - repositionHud(tileWidth, tileHeight, scale); + repositionHud(tileWidth, tileHeight, scale, needsYTile); m_renderWidth = tileWidth; m_renderHeight = tileHeight; @@ -805,7 +809,7 @@ void UIScene_HUD::handleTimerComplete(int id) //setVisible(anyVisible); } -void UIScene_HUD::repositionHud(S32 tileWidth, S32 tileHeight, F32 scale) +void UIScene_HUD::repositionHud(S32 tileWidth, S32 tileHeight, F32 scale, bool needsYTile) { if(!m_bSplitscreen) return; diff --git a/Minecraft.Client/Common/UI/UIScene_HUD.h b/Minecraft.Client/Common/UI/UIScene_HUD.h index 569b523495..04468c8ecd 100644 --- a/Minecraft.Client/Common/UI/UIScene_HUD.h +++ b/Minecraft.Client/Common/UI/UIScene_HUD.h @@ -176,5 +176,5 @@ class UIScene_HUD : public UIScene, public IUIScene_HUD #endif private: - void repositionHud(S32 tileWidth, S32 tileHeight, F32 scale); + void repositionHud(S32 tileWidth, S32 tileHeight, F32 scale, bool needsYTile); }; diff --git a/Minecraft.Client/Common/UI/UIScene_InGameInfoMenu.cpp b/Minecraft.Client/Common/UI/UIScene_InGameInfoMenu.cpp index 7fc3d0357f..338d1905cd 100644 --- a/Minecraft.Client/Common/UI/UIScene_InGameInfoMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_InGameInfoMenu.cpp @@ -150,8 +150,6 @@ void UIScene_InGameInfoMenu::updateTooltips() void UIScene_InGameInfoMenu::handleDestroy() { g_NetworkManager.UnRegisterPlayerChangedCallback(m_iPad, &UIScene_InGameInfoMenu::OnPlayerChanged, this); - - m_parentLayer->removeComponent(eUIComponent_MenuBackground); } void UIScene_InGameInfoMenu::handleGainFocus(bool navBack) diff --git a/Minecraft.Client/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp index b2981ebf60..d953a07752 100644 --- a/Minecraft.Client/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp @@ -6,12 +6,13 @@ #define GAME_CREATE_ONLINE_TIMER_TIME 100 #ifdef _LARGE_WORLDS -int m_iWorldSizeTitleA[4] = +int m_iWorldSizeTitleA[5] = { IDS_WORLD_SIZE_TITLE_CLASSIC, IDS_WORLD_SIZE_TITLE_SMALL, IDS_WORLD_SIZE_TITLE_MEDIUM, IDS_WORLD_SIZE_TITLE_LARGE, + IDS_WORLD_SIZE_TITLE_INFINITE, }; #endif @@ -34,7 +35,8 @@ UIScene_LaunchMoreOptionsMenu::UIScene_LaunchMoreOptionsMenu(int iPad, void *ini value[1].boolval = false; if(m_params->currentWorldSize == e_worldSize_Classic || m_params->currentWorldSize == e_worldSize_Small || - m_params->currentWorldSize == e_worldSize_Medium ) + m_params->currentWorldSize == e_worldSize_Medium || + m_params->currentWorldSize == e_worldSize_Large ) { // don't show the increase world size stuff if we're already large, or the size is unknown. value[1].boolval = true; @@ -109,7 +111,7 @@ UIScene_LaunchMoreOptionsMenu::UIScene_LaunchMoreOptionsMenu(int iPad, void *ini #ifdef _LARGE_WORLDS m_labelWorldSize.init(app.GetString(IDS_WORLD_SIZE)); - m_sliderWorldSize.init(app.GetString(m_iWorldSizeTitleA[m_params->worldSize]),eControl_WorldSize,0,3,m_params->worldSize); + m_sliderWorldSize.init(app.GetString(m_iWorldSizeTitleA[m_params->worldSize]),eControl_WorldSize,0,4,m_params->worldSize); m_checkboxes[eLaunchCheckbox_DisableSaving].init( app.GetString(IDS_DISABLE_SAVING), eLaunchCheckbox_DisableSaving, m_params->bDisableSaving ); @@ -117,7 +119,7 @@ UIScene_LaunchMoreOptionsMenu::UIScene_LaunchMoreOptionsMenu(int iPad, void *ini { m_labelWorldResize.init(app.GetString(IDS_INCREASE_WORLD_SIZE)); int min= static_cast(m_params->currentWorldSize)-1; - int max=3; + int max=4; int curr = static_cast(m_params->newWorldSize)-1; m_sliderWorldResize.init(app.GetString(m_iWorldSizeTitleA[curr]),eControl_WorldResize,min,max,curr); m_checkboxes[eLaunchCheckbox_WorldResizeType].init(app.GetString(IDS_INCREASE_WORLD_SIZE_OVERWRITE_EDGES),eLaunchCheckbox_WorldResizeType,m_params->newWorldSizeOverwriteEdges); diff --git a/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp index d61a790227..6c70814c57 100644 --- a/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp @@ -912,6 +912,10 @@ void UIScene_LoadMenu::StartSharedLaunchFlow() newWorldSize = LEVEL_WIDTH_LARGE; newHellScale = HELL_LEVEL_SCALE_LARGE; break; + case e_worldSize_Infinite: + newWorldSize = LEVEL_WIDTH_INFINITE; + newHellScale = HELL_LEVEL_SCALE_INFINITE; + break; default: assert(0); break; diff --git a/Minecraft.Client/CowRenderer.h b/Minecraft.Client/CowRenderer.h index 3e4e9a0c6c..74a8089a78 100644 --- a/Minecraft.Client/CowRenderer.h +++ b/Minecraft.Client/CowRenderer.h @@ -9,6 +9,6 @@ class CowRenderer : public MobRenderer public: CowRenderer(Model *model, float shadow); - virtual void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); }; \ No newline at end of file diff --git a/Minecraft.Client/DefaultRenderer.h b/Minecraft.Client/DefaultRenderer.h index 28630de29f..f151dc97cb 100644 --- a/Minecraft.Client/DefaultRenderer.h +++ b/Minecraft.Client/DefaultRenderer.h @@ -4,6 +4,6 @@ class DefaultRenderer : public EntityRenderer { public: - virtual void render(shared_ptr entity, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr entity, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob) { return nullptr; }; }; \ No newline at end of file diff --git a/Minecraft.Client/DurangoMedia/4J_strings.h b/Minecraft.Client/DurangoMedia/4J_strings.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Minecraft.Client/DurangoMedia/Layout/Contributors/015236CEB96771670B67A93104CDDD.filestate.xml b/Minecraft.Client/DurangoMedia/Layout/Contributors/015236CEB96771670B67A93104CDDD.filestate.xml deleted file mode 100644 index c742140419..0000000000 --- a/Minecraft.Client/DurangoMedia/Layout/Contributors/015236CEB96771670B67A93104CDDD.filestate.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/AppxManifest.xml b/Minecraft.Client/DurangoMedia/Layout/Image/Loose/AppxManifest.xml deleted file mode 100644 index ae7d93e523..0000000000 --- a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/AppxManifest.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - Minecraft: Xbox One Edition - Microsoft Studios - StoreLogo.png - Minecraft - - - 6.2 - 6.2 - title - era - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - windows.xbox.networking.realtimesession.dll - - - - - - Microsoft.Xbox.GameChat.dll - - - - - - Microsoft.Xbox.Services.dll - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/Microsoft.Xbox.GameChat.dll b/Minecraft.Client/DurangoMedia/Layout/Image/Loose/Microsoft.Xbox.GameChat.dll deleted file mode 100644 index 3d83ce3f6f..0000000000 Binary files a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/Microsoft.Xbox.GameChat.dll and /dev/null differ diff --git a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/Microsoft.Xbox.Services.dll b/Minecraft.Client/DurangoMedia/Layout/Image/Loose/Microsoft.Xbox.Services.dll deleted file mode 100644 index 853404c194..0000000000 Binary files a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/Microsoft.Xbox.Services.dll and /dev/null differ diff --git a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/Minecraft.Client.exe b/Minecraft.Client/DurangoMedia/Layout/Image/Loose/Minecraft.Client.exe deleted file mode 100644 index e505c5214f..0000000000 Binary files a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/Minecraft.Client.exe and /dev/null differ diff --git a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/SmallLogo.png b/Minecraft.Client/DurangoMedia/Layout/Image/Loose/SmallLogo.png deleted file mode 100644 index 00b540716f..0000000000 Binary files a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/SmallLogo.png and /dev/null differ diff --git a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/SplashScreen.png b/Minecraft.Client/DurangoMedia/Layout/Image/Loose/SplashScreen.png deleted file mode 100644 index 948fdad77a..0000000000 Binary files a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/SplashScreen.png and /dev/null differ diff --git a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/StoreLogo.png b/Minecraft.Client/DurangoMedia/Layout/Image/Loose/StoreLogo.png deleted file mode 100644 index 679b33daaa..0000000000 Binary files a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/StoreLogo.png and /dev/null differ diff --git a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/appdata.bin b/Minecraft.Client/DurangoMedia/Layout/Image/Loose/appdata.bin deleted file mode 100644 index 42e51480a3..0000000000 Binary files a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/appdata.bin and /dev/null differ diff --git a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/windows.xbox.networking.realtimesession.dll b/Minecraft.Client/DurangoMedia/Layout/Image/Loose/windows.xbox.networking.realtimesession.dll deleted file mode 100644 index 7ff53c86bc..0000000000 Binary files a/Minecraft.Client/DurangoMedia/Layout/Image/Loose/windows.xbox.networking.realtimesession.dll and /dev/null differ diff --git a/Minecraft.Client/EnderCrystalRenderer.h b/Minecraft.Client/EnderCrystalRenderer.h index 76e3b1718b..ba43ebf212 100644 --- a/Minecraft.Client/EnderCrystalRenderer.h +++ b/Minecraft.Client/EnderCrystalRenderer.h @@ -13,6 +13,6 @@ class EnderCrystalRenderer : public EntityRenderer public: EnderCrystalRenderer(); - virtual void render(shared_ptr _crystal, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _crystal, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); }; \ No newline at end of file diff --git a/Minecraft.Client/EnderDragonRenderer.h b/Minecraft.Client/EnderDragonRenderer.h index 19209a454a..1df60c2a10 100644 --- a/Minecraft.Client/EnderDragonRenderer.h +++ b/Minecraft.Client/EnderDragonRenderer.h @@ -25,7 +25,7 @@ class EnderDragonRenderer : public MobRenderer virtual void renderModel(shared_ptr _mob, float wp, float ws, float bob, float headRotMinusBodyRot, float headRotx, float scale); public: - virtual void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); protected: diff --git a/Minecraft.Client/EndermanRenderer.h b/Minecraft.Client/EndermanRenderer.h index a65464c062..6fd210c6f1 100644 --- a/Minecraft.Client/EndermanRenderer.h +++ b/Minecraft.Client/EndermanRenderer.h @@ -15,7 +15,7 @@ class EndermanRenderer : public MobRenderer public: EndermanRenderer(); - void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); ResourceLocation *getTextureLocation(shared_ptr mob); void additionalRendering(shared_ptr _mob, float a); diff --git a/Minecraft.Client/EntityRenderDispatcher.cpp b/Minecraft.Client/EntityRenderDispatcher.cpp index 01972e5685..35b2024470 100644 --- a/Minecraft.Client/EntityRenderDispatcher.cpp +++ b/Minecraft.Client/EntityRenderDispatcher.cpp @@ -295,6 +295,11 @@ void EntityRenderDispatcher::render(shared_ptr entity, double x, double } } +void EntityRenderDispatcher::beginFrame() +{ + shadowTileCache.clear(); +} + double EntityRenderDispatcher::distanceToSqr(double x, double y, double z) { double xd = x - xPlayer; diff --git a/Minecraft.Client/EntityRenderDispatcher.h b/Minecraft.Client/EntityRenderDispatcher.h index 07ab7c4d00..41bd9d4d5f 100644 --- a/Minecraft.Client/EntityRenderDispatcher.h +++ b/Minecraft.Client/EntityRenderDispatcher.h @@ -17,6 +17,29 @@ class EntityRenderDispatcher public: static EntityRenderDispatcher *instance; + struct ShadowTileKey + { + int x, y, z; + bool operator==(const ShadowTileKey &o) const + { + return x == o.x && y == o.y && z == o.z; + } + }; + + struct ShadowTileKeyHash + { + size_t operator()(const ShadowTileKey &k) const + { + return ((size_t)k.x * 73856093) ^ ((size_t)k.y * 19349663) ^ ((size_t)k.z * 83492791); + } + }; + + struct ShadowTileValue + { + int tileid; + int brightness; + }; + private: Font *font; @@ -39,11 +62,13 @@ class EntityRenderDispatcher EntityRenderDispatcher(); public: + unordered_map shadowTileCache; + void beginFrame(); EntityRenderer *getRenderer(eINSTANCEOF e); EntityRenderer *getRenderer(shared_ptr e); void prepare(Level *level, Textures *textures, Font *font, shared_ptr player, shared_ptr crosshairPickMob, Options *options, float a); - void render(shared_ptr entity, float a); - void render(shared_ptr entity, double x, double y, double z, float rot, float a, bool bItemFrame = false, bool bRenderPlayerShadow = true); + void render(const shared_ptr entity, float a); + void render(const shared_ptr entity, double x, double y, double z, float rot, float a, bool bItemFrame = false, bool bRenderPlayerShadow = true); void setLevel(Level *level); double distanceToSqr(double x, double y, double z); Font *getFont(); diff --git a/Minecraft.Client/EntityRenderer.cpp b/Minecraft.Client/EntityRenderer.cpp index fa41dfa606..28fb05a760 100644 --- a/Minecraft.Client/EntityRenderer.cpp +++ b/Minecraft.Client/EntityRenderer.cpp @@ -202,18 +202,26 @@ void EntityRenderer::renderShadow(shared_ptr e, double x, double y, doub double xo = x - ex; double yo = y - ey; double zo = z - ez; - + auto &cache = entityRenderDispatcher->shadowTileCache; Tesselator *tt = Tesselator::getInstance(); tt->begin(); for (int xt = x0; xt <= x1; xt++) for (int yt = y0; yt <= y1; yt++) for (int zt = z0; zt <= z1; zt++) - { - int t = level->getTile(xt, yt - 1, zt); - if (t > 0 && level->getRawBrightness(xt, yt, zt) > 3) + { + EntityRenderDispatcher::ShadowTileKey key = { xt, yt, zt }; + auto it = cache.find(key); + if (it == cache.end()) + { + EntityRenderDispatcher::ShadowTileValue val; + val.tileid = level->getTile(xt, yt - 1, zt); + val.brightness = (val.tileid > 0) ? level->getRawBrightness(xt, yt, zt) : 0; + it = cache.emplace(key, val).first; + } + if (it->second.tileid > 0 && it->second.brightness > 3) { - renderTileShadow(Tile::tiles[t], x, y + e->getShadowHeightOffs() + fYLocalPlayerShadowOffset, z, xt, yt , zt, pow, r, xo, yo + e->getShadowHeightOffs() + fYLocalPlayerShadowOffset, zo); - } + renderTileShadow(Tile::tiles[it->second.tileid], x, y + e->getShadowHeightOffs() + fYLocalPlayerShadowOffset, z, xt, yt, zt, pow, r, xo, yo + e->getShadowHeightOffs() + fYLocalPlayerShadowOffset, zo); + } } tt->end(); diff --git a/Minecraft.Client/EntityRenderer.h b/Minecraft.Client/EntityRenderer.h index ef3b63bdc2..9d3f208902 100644 --- a/Minecraft.Client/EntityRenderer.h +++ b/Minecraft.Client/EntityRenderer.h @@ -42,7 +42,7 @@ class EntityRenderer EntityRenderer(); // 4J - added virtual ~EntityRenderer(); public: - virtual void render(shared_ptr entity, double x, double y, double z, float rot, float a) = 0; + virtual void render(const shared_ptr entity, double x, double y, double z, float rot, float a) = 0; protected: virtual void bindTexture(shared_ptr entity); virtual void bindTexture(ResourceLocation *location); @@ -61,7 +61,7 @@ class EntityRenderer static void renderFlat(AABB *bb); static void renderFlat(float x0, float y0, float z0, float x1, float y1, float z1); virtual void init(EntityRenderDispatcher *entityRenderDispatcher); - virtual void postRender(shared_ptr entity, double x, double y, double z, float rot, float a, bool bRenderPlayerShadow); + virtual void postRender(const shared_ptr entity, double x, double y, double z, float rot, float a, bool bRenderPlayerShadow); virtual Font *getFont(); virtual void registerTerrainTextures(IconRegister *iconRegister); diff --git a/Minecraft.Client/ExperienceOrbRenderer.h b/Minecraft.Client/ExperienceOrbRenderer.h index 68047b803b..97c02ce828 100644 --- a/Minecraft.Client/ExperienceOrbRenderer.h +++ b/Minecraft.Client/ExperienceOrbRenderer.h @@ -9,7 +9,7 @@ class ExperienceOrbRenderer : public EntityRenderer public: ExperienceOrbRenderer(); - virtual void render(shared_ptr _orb, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _orb, double x, double y, double z, float rot, float a); void blit(int x, int y, int sx, int sy, int w, int h); virtual ResourceLocation *getTextureLocation(shared_ptr mob); diff --git a/Minecraft.Client/FallingTileRenderer.h b/Minecraft.Client/FallingTileRenderer.h index de4c5bfc38..bdf879ab1d 100644 --- a/Minecraft.Client/FallingTileRenderer.h +++ b/Minecraft.Client/FallingTileRenderer.h @@ -9,6 +9,6 @@ class FallingTileRenderer : public EntityRenderer public: FallingTileRenderer(); - virtual void render(shared_ptr _tile, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _tile, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); }; \ No newline at end of file diff --git a/Minecraft.Client/FireballRenderer.h b/Minecraft.Client/FireballRenderer.h index 44b8b4c4f4..cdd242b23b 100644 --- a/Minecraft.Client/FireballRenderer.h +++ b/Minecraft.Client/FireballRenderer.h @@ -9,7 +9,7 @@ class FireballRenderer : public EntityRenderer public: FireballRenderer(float scale); - virtual void render(shared_ptr _fireball, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _fireball, double x, double y, double z, float rot, float a); private: // 4J Added override diff --git a/Minecraft.Client/FishingHookRenderer.h b/Minecraft.Client/FishingHookRenderer.h index 8c58ea9b7b..d0ec8755c8 100644 --- a/Minecraft.Client/FishingHookRenderer.h +++ b/Minecraft.Client/FishingHookRenderer.h @@ -7,6 +7,6 @@ class FishingHookRenderer : public EntityRenderer static ResourceLocation PARTICLE_LOCATION; public: - virtual void render(shared_ptr _hook, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _hook, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); }; \ No newline at end of file diff --git a/Minecraft.Client/Gui.cpp b/Minecraft.Client/Gui.cpp index 43b41998b2..f0d44319a1 100644 --- a/Minecraft.Client/Gui.cpp +++ b/Minecraft.Client/Gui.cpp @@ -443,7 +443,8 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) double maxHealth = minecraft->localplayers[iPad]->getAttribute(SharedMonsterAttributes.MAX_HEALTH); double totalAbsorption = minecraft->localplayers[iPad]->getAbsorptionAmount(); - int numHealthRows = Mth.ceil((maxHealth + totalAbsorption) / 2 / (float) NUM_HEARTS_PER_ROW); + const double healthHalves = (maxHealth + totalAbsorption) / 2.0; + int numHealthRows = Mth.ceil(healthHalves / (float) NUM_HEARTS_PER_ROW); int healthRowHeight = Math.max(10 - (numHealthRows - 2), 3); int yLine2 = yLine1 - (numHealthRows - 1) * healthRowHeight - 10; absorption = totalAbsorption; @@ -469,7 +470,7 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) } //minecraft.profiler.popPush("health"); - for (int i = Mth.ceil((maxHealth + totalAbsorption) / 2) - 1; i >= 0; i--) + for (int i = (int)Mth.ceil(healthHalves) - 1; i >= 0; i--) { int healthTexBaseX = 16; if (minecraft.player.hasEffect(MobEffect.poison)) @@ -607,8 +608,11 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) // render air bubbles if (minecraft->player->isUnderLiquid(Material::water)) { - int count = (int) ceil((minecraft->player->getAirSupply() - 2) * 10.0f / Player::TOTAL_AIR_SUPPLY); - int extra = (int) ceil((minecraft->player->getAirSupply()) * 10.0f / Player::TOTAL_AIR_SUPPLY) - count; + const int airSupply = minecraft->player->getAirSupply(); + const float airScale = 10.0f / Player::TOTAL_AIR_SUPPLY; + const float airSupplyScaled = airSupply * airScale; + int count = (int) ceil((airSupply - 2) * airScale); + int extra = (int) ceil(airSupplyScaled) - count; for (int i = 0; i < count + extra; i++) { // Air bubbles @@ -725,7 +729,8 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) Lighting::turnOn(); glRotatef(-45 - 90, 0, 1, 0); - glRotatef(-(float) atan(yd / 40.0f ) * 20, 1, 0, 0); + const float xRotAngle = -(float) atan(yd / 40.0f) * 20; + glRotatef(xRotAngle, 1, 0, 0); float bodyRot = (minecraft->player->yBodyRotO + (minecraft->player->yBodyRot - minecraft->player->yBodyRotO)); // Fixed rotation angle of degrees, adjusted by bodyRot to negate the rotation that occurs in the renderer // bodyRot in the rotation below is a simplification of "180 - (180 - bodyRot)" where the first 180 is EntityRenderDispatcher::instance->playerRotY that we set below @@ -736,7 +741,7 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) // Set head rotation to body rotation to make head static minecraft->player->yRot = bodyRot; minecraft->player->yRotO = minecraft->player->yRot; - minecraft->player->xRot = -(float) atan(yd / 40.0f) * 20; + minecraft->player->xRot = xRotAngle; minecraft->player->onFire = 0; minecraft->player->setSharedFlag(Entity::FLAG_ONFIRE, false); @@ -849,207 +854,6 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) // font.draw(str, x + 1, y, 0xffffff); // } -#ifndef _FINAL_BUILD - MemSect(31); - - // temporarily render overlay at all times so version is more obvious in bug reports - // we can turn this off once things stabilize - if (true)// minecraft->options->renderDebug && minecraft->player != nullptr && minecraft->level != nullptr) - { - const int debugLeft = 1; - const int debugTop = 1; - const float maxContentWidth = 1200.f; - const float maxContentHeight = 420.f; - float scale = static_cast(screenWidth - debugLeft - 8) / maxContentWidth; - float scaleV = static_cast(screenHeight - debugTop - 80) / maxContentHeight; - if (scaleV < scale) scale = scaleV; - if (scale > 1.f) scale = 1.f; - if (scale < 0.5f) scale = 0.5f; - glPushMatrix(); - glTranslatef(static_cast(debugLeft), static_cast(debugTop), 0.f); - glScalef(scale, scale, 1.f); - glTranslatef(static_cast(-debugLeft), static_cast(-debugTop), 0.f); - - vector lines; - - lines.push_back(ClientConstants::VERSION_STRING); - lines.push_back(ClientConstants::BRANCH_STRING); - if (minecraft->options->renderDebug && minecraft->player != nullptr && minecraft->level != nullptr) - { - lines.push_back(minecraft->fpsString); - lines.push_back(L"E: " + std::to_wstring(minecraft->level->getAllEntities().size())); // Could maybe use entity::shouldRender to work out how many are rendered but thats like expensive - // TODO Add server information with packet counts - once multiplayer is more stable - int renderDistance = app.GetGameSettings(iPad, eGameSetting_RenderDistance); - // Calculate the chunk sections using 16 * (2n + 1)^2 - lines.push_back(L"C: " + std::to_wstring(16 * (2 * renderDistance + 1) * (2 * renderDistance + 1)) + L" D: " + std::to_wstring(renderDistance)); - lines.push_back(minecraft->gatherStats4()); // Chunk Cache - - // Dimension - wstring dimension = L"unknown"; - switch (minecraft->player->dimension) - { - case -1: - dimension = L"minecraft:the_nether"; - break; - case 0: - dimension = L"minecraft:overworld"; - break; - case 1: - dimension = L"minecraft:the_end"; - break; - } - lines.push_back(dimension); - - lines.push_back(L""); // Spacer - - // Players block pos - int xBlockPos = Mth::floor(minecraft->player->x); - int yBlockPos = Mth::floor(minecraft->player->y); - int zBlockPos = Mth::floor(minecraft->player->z); - - // Chunk player is in - int xChunkPos = xBlockPos >> 4; - int yChunkPos = yBlockPos >> 4; - int zChunkPos = zBlockPos >> 4; - - // Players offset within the chunk - int xChunkOffset = xBlockPos & 15; - int yChunkOffset = yBlockPos & 15; - int zChunkOffset = zBlockPos & 15; - - // Format the position like java with limited decumal places - WCHAR posString[44]; // Allows upto 7 digit positions (+-9_999_999) - swprintf(posString, 44, L"%.3f / %.5f / %.3f", minecraft->player->x, minecraft->player->y, minecraft->player->z); - - lines.push_back(L"XYZ: " + std::wstring(posString)); - lines.push_back(L"Block: " + std::to_wstring(static_cast(xBlockPos)) + L" " + std::to_wstring(static_cast(yBlockPos)) + L" " + std::to_wstring(static_cast(zBlockPos))); - lines.push_back(L"Chunk: " + std::to_wstring(xChunkOffset) + L" " + std::to_wstring(yChunkOffset) + L" " + std::to_wstring(zChunkOffset) + L" in " + std::to_wstring(xChunkPos) + L" " + std::to_wstring(yChunkPos) + L" " + std::to_wstring(zChunkPos)); - - // Wrap the yRot to 360 then adjust to (-180 to 180) range to match java - float yRotDisplay = fmod(minecraft->player->yRot, 360.0f); - if (yRotDisplay > 180.0f) - { - yRotDisplay -= 360.0f; - } - if (yRotDisplay < -180.0f) - { - yRotDisplay += 360.0f; - } - // Generate the angle string in the format "yRot / xRot" with one decimal place, similar to java edition - WCHAR angleString[16]; - swprintf(angleString, 16, L"%.1f / %.1f", yRotDisplay, minecraft->player->xRot); - - // Work out the named direction - int direction = Mth::floor(minecraft->player->yRot * 4.0f / 360.0f + 0.5) & 0x3; - wstring cardinalDirection; - switch (direction) - { - case 0: - cardinalDirection = L"south"; - break; - case 1: - cardinalDirection = L"west"; - break; - case 2: - cardinalDirection = L"north"; - break; - case 3: - cardinalDirection = L"east"; - break; - } - - lines.push_back(L"Facing: " + cardinalDirection + L" (" + angleString + L")"); - - // We have to limit y to 256 as we don't get any information past that - if (minecraft->level != NULL && minecraft->level->hasChunkAt(xBlockPos, fmod(yBlockPos, 256), zBlockPos)) - { - LevelChunk *chunkAt = minecraft->level->getChunkAt(xBlockPos, zBlockPos); - if (chunkAt != NULL) - { - int skyLight = chunkAt->getBrightness(LightLayer::Sky, xChunkOffset, yChunkOffset, zChunkOffset); - int blockLight = chunkAt->getBrightness(LightLayer::Block, xChunkOffset, yChunkOffset, zChunkOffset); - int maxLight = fmax(skyLight, blockLight); - lines.push_back(L"Light: " + std::to_wstring(maxLight) + L" (" + std::to_wstring(skyLight) + L" sky, " + std::to_wstring(blockLight) + L" block)"); - - lines.push_back(L"CH S: " + std::to_wstring(chunkAt->getHeightmap(xChunkOffset, zChunkOffset))); - - Biome *biome = chunkAt->getBiome(xChunkOffset, zChunkOffset, minecraft->level->getBiomeSource()); - lines.push_back(L"Biome: " + biome->m_name + L" (" + std::to_wstring(biome->id) + L")"); - - lines.push_back(L"Difficulty: " + std::to_wstring(minecraft->level->difficulty) + L" (Day " + std::to_wstring(minecraft->level->getGameTime() / Level::TICKS_PER_DAY) + L")"); - } - } - - // This is all LCE only stuff, it was never on java - lines.push_back(L""); // Spacer - lines.push_back(L"Seed: " + std::to_wstring(minecraft->level->getLevelData()->getSeed())); - lines.push_back(minecraft->gatherStats1()); // Time to autosave - lines.push_back(minecraft->gatherStats2()); // Empty currently - CPlatformNetworkManagerStub::GatherStats() - lines.push_back(minecraft->gatherStats3()); // RTT - } - -#ifdef _DEBUG // Only show terrain features in debug builds not release - // TERRAIN FEATURES - if (minecraft->level->dimension->id == 0) - { - wstring wfeature[eTerrainFeature_Count]; - - wfeature[eTerrainFeature_Stronghold] = L"Stronghold: "; - wfeature[eTerrainFeature_Mineshaft] = L"Mineshaft: "; - wfeature[eTerrainFeature_Village] = L"Village: "; - wfeature[eTerrainFeature_Ravine] = L"Ravine: "; - - float maxW = static_cast(screenWidth - debugLeft - 8) / scale; - float maxWForContent = maxW - static_cast(font->width(L"...")); - bool truncated[eTerrainFeature_Count] = {}; - - for (size_t i = 0; i < app.m_vTerrainFeatures.size(); i++) - { - FEATURE_DATA *pFeatureData = app.m_vTerrainFeatures[i]; - int type = pFeatureData->eTerrainFeature; - if (type < eTerrainFeature_Stronghold || type > eTerrainFeature_Ravine) - { - continue; - } - if (truncated[type]) - { - continue; - } - - wstring itemInfo = L"[" + std::to_wstring(pFeatureData->x * 16) + L", " + std::to_wstring(pFeatureData->z * 16) + L"] "; - if (font->width(wfeature[type] + itemInfo) <= maxWForContent) - { - wfeature[type] += itemInfo; - } - else - { - wfeature[type] += L"..."; - truncated[type] = true; - } - } - - lines.push_back(L""); // Add a spacer line - for (int i = eTerrainFeature_Stronghold; i <= static_cast(eTerrainFeature_Ravine); i++) - { - lines.push_back(wfeature[i]); - } - lines.push_back(L""); - } -#endif - - // Loop through the lines and draw them all on screen - int yPos = debugTop; - for (const auto &line : lines) - { - drawString(font, line, debugLeft, yPos, 0xffffff); - yPos += 10; - } - - glPopMatrix(); - } - MemSect(0); -#endif - lastTickA = a; // 4J Stu - This is now displayed in a xui scene #if 0 @@ -1203,6 +1007,190 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) glPopMatrix(); } +#ifndef _FINAL_BUILD + MemSect(31); + if (true) + { + // Real window dimensions updated on every WM_SIZE — always current + extern int g_rScreenWidth; + extern int g_rScreenHeight; + + // Set up a fresh projection using physical pixel coordinates so the debug + // text is never distorted regardless of aspect ratio, splitscreen layout, + // or menu state. 1 coordinate unit = 1 physical pixel. + // Compute the actual viewport dimensions for this player's screen section. + // glOrtho must match the viewport exactly for 1 unit = 1 physical pixel. + int vpW = g_rScreenWidth; + int vpH = g_rScreenHeight; + switch (minecraft->player->m_iScreenSection) + { + case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: + case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: + vpH /= 2; + break; + case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: + case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: + vpW /= 2; + break; + 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: + vpW /= 2; + vpH /= 2; + break; + default: // VIEWPORT_TYPE_FULLSCREEN + break; + } + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, vpW, vpH, 0, 1000, 3000); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTranslatef(0, 0, -2000); + + // Font was designed for guiScale px/unit; scale up so characters appear + // at the same physical size as the rest of the HUD at 0.5x. + const float fontScale = static_cast(guiScale) * 1.0f; + const int debugLeft = 1; + const int debugTop = 1; + + glTranslatef(static_cast(debugLeft), static_cast(debugTop), 0.f); + glScalef(fontScale, fontScale, 1.f); + glTranslatef(static_cast(-debugLeft), static_cast(-debugTop), 0.f); + + vector lines; + + // Only show version/branch for player 0 to avoid cluttering each splitscreen viewport + if (iPad == 0) + { + lines.push_back(ClientConstants::VERSION_STRING); + lines.push_back(ClientConstants::BRANCH_STRING); + } + if (minecraft->options->renderDebug && minecraft->player != nullptr && minecraft->level != nullptr) + { + lines.push_back(minecraft->fpsString); + lines.push_back(L"E: " + std::to_wstring(minecraft->level->getAllEntities().size())); + int renderDistance = app.GetGameSettings(iPad, eGameSetting_RenderDistance); + lines.push_back(L"C: " + std::to_wstring(16 * (2 * renderDistance + 1) * (2 * renderDistance + 1)) + L" D: " + std::to_wstring(renderDistance)); + lines.push_back(minecraft->gatherStats4()); + + wstring dimension = L"unknown"; + switch (minecraft->player->dimension) + { + case -1: dimension = L"minecraft:the_nether"; break; + case 0: dimension = L"minecraft:overworld"; break; + case 1: dimension = L"minecraft:the_end"; break; + } + lines.push_back(dimension); + lines.push_back(L""); + + int xBlockPos = Mth::floor(minecraft->player->x); + int yBlockPos = Mth::floor(minecraft->player->y); + int zBlockPos = Mth::floor(minecraft->player->z); + int xChunkPos = xBlockPos >> 4; + int yChunkPos = yBlockPos >> 4; + int zChunkPos = zBlockPos >> 4; + int xChunkOffset = xBlockPos & 15; + int yChunkOffset = yBlockPos & 15; + int zChunkOffset = zBlockPos & 15; + + WCHAR posString[44]; + swprintf(posString, 44, L"%.3f / %.5f / %.3f", minecraft->player->x, minecraft->player->y, minecraft->player->z); + + lines.push_back(L"XYZ: " + std::wstring(posString)); + lines.push_back(L"Block: " + std::to_wstring(xBlockPos) + L" " + std::to_wstring(yBlockPos) + L" " + std::to_wstring(zBlockPos)); + lines.push_back(L"Chunk: " + std::to_wstring(xChunkOffset) + L" " + std::to_wstring(yChunkOffset) + L" " + std::to_wstring(zChunkOffset) + L" in " + std::to_wstring(xChunkPos) + L" " + std::to_wstring(yChunkPos) + L" " + std::to_wstring(zChunkPos)); + + float yRotDisplay = fmod(minecraft->player->yRot, 360.0f); + if (yRotDisplay > 180.0f) yRotDisplay -= 360.0f; + if (yRotDisplay < -180.0f) yRotDisplay += 360.0f; + WCHAR angleString[16]; + swprintf(angleString, 16, L"%.1f / %.1f", yRotDisplay, minecraft->player->xRot); + + int direction = Mth::floor(minecraft->player->yRot * 4.0f / 360.0f + 0.5) & 0x3; + const wchar_t* cardinals[] = { L"south", L"west", L"north", L"east" }; + lines.push_back(L"Facing: " + std::wstring(cardinals[direction]) + L" (" + angleString + L")"); + + if (minecraft->level != NULL && minecraft->level->hasChunkAt(xBlockPos, fmod(yBlockPos, 256), zBlockPos)) + { + LevelChunk *chunkAt = minecraft->level->getChunkAt(xBlockPos, zBlockPos); + if (chunkAt != NULL) + { + int skyLight = chunkAt->getBrightness(LightLayer::Sky, xChunkOffset, yChunkOffset, zChunkOffset); + int blockLight = chunkAt->getBrightness(LightLayer::Block, xChunkOffset, yChunkOffset, zChunkOffset); + int maxLight = fmax(skyLight, blockLight); + lines.push_back(L"Light: " + std::to_wstring(maxLight) + L" (" + std::to_wstring(skyLight) + L" sky, " + std::to_wstring(blockLight) + L" block)"); + lines.push_back(L"CH S: " + std::to_wstring(chunkAt->getHeightmap(xChunkOffset, zChunkOffset))); + Biome *biome = chunkAt->getBiome(xChunkOffset, zChunkOffset, minecraft->level->getBiomeSource()); + lines.push_back(L"Biome: " + biome->m_name + L" (" + std::to_wstring(biome->id) + L")"); + lines.push_back(L"Difficulty: " + std::to_wstring(minecraft->level->difficulty) + L" (Day " + std::to_wstring(minecraft->level->getGameTime() / Level::TICKS_PER_DAY) + L")"); + } + } + + lines.push_back(L""); + lines.push_back(L"Seed: " + std::to_wstring(minecraft->level->getLevelData()->getSeed())); + lines.push_back(minecraft->gatherStats1()); + lines.push_back(minecraft->gatherStats2()); + lines.push_back(minecraft->gatherStats3()); + } + +#ifdef _DEBUG + if (minecraft->options->renderDebug && minecraft->player != nullptr && minecraft->level != nullptr && minecraft->level->dimension->id == 0) + { + wstring wfeature[eTerrainFeature_Count]; + wfeature[eTerrainFeature_Stronghold] = L"Stronghold: "; + wfeature[eTerrainFeature_Mineshaft] = L"Mineshaft: "; + wfeature[eTerrainFeature_Village] = L"Village: "; + wfeature[eTerrainFeature_Ravine] = L"Ravine: "; + + // maxW in font units: physical width divided by font scale + float maxW = (static_cast(g_rScreenWidth) - debugLeft - 8) / fontScale; + float maxWForContent = maxW - static_cast(font->width(L"...")); + bool truncated[eTerrainFeature_Count] = {}; + + for (size_t i = 0; i < app.m_vTerrainFeatures.size(); i++) + { + FEATURE_DATA *pFeatureData = app.m_vTerrainFeatures[i]; + int type = pFeatureData->eTerrainFeature; + if (type < eTerrainFeature_Stronghold || type > eTerrainFeature_Ravine) continue; + if (truncated[type]) continue; + wstring itemInfo = L"[" + std::to_wstring(pFeatureData->x * 16) + L", " + std::to_wstring(pFeatureData->z * 16) + L"] "; + if (font->width(wfeature[type] + itemInfo) <= maxWForContent) + wfeature[type] += itemInfo; + else + { + wfeature[type] += L"..."; + truncated[type] = true; + } + } + + lines.push_back(L""); + for (int i = eTerrainFeature_Stronghold; i <= static_cast(eTerrainFeature_Ravine); i++) + lines.push_back(wfeature[i]); + lines.push_back(L""); + } +#endif + + int yPos = debugTop; + for (const auto &line : lines) + { + drawString(font, line, debugLeft, yPos, 0xffffff); + yPos += 10; + } + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + } + MemSect(0); +#endif + glColor4f(1, 1, 1, 1); glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST); diff --git a/Minecraft.Client/HumanoidMobRenderer.h b/Minecraft.Client/HumanoidMobRenderer.h index 98d8b8dbd1..a9a60ddc2f 100644 --- a/Minecraft.Client/HumanoidMobRenderer.h +++ b/Minecraft.Client/HumanoidMobRenderer.h @@ -30,7 +30,7 @@ class HumanoidMobRenderer : public MobRenderer protected: virtual void createArmorParts(); virtual int prepareArmor(shared_ptr _mob, int layer, float a); - virtual void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); virtual void prepareCarriedItem(shared_ptr mob, shared_ptr item); virtual void additionalRendering(shared_ptr mob, float a); diff --git a/Minecraft.Client/ItemFrameRenderer.h b/Minecraft.Client/ItemFrameRenderer.h index a6eea8f44f..88385e5960 100644 --- a/Minecraft.Client/ItemFrameRenderer.h +++ b/Minecraft.Client/ItemFrameRenderer.h @@ -9,7 +9,7 @@ class ItemFrameRenderer : public EntityRenderer public: void registerTerrainTextures(IconRegister *iconRegister); - virtual void render(shared_ptr _itemframe, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _itemframe, double x, double y, double z, float rot, float a); private: void drawFrame(shared_ptr itemFrame); diff --git a/Minecraft.Client/ItemInHandRenderer.cpp b/Minecraft.Client/ItemInHandRenderer.cpp index 66c922b426..13d4fc20d7 100644 --- a/Minecraft.Client/ItemInHandRenderer.cpp +++ b/Minecraft.Client/ItemInHandRenderer.cpp @@ -228,7 +228,7 @@ void ItemInHandRenderer::renderItem(shared_ptr mob, shared_ptrid]->getColor(item,0); + int col = Item::items[item->id]->getColor(item, layer); float red = ((col >> 16) & 0xff) / 255.0f; float g = ((col >> 8) & 0xff) / 255.0f; float b = ((col) & 0xff) / 255.0f; diff --git a/Minecraft.Client/ItemSpriteRenderer.h b/Minecraft.Client/ItemSpriteRenderer.h index 79499e9406..a632dd951b 100644 --- a/Minecraft.Client/ItemSpriteRenderer.h +++ b/Minecraft.Client/ItemSpriteRenderer.h @@ -11,7 +11,7 @@ class ItemSpriteRenderer : public EntityRenderer public: ItemSpriteRenderer(Item *sourceItem, int sourceItemAuxValue = 0); //ItemSpriteRenderer(Item *icon); - virtual void render(shared_ptr e, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr e, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); private: diff --git a/Minecraft.Client/LeashKnotRenderer.h b/Minecraft.Client/LeashKnotRenderer.h index 6eeca5744c..f54f55a8ff 100644 --- a/Minecraft.Client/LeashKnotRenderer.h +++ b/Minecraft.Client/LeashKnotRenderer.h @@ -12,7 +12,7 @@ class LeashKnotRenderer : public EntityRenderer public: LeashKnotRenderer(); ~LeashKnotRenderer(); - virtual void render(shared_ptr entity, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr entity, double x, double y, double z, float rot, float a); protected: virtual ResourceLocation *getTextureLocation(shared_ptr entity); diff --git a/Minecraft.Client/LevelRenderer.cpp b/Minecraft.Client/LevelRenderer.cpp index cf2937f4fb..5987ddab4e 100644 --- a/Minecraft.Client/LevelRenderer.cpp +++ b/Minecraft.Client/LevelRenderer.cpp @@ -540,6 +540,7 @@ void LevelRenderer::renderEntities(Vec3 *cam, Culler *culler, float a) TileEntityRenderDispatcher::xOff = (player->xOld + (player->x - player->xOld) * a); TileEntityRenderDispatcher::yOff = (player->yOld + (player->y - player->yOld) * a); TileEntityRenderDispatcher::zOff = (player->zOld + (player->z - player->zOld) * a); + EntityRenderDispatcher::instance->beginFrame(); mc->gameRenderer->turnOnLightLayer(a); // 4J - brought forward from 1.8.2 diff --git a/Minecraft.Client/LightningBoltRenderer.h b/Minecraft.Client/LightningBoltRenderer.h index 5a2b33a3ef..fc29839494 100644 --- a/Minecraft.Client/LightningBoltRenderer.h +++ b/Minecraft.Client/LightningBoltRenderer.h @@ -4,5 +4,5 @@ class LightningBoltRenderer : public EntityRenderer { public: - virtual void render(shared_ptr bolt, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr bolt, double x, double y, double z, float rot, float a); }; \ No newline at end of file diff --git a/Minecraft.Client/LivingEntityRenderer.h b/Minecraft.Client/LivingEntityRenderer.h index 2f77e1b54a..f5c4e6b4f2 100644 --- a/Minecraft.Client/LivingEntityRenderer.h +++ b/Minecraft.Client/LivingEntityRenderer.h @@ -20,7 +20,7 @@ class LivingEntityRenderer : public EntityRenderer public: LivingEntityRenderer(Model *model, float shadow); - virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr mob, double x, double y, double z, float rot, float a); virtual void setArmor(Model *armor); private: diff --git a/Minecraft.Client/MinecartRenderer.h b/Minecraft.Client/MinecartRenderer.h index f35092a1c1..8bf5087728 100644 --- a/Minecraft.Client/MinecartRenderer.h +++ b/Minecraft.Client/MinecartRenderer.h @@ -14,7 +14,7 @@ class MinecartRenderer : public EntityRenderer public: MinecartRenderer(); - virtual void render(shared_ptr _cart, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _cart, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); protected: diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index aa8fa1fa3a..11fd81a0d0 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -1629,7 +1629,7 @@ void Minecraft::run_middle() s_prevXButtons[i] = xCurButtons; } bool startJustPressed = s_startPressLatch[i] > 0; - bool tryJoin = !pause && !ui.IsIgnorePlayerJoinMenuDisplayed(ProfileManager.GetPrimaryPad()) && g_NetworkManager.SessionHasSpace() && xCurButtons != 0; + bool tryJoin = !pause && !ui.IsIgnorePlayerJoinMenuDisplayed(ProfileManager.GetPrimaryPad()) && g_NetworkManager.SessionHasSpace() && xCurButtons != 0 && g_KBMInput.IsWindowFocused(); #else bool tryJoin = !pause && !ui.IsIgnorePlayerJoinMenuDisplayed(ProfileManager.GetPrimaryPad()) && g_NetworkManager.SessionHasSpace() && RenderManager.IsHiDef() && InputManager.ButtonPressed(i); #endif @@ -3706,7 +3706,9 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) app.EnableDebugOverlay(options->renderDebug,iPad); #else // 4J Stu - The xbox uses a completely different way of navigating to this scene - ui.NavigateToScene(0, eUIScene_DebugOverlay, nullptr, eUILayer_Debug); + // Always open in the fullscreen group so the overlay spans the full window + // regardless of split-screen viewport configuration. + ui.NavigateToScene(0, eUIScene_DebugOverlay, nullptr, eUILayer_Debug, eUIGroup_Fullscreen); #endif #endif } diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index bdcc9f8138..2cf6930ac9 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -937,7 +937,11 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring storage = shared_ptr(new McRegionLevelStorage(newFormatSave, File(L"."), name, true)); #else - storage = std::make_shared(new ConsoleSaveFileOriginal(L""), File(L"."), name, true); + ConsoleSaveFileOriginal* pSave = new ConsoleSaveFileOriginal(L""); + + pSave->ConvertToLocalPlatform(); + storage = std::make_shared(pSave, File(L"."), name, true); + #endif } diff --git a/Minecraft.Client/MobRenderer.h b/Minecraft.Client/MobRenderer.h index 6ab4af0cc3..b3d7ffbcf9 100644 --- a/Minecraft.Client/MobRenderer.h +++ b/Minecraft.Client/MobRenderer.h @@ -13,7 +13,7 @@ class MobRenderer : public LivingEntityRenderer { public: MobRenderer(Model *model, float shadow); - virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr mob, double x, double y, double z, float rot, float a); protected: virtual bool shouldShowName(shared_ptr mob); diff --git a/Minecraft.Client/MultiPlayerLevel.h b/Minecraft.Client/MultiPlayerLevel.h index a552fc2b10..b7f1640a3a 100644 --- a/Minecraft.Client/MultiPlayerLevel.h +++ b/Minecraft.Client/MultiPlayerLevel.h @@ -12,6 +12,7 @@ using namespace std; class MultiPlayerLevel : public Level { + friend class ClientConnection; private: static const int TICKS_BEFORE_RESET = 20 * 4; diff --git a/Minecraft.Client/MushroomCowRenderer.h b/Minecraft.Client/MushroomCowRenderer.h index 69dc1dd70d..88e75cec45 100644 --- a/Minecraft.Client/MushroomCowRenderer.h +++ b/Minecraft.Client/MushroomCowRenderer.h @@ -9,7 +9,7 @@ class MushroomCowRenderer : public MobRenderer public: MushroomCowRenderer(Model *model, float shadow); - virtual void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); protected: virtual void additionalRendering(shared_ptr _mob, float a); diff --git a/Minecraft.Client/OcelotRenderer.h b/Minecraft.Client/OcelotRenderer.h index b059a79974..20c4cb6014 100644 --- a/Minecraft.Client/OcelotRenderer.h +++ b/Minecraft.Client/OcelotRenderer.h @@ -11,7 +11,7 @@ class OcelotRenderer : public MobRenderer public: OcelotRenderer(Model *model, float shadow); - virtual void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); protected: virtual ResourceLocation *getTextureLocation(shared_ptr entity); diff --git a/Minecraft.Client/PaintingRenderer.h b/Minecraft.Client/PaintingRenderer.h index 42dacd012d..9903472d48 100644 --- a/Minecraft.Client/PaintingRenderer.h +++ b/Minecraft.Client/PaintingRenderer.h @@ -12,7 +12,7 @@ class PaintingRenderer : public EntityRenderer public: PaintingRenderer(); // 4J -added - virtual void render(shared_ptr _painting, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _painting, double x, double y, double z, float rot, float a); private: void renderPainting(shared_ptr painting, int w, int h, int uo, int vo); diff --git a/Minecraft.Client/PigRenderer.h b/Minecraft.Client/PigRenderer.h index b089b6bd9e..277e26e35e 100644 --- a/Minecraft.Client/PigRenderer.h +++ b/Minecraft.Client/PigRenderer.h @@ -14,6 +14,6 @@ class PigRenderer : public MobRenderer virtual int prepareArmor(shared_ptr _pig, int layer, float a); public: - virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); }; \ No newline at end of file diff --git a/Minecraft.Client/PlayerRenderer.h b/Minecraft.Client/PlayerRenderer.h index 494ff795f0..a674263b58 100644 --- a/Minecraft.Client/PlayerRenderer.h +++ b/Minecraft.Client/PlayerRenderer.h @@ -30,7 +30,7 @@ class PlayerRenderer : public LivingEntityRenderer virtual void prepareSecondPassArmor(shared_ptr mob, int layer, float a); public: - virtual void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); protected: virtual void additionalRendering(shared_ptr _mob, float a); diff --git a/Minecraft.Client/SheepRenderer.h b/Minecraft.Client/SheepRenderer.h index 14fe2c02f4..5005b679c2 100644 --- a/Minecraft.Client/SheepRenderer.h +++ b/Minecraft.Client/SheepRenderer.h @@ -14,6 +14,6 @@ class SheepRenderer : public MobRenderer virtual int prepareArmor(shared_ptr _sheep, int layer, float a); public: - virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); }; \ No newline at end of file diff --git a/Minecraft.Client/SilverfishRenderer.h b/Minecraft.Client/SilverfishRenderer.h index 23c899bb50..96ac12d629 100644 --- a/Minecraft.Client/SilverfishRenderer.h +++ b/Minecraft.Client/SilverfishRenderer.h @@ -16,7 +16,7 @@ class SilverfishRenderer : public MobRenderer float getFlipDegrees(shared_ptr spider); public: - virtual void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); protected: diff --git a/Minecraft.Client/SquidRenderer.h b/Minecraft.Client/SquidRenderer.h index 8767844374..d0c301ca79 100644 --- a/Minecraft.Client/SquidRenderer.h +++ b/Minecraft.Client/SquidRenderer.h @@ -8,7 +8,7 @@ class SquidRenderer : public MobRenderer public: SquidRenderer(Model *model, float shadow); - virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr mob, double x, double y, double z, float rot, float a); protected: virtual void setupRotations(shared_ptr _mob, float bob, float bodyRot, float a); diff --git a/Minecraft.Client/TntRenderer.h b/Minecraft.Client/TntRenderer.h index 7aa3fa9e67..4a07cf0359 100644 --- a/Minecraft.Client/TntRenderer.h +++ b/Minecraft.Client/TntRenderer.h @@ -8,6 +8,6 @@ class TntRenderer : public EntityRenderer public: TntRenderer(); - virtual void render(shared_ptr _tnt, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _tnt, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); }; \ No newline at end of file diff --git a/Minecraft.Client/VillagerGolemRenderer.h b/Minecraft.Client/VillagerGolemRenderer.h index e20fb81cd0..a65d4e1622 100644 --- a/Minecraft.Client/VillagerGolemRenderer.h +++ b/Minecraft.Client/VillagerGolemRenderer.h @@ -12,7 +12,7 @@ class VillagerGolemRenderer : public MobRenderer public: VillagerGolemRenderer(); - virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr mob); protected: diff --git a/Minecraft.Client/VillagerRenderer.h b/Minecraft.Client/VillagerRenderer.h index 0114bb03de..be73d7114f 100644 --- a/Minecraft.Client/VillagerRenderer.h +++ b/Minecraft.Client/VillagerRenderer.h @@ -18,7 +18,7 @@ class VillagerRenderer : public MobRenderer public: VillagerRenderer(); - virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr _mob); protected: diff --git a/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp b/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp index 28d2950491..9d73eda8a2 100644 --- a/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp +++ b/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp @@ -392,6 +392,11 @@ bool WinsockNetLayer::JoinGame(const char* ip, int port) } s_localSmallId = assignedSmallId; + // Save the host IP and port so JoinSplitScreen can connect to the same host + // regardless of how the connection was initiated (UI vs command line). + strncpy_s(g_Win64MultiplayerIP, sizeof(g_Win64MultiplayerIP), ip, _TRUNCATE); + g_Win64MultiplayerPort = port; + app.DebugPrintf("Win64 LAN: Connected to %s:%d, assigned smallId=%d\n", ip, port, s_localSmallId); s_active = true; @@ -733,6 +738,11 @@ bool WinsockNetLayer::PopDisconnectedSmallId(BYTE* outSmallId) void WinsockNetLayer::PushFreeSmallId(BYTE smallId) { + // SmallIds 0..(XUSER_MAX_COUNT-1) are permanently reserved for the host's + // local pads and must never be recycled to remote clients. + if (smallId < (BYTE)XUSER_MAX_COUNT) + return; + EnterCriticalSection(&s_freeSmallIdLock); // Guard against double-recycle: the reconnect path (queueSmallIdForRecycle) and // the DoWork disconnect path can both push the same smallId. If we allow duplicates, diff --git a/Minecraft.Client/Windows64Media/DLC/LittleBigPlanet/Skins.pck b/Minecraft.Client/Windows64Media/DLC/LittleBigPlanet/Skins.pck new file mode 100644 index 0000000000..07df720dc0 Binary files /dev/null and b/Minecraft.Client/Windows64Media/DLC/LittleBigPlanet/Skins.pck differ diff --git a/Minecraft.Client/Windows64Media/Media/languages.loc b/Minecraft.Client/Windows64Media/Media/languages.loc index e3d9162b03..5598eda4b7 100644 Binary files a/Minecraft.Client/Windows64Media/Media/languages.loc and b/Minecraft.Client/Windows64Media/Media/languages.loc differ diff --git a/Minecraft.Client/Windows64Media/loc/stringsPlatformSpecific.xml b/Minecraft.Client/Windows64Media/loc/stringsPlatformSpecific.xml index b222769b9d..cc20a840a7 100644 --- a/Minecraft.Client/Windows64Media/loc/stringsPlatformSpecific.xml +++ b/Minecraft.Client/Windows64Media/loc/stringsPlatformSpecific.xml @@ -261,6 +261,9 @@ If you try to save while using the trial version, you will be given the option t Classic + + Infinite + Game Options diff --git a/Minecraft.Client/Windows64Media/strings.h b/Minecraft.Client/Windows64Media/strings.h index 63e3a7f4ee..65f4b7b45a 100644 --- a/Minecraft.Client/Windows64Media/strings.h +++ b/Minecraft.Client/Windows64Media/strings.h @@ -2289,3 +2289,4 @@ #define IDS_RICHPRESENCESTATE_BREWING 2283 #define IDS_RICHPRESENCESTATE_ANVIL 2284 #define IDS_RICHPRESENCESTATE_TRADING 2285 +#define IDS_WORLD_SIZE_TITLE_INFINITE 2286 \ No newline at end of file diff --git a/Minecraft.Client/WitchRenderer.h b/Minecraft.Client/WitchRenderer.h index c221ab3446..e4c86f16ab 100644 --- a/Minecraft.Client/WitchRenderer.h +++ b/Minecraft.Client/WitchRenderer.h @@ -11,7 +11,7 @@ class WitchRenderer : public MobRenderer public: WitchRenderer(); - virtual void render(shared_ptr entity, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr entity, double x, double y, double z, float rot, float a); protected: virtual ResourceLocation *getTextureLocation(shared_ptr entity); diff --git a/Minecraft.Client/WitherBossRenderer.h b/Minecraft.Client/WitherBossRenderer.h index 5e567d11ef..2c0ca78713 100644 --- a/Minecraft.Client/WitherBossRenderer.h +++ b/Minecraft.Client/WitherBossRenderer.h @@ -14,7 +14,7 @@ class WitherBossRenderer : public MobRenderer public: WitherBossRenderer(); - virtual void render(shared_ptr entity, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr entity, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr entity); protected: diff --git a/Minecraft.Client/WitherSkullRenderer.h b/Minecraft.Client/WitherSkullRenderer.h index eaf0f005c6..58793ae23a 100644 --- a/Minecraft.Client/WitherSkullRenderer.h +++ b/Minecraft.Client/WitherSkullRenderer.h @@ -13,7 +13,7 @@ class WitherSkullRenderer : public EntityRenderer public: WitherSkullRenderer(); - void render(shared_ptr entity, double x, double y, double z, float rot, float a); + void render(const shared_ptr entity, double x, double y, double z, float rot, float a); ResourceLocation *getTextureLocation(shared_ptr entity); private: diff --git a/Minecraft.Client/ZombieRenderer.h b/Minecraft.Client/ZombieRenderer.h index c8f110b180..99f7a182a0 100644 --- a/Minecraft.Client/ZombieRenderer.h +++ b/Minecraft.Client/ZombieRenderer.h @@ -31,7 +31,7 @@ class ZombieRenderer : public HumanoidMobRenderer virtual int prepareArmor(shared_ptr _mob, int layer, float a); public: - virtual void render(shared_ptr _mob, double x, double y, double z, float rot, float a); + virtual void render(const shared_ptr _mob, double x, double y, double z, float rot, float a); virtual ResourceLocation *getTextureLocation(shared_ptr entity); protected: diff --git a/Minecraft.Client/redist64/binkawin64.asi b/Minecraft.Client/redist64/binkawin64.asi deleted file mode 100644 index f0574d9d83..0000000000 Binary files a/Minecraft.Client/redist64/binkawin64.asi and /dev/null differ diff --git a/Minecraft.Client/redist64/mss64dolby.flt b/Minecraft.Client/redist64/mss64dolby.flt deleted file mode 100644 index 1842df34be..0000000000 Binary files a/Minecraft.Client/redist64/mss64dolby.flt and /dev/null differ diff --git a/Minecraft.Client/redist64/mss64ds3d.flt b/Minecraft.Client/redist64/mss64ds3d.flt deleted file mode 100644 index 77a0f8aafc..0000000000 Binary files a/Minecraft.Client/redist64/mss64ds3d.flt and /dev/null differ diff --git a/Minecraft.Client/redist64/mss64dsp.flt b/Minecraft.Client/redist64/mss64dsp.flt deleted file mode 100644 index 5b47b314e2..0000000000 Binary files a/Minecraft.Client/redist64/mss64dsp.flt and /dev/null differ diff --git a/Minecraft.Client/redist64/mss64eax.flt b/Minecraft.Client/redist64/mss64eax.flt deleted file mode 100644 index 18d0033db1..0000000000 Binary files a/Minecraft.Client/redist64/mss64eax.flt and /dev/null differ diff --git a/Minecraft.Client/redist64/mss64srs.flt b/Minecraft.Client/redist64/mss64srs.flt deleted file mode 100644 index 9412318aec..0000000000 Binary files a/Minecraft.Client/redist64/mss64srs.flt and /dev/null differ diff --git a/Minecraft.World/BonusChestFeature.cpp b/Minecraft.World/BonusChestFeature.cpp index cd33e60aed..86dc972584 100644 --- a/Minecraft.World/BonusChestFeature.cpp +++ b/Minecraft.World/BonusChestFeature.cpp @@ -24,18 +24,21 @@ bool BonusChestFeature::place(Level *level, Random *random, int x, int y, int z) bool BonusChestFeature::place(Level *level, Random *random, int x, int y, int z, bool force) { - if( !force ) + //Will only spawn a bonus chest if the world is new and has never been saved. + if (level->isNew) { - int t = 0; - while (((t = level->getTile(x, y, z)) == 0 || t == Tile::leaves_Id) && y > 1) + if( !force ) + { + int t = 0; + while (((t = level->getTile(x, y, z)) == 0 || t == Tile::leaves_Id) && y > 1) y--; - if (y < 1) - { - return false; + if (y < 1) + { + return false; + } + y++; } - y++; - } for (int i = 0; i < 4; i++) { @@ -85,4 +88,6 @@ bool BonusChestFeature::place(Level *level, Random *random, int x, int y, int z, } return false; + + } } diff --git a/Minecraft.World/ButtonTile.cpp b/Minecraft.World/ButtonTile.cpp index b05d597d17..33bec683eb 100644 --- a/Minecraft.World/ButtonTile.cpp +++ b/Minecraft.World/ButtonTile.cpp @@ -46,11 +46,13 @@ bool ButtonTile::isCubeShaped() bool ButtonTile::mayPlace(Level *level, int x, int y, int z, int face) { + if (face == 0 && level->isSolidBlockingTile(x, y + 1, z)) return true; // STARSEED- support for ceiling button placement + if (face == 1 && level->isSolidBlockingTile(x, y - 1, z)) return true; // STARSEED- support for floor button placement if (face == 2 && level->isSolidBlockingTile(x, y, z + 1)) return true; if (face == 3 && level->isSolidBlockingTile(x, y, z - 1)) return true; if (face == 4 && level->isSolidBlockingTile(x + 1, y, z)) return true; if (face == 5 && level->isSolidBlockingTile(x - 1, y, z)) return true; - return false; + return false; } bool ButtonTile::mayPlace(Level *level, int x, int y, int z) @@ -71,23 +73,67 @@ bool ButtonTile::mayPlace(Level *level, int x, int y, int z) { return true; } + if (level->isSolidBlockingTile(x, y - 1, z)) + { + return true; // STARSEED- floor + } + if (level->isSolidBlockingTile(x, y + 1, z)) + { + return true; // STARSEED- ceiling + } return false; } - +shared_ptr ButtonTile::lastPlayer; int ButtonTile::getPlacedOnFaceDataValue(Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue) { - int dir = level->getData(x, y, z); - - int oldFlip = dir & 8; - dir &= 7; + int dir = level->getData(x, y, z); - if (face == 2 && level->isSolidBlockingTile(x, y, z + 1)) dir = 4; - else if (face == 3 && level->isSolidBlockingTile(x, y, z - 1)) dir = 3; - else if (face == 4 && level->isSolidBlockingTile(x + 1, y, z)) dir = 2; - else if (face == 5 && level->isSolidBlockingTile(x - 1, y, z)) dir = 1; - else dir = findFace(level, x, y, z); + int oldFlip = dir & 8; + dir &= 7; - return dir + oldFlip; + if (face == 0 && level->isSolidBlockingTile(x, y + 1, z)) + { + int rot = 0; + + if (lastPlayer) + { + rot = (int)(lastPlayer->yRot * 4.0f / 360.0f + 0.5f) & 3; + } + + if (rot == 0 || rot == 2) + { + dir = 0; // ceiling northsouth + } + else + { + dir = 7; // ceiling eastwest + } + } + else if (face == 1 && level->isSolidBlockingTile(x, y - 1, z)) + { + int rot = 0; + + if (lastPlayer) + { + rot = (int)(lastPlayer->yRot * 4.0f / 360.0f + 0.5f) & 3; + } + + if (rot == 0 || rot == 2) + { + dir = 5; // floor northsouth + } + else + { + dir = 6; // floor eastwest + } + } + else if (face == 2 && level->isSolidBlockingTile(x, y, z + 1)) dir = 4; + else if (face == 3 && level->isSolidBlockingTile(x, y, z - 1)) dir = 3; + else if (face == 4 && level->isSolidBlockingTile(x + 1, y, z)) dir = 2; + else if (face == 5 && level->isSolidBlockingTile(x - 1, y, z)) dir = 1; + else dir = findFace(level, x, y, z); + + return dir + oldFlip; } int ButtonTile::findFace(Level *level, int x, int y, int z) @@ -108,6 +154,14 @@ int ButtonTile::findFace(Level *level, int x, int y, int z) { return 4; } + if (level->isSolidBlockingTile(x, y - 1, z)) //STARSEED- floor/ceiling + { + return 5; + } + if (level->isSolidBlockingTile(x, y + 1, z)) // STARSEED- floor/ceiling + { + return 0; + } return 1; } @@ -122,6 +176,9 @@ void ButtonTile::neighborChanged(Level *level, int x, int y, int z, int type) if (!level->isSolidBlockingTile(x + 1, y, z) && dir == 2) replace = true; if (!level->isSolidBlockingTile(x, y, z - 1) && dir == 3) replace = true; if (!level->isSolidBlockingTile(x, y, z + 1) && dir == 4) replace = true; + if (!level->isSolidBlockingTile(x, y - 1, z) && dir == 5) replace = true; // STARSEED- support for floor/ceiling + if (!level->isSolidBlockingTile(x, y + 1, z) && dir == 0) replace = true; // STARSEED- support for floor/ceiling + if (replace) { @@ -175,6 +232,22 @@ void ButtonTile::updateShape(int data) { setShape(0.5f - r, h0, 1 - d, 0.5f + r, h1, 1); } + else if (dir == 5) // STARSEED- bounding box for floor and correct shape + { + setShape(0.5f - r, 0, 0.5f - (h1 - h0) / 2, 0.5f + r, d, 0.5f + (h1 - h0) / 2); + } + else if (dir == 6) // STARSEED- rotated floor + { + setShape(0.5f - (h1 - h0) / 2, 0, 0.5f - r, 0.5f + (h1 - h0) / 2, d, 0.5f + r); + } + else if (dir == 0) // STARSEED- bounding box for ceiling and correct shape + { + setShape(0.5f - r, 1 - d, 0.5f - (h1 - h0) / 2, 0.5f + r, 1, 0.5f + (h1 - h0) / 2); + } + else if (dir == 7) // STARSEED- rotated ceiling + { + setShape(0.5f - (h1 - h0) / 2, 1 - d, 0.5f - r, 0.5f + (h1 - h0) / 2, 1, 0.5f + r); + } } void ButtonTile::attack(Level *level, int x, int y, int z, shared_ptr player) @@ -240,6 +313,8 @@ int ButtonTile::getDirectSignal(LevelSource *level, int x, int y, int z, int dir if (myDir == 3 && dir == 3) return Redstone::SIGNAL_MAX; if (myDir == 2 && dir == 4) return Redstone::SIGNAL_MAX; if (myDir == 1 && dir == 5) return Redstone::SIGNAL_MAX; + if (myDir == 5 && dir == 0) return Redstone::SIGNAL_MAX; // STARSEED- floor + if (myDir == 0 && dir == 1) return Redstone::SIGNAL_MAX; // STARSEED- ceiling return false; } @@ -350,10 +425,14 @@ void ButtonTile::updateNeighbours(Level *level, int x, int y, int z, int dir) { level->updateNeighborsAt(x, y, z + 1, id); } - else - { - level->updateNeighborsAt(x, y - 1, z, id); - } + else if (dir == 5) // STARSEED- floor + { + level->updateNeighborsAt(x, y - 1, z, id); + } + else if (dir == 0) // STARSEED- ceiling + { + level->updateNeighborsAt(x, y + 1, z, id); + } } bool ButtonTile::shouldTileTick(Level *level, int x,int y,int z) diff --git a/Minecraft.World/ButtonTile.h b/Minecraft.World/ButtonTile.h index 96c49cdfb2..589e226124 100644 --- a/Minecraft.World/ButtonTile.h +++ b/Minecraft.World/ButtonTile.h @@ -17,6 +17,7 @@ class ButtonTile : public Tile ButtonTile(int id, bool sensitive); public: + static shared_ptr lastPlayer; Icon *getTexture(int face, int data); virtual AABB *getAABB(Level *level, int x, int y, int z); virtual int getTickDelay(Level *level); diff --git a/Minecraft.World/ChunkSource.h b/Minecraft.World/ChunkSource.h index 37b0ecc33e..ffbb29efd4 100644 --- a/Minecraft.World/ChunkSource.h +++ b/Minecraft.World/ChunkSource.h @@ -7,13 +7,14 @@ class TilePos; // The maximum number of chunks that we can store #ifdef _LARGE_WORLDS // 4J Stu - Our default map (at zoom level 3) is 1024x1024 blocks (or 64 chunks) -#define LEVEL_MAX_WIDTH (5*64) //(6*54) +//#define LEVEL_MAX_WIDTH (29999984 / 16) //1,874,999 chunks +#define LEVEL_MAX_WIDTH (6 * 64) // Keep renderer sane #define LEVEL_WIDTH_CLASSIC 54 #define LEVEL_WIDTH_SMALL 64 #define LEVEL_WIDTH_MEDIUM (3*64) #define LEVEL_WIDTH_LARGE (5*64) - +#define LEVEL_WIDTH_INFINITE (29999984 / 16) // Infinite World Size #else #define LEVEL_MAX_WIDTH 54 #endif @@ -31,6 +32,7 @@ class TilePos; #define HELL_LEVEL_SCALE_SMALL 3 #define HELL_LEVEL_SCALE_MEDIUM 6 #define HELL_LEVEL_SCALE_LARGE 8 +#define HELL_LEVEL_SCALE_INFINITE 8 #else #define HELL_LEVEL_MAX_SCALE 3 diff --git a/Minecraft.World/ConsoleSaveFileOutputStream.cpp b/Minecraft.World/ConsoleSaveFileOutputStream.cpp index c4812a7347..8d05ee60c0 100644 --- a/Minecraft.World/ConsoleSaveFileOutputStream.cpp +++ b/Minecraft.World/ConsoleSaveFileOutputStream.cpp @@ -66,7 +66,7 @@ void ConsoleSaveFileOutputStream::write(byteArray b) BOOL result = m_saveFile->writeFile( m_file, - &b.data, // data buffer + b.data, // data buffer b.length, // number of bytes to write &numberOfBytesWritten // number of bytes written ); diff --git a/Minecraft.World/EnderMan.cpp b/Minecraft.World/EnderMan.cpp index e123181870..da469a3a22 100644 --- a/Minecraft.World/EnderMan.cpp +++ b/Minecraft.World/EnderMan.cpp @@ -410,9 +410,14 @@ bool EnderMan::hurt(DamageSource *source, float damage) if ( dynamic_cast(source) != nullptr && source->getEntity()->instanceof(eTYPE_PLAYER)) { - aggroedByPlayer = true; + if (!dynamic_pointer_cast(source->getEntity())->abilities.invulnerable) + { + aggroedByPlayer = true; + } + else setCreepy(false); } + if (dynamic_cast(source) != nullptr) { aggroedByPlayer = false; diff --git a/Minecraft.World/EntityHorse.cpp b/Minecraft.World/EntityHorse.cpp index 32c9eb2de6..0bf5bc080c 100644 --- a/Minecraft.World/EntityHorse.cpp +++ b/Minecraft.World/EntityHorse.cpp @@ -515,6 +515,15 @@ bool EntityHorse::canSpawn() return Animal::canSpawn(); } +bool EntityHorse::removeWhenFarAway() +{ + if (isTamed()) return false; + if (isSaddled()) return false; + if (isLeashed()) return false; + if (getArmorType() > 0) return false; + return Animal::removeWhenFarAway(); +} + shared_ptr EntityHorse::getClosestMommy(shared_ptr baby, double searchRadius) { diff --git a/Minecraft.World/EntityHorse.h b/Minecraft.World/EntityHorse.h index c2784491af..c91da172a3 100644 --- a/Minecraft.World/EntityHorse.h +++ b/Minecraft.World/EntityHorse.h @@ -192,6 +192,7 @@ class EntityHorse : public Animal, public net_minecraft_world::ContainerListener public: virtual void containerChanged(); virtual bool canSpawn(); + virtual bool removeWhenFarAway() override; protected: virtual shared_ptr getClosestMommy(shared_ptr baby, double searchRadius); diff --git a/Minecraft.World/LevelChunk.cpp b/Minecraft.World/LevelChunk.cpp index 118dbcdda0..584e3df10d 100644 --- a/Minecraft.World/LevelChunk.cpp +++ b/Minecraft.World/LevelChunk.cpp @@ -1222,6 +1222,30 @@ void LevelChunk::addEntity(shared_ptr e) #endif } +void LevelChunk::addRidingEntities(shared_ptr rider, CompoundTag *riderTag) +{ +#ifdef _LARGE_WORLDS #This shouldnt be called when we dont have large worlds enabled + CompoundTag *mountTag = riderTag; + shared_ptr ridingEntity = rider; + + while (mountTag != NULL && mountTag->contains(Entity::RIDING_TAG)) + { + CompoundTag *nextMountTag = mountTag->getCompound(Entity::RIDING_TAG); + shared_ptr mount = EntityIO::loadStatic(nextMountTag, level); + if (mount == NULL) + { + break; + } + + mount->onLoadedFromSave(); + addEntity(mount); + ridingEntity->ride(mount); + + ridingEntity = mount; + mountTag = nextMountTag; + } +#endif +}; void LevelChunk::removeEntity(shared_ptr e) { @@ -1431,6 +1455,7 @@ void LevelChunk::load() { ent->onLoadedFromSave(); addEntity(ent); + addRidingEntities(ent, teTag); } } } @@ -1628,18 +1653,18 @@ void LevelChunk::getEntities(shared_ptr except, AABB *bb, vectorbb->intersects(bb) && (selector == nullptr || selector->matches(e))) + if (e && e != except && e->bb->intersects(bb) && (selector == nullptr || selector->matches(e))) { es.push_back(e); + vector > *subs = e->getSubEntities(); if (subs != nullptr) { - for (const auto& sub : *subs) + for (const auto& subEntity : *subs) { - e = sub; - if ( e && e != except && e->bb->intersects(bb) && (selector == nullptr || selector->matches(e))) + if (subEntity && subEntity != except && subEntity->bb->intersects(bb) && (selector == nullptr || selector->matches(subEntity))) { - es.push_back(e); + es.push_back(subEntity); } } } diff --git a/Minecraft.World/LevelChunk.h b/Minecraft.World/LevelChunk.h index fdb2ba6c2f..bd2b3b910d 100644 --- a/Minecraft.World/LevelChunk.h +++ b/Minecraft.World/LevelChunk.h @@ -192,6 +192,7 @@ class LevelChunk virtual void setBrightness(LightLayer::variety layer, int x, int y, int z, int brightness); virtual int getRawBrightness(int x, int y, int z, int skyDampen); virtual void addEntity(shared_ptr e); + virtual void addRidingEntities(shared_ptr rider, CompoundTag *riderTag); virtual void removeEntity(shared_ptr e); virtual void removeEntity(shared_ptr e, int yc); virtual bool isSkyLit(int x, int y, int z); diff --git a/Minecraft.World/LevelData.cpp b/Minecraft.World/LevelData.cpp index fbc10ddb13..e689524377 100644 --- a/Minecraft.World/LevelData.cpp +++ b/Minecraft.World/LevelData.cpp @@ -145,6 +145,7 @@ LevelData::LevelData(CompoundTag *tag) case LEVEL_WIDTH_CLASSIC: m_classicEdgeMoat = bUseMoat; break; case LEVEL_WIDTH_SMALL: m_smallEdgeMoat = bUseMoat; break; case LEVEL_WIDTH_MEDIUM: m_mediumEdgeMoat = bUseMoat; break; + case LEVEL_WIDTH_LARGE: break; default: assert(0); break; } assert(newWorldSize > m_xzSize); @@ -176,6 +177,7 @@ LevelData::LevelData(CompoundTag *tag) case LEVEL_WIDTH_SMALL: hostOptionworldSize = e_worldSize_Small; break; case LEVEL_WIDTH_MEDIUM: hostOptionworldSize = e_worldSize_Medium; break; case LEVEL_WIDTH_LARGE: hostOptionworldSize = e_worldSize_Large; break; + case LEVEL_WIDTH_INFINITE: hostOptionworldSize = e_worldSize_Infinite; break; default: assert(0); break; } app.SetGameHostOption(eGameHostOption_WorldSize, hostOptionworldSize ); diff --git a/Minecraft.World/LivingEntity.cpp b/Minecraft.World/LivingEntity.cpp index 3ace880685..3af9efe962 100644 --- a/Minecraft.World/LivingEntity.cpp +++ b/Minecraft.World/LivingEntity.cpp @@ -1354,6 +1354,10 @@ bool LivingEntity::shouldShowName() Icon *LivingEntity::getItemInHandIcon(shared_ptr item, int layer) { + if (item->getItem()->hasMultipleSpriteLayers()) + { + return item->getItem()->getLayerIcon(item->getAuxValue(), layer); + } return item->getIcon(); } @@ -1999,4 +2003,4 @@ bool LivingEntity::isAlliedTo(Team *other) return getTeam()->isAlliedTo(other); } return false; -} \ No newline at end of file +} diff --git a/Minecraft.World/MinecartTNT.cpp b/Minecraft.World/MinecartTNT.cpp index 6e72d66b7a..18681aa46c 100644 --- a/Minecraft.World/MinecartTNT.cpp +++ b/Minecraft.World/MinecartTNT.cpp @@ -64,28 +64,34 @@ void MinecartTNT::destroy(DamageSource *source) double speedSqr = xd * xd + zd * zd; - if (!source->isExplosion()) + if (!app.GetGameHostOption(eGameHostOption_TNT) || !source->isExplosion()) { - spawnAtLocation(std::make_shared(Tile::tnt, 1), 0); + spawnAtLocation( shared_ptr( new ItemInstance(Tile::tnt, 1) ), 0); } - if (source->isFire() || source->isExplosion() || speedSqr >= 0.01f) + if (app.GetGameHostOption(eGameHostOption_TNT)) { - explode(speedSqr); + if (source->isFire() || source->isExplosion() || speedSqr >= 0.01f) + { + explode(speedSqr); + } } } void MinecartTNT::explode(double speedSqr) { + if (!app.GetGameHostOption(eGameHostOption_TNT)) + { + remove(); + return; + } + if (!level->isClientSide) { double speed = sqrt(speedSqr); - if (speed > 5.0) speed = 5.0; - if (app.GetGameHostOption(eGameHostOption_TNT)) - { - level->explode(shared_from_this(), x, y, z, static_cast(4 + random->nextDouble() * 1.5f * speed), true); - remove(); - } + if (speed > 5) speed = 5; + level->explode(shared_from_this(), x, y, z, (float) (4 + random->nextDouble() * 1.5f * speed), true); + remove(); } } @@ -122,12 +128,15 @@ void MinecartTNT::handleEntityEvent(byte eventId) void MinecartTNT::primeFuse() { - fuse = 80; - - if (!level->isClientSide) + if (app.GetGameHostOption(eGameHostOption_TNT)) { - level->broadcastEntityEvent(shared_from_this(), EVENT_PRIME); - level->playEntitySound(shared_from_this(), eSoundType_RANDOM_FUSE, 1, 1.0f); + fuse = 80; + + if (!level->isClientSide) + { + level->broadcastEntityEvent(shared_from_this(), EVENT_PRIME); + level->playEntitySound(shared_from_this(), eSoundType_RANDOM_FUSE, 1, 1.0f); + } } } diff --git a/Minecraft.World/Monster.cpp b/Minecraft.World/Monster.cpp index 2de4531538..ad19a36d4d 100644 --- a/Minecraft.World/Monster.cpp +++ b/Minecraft.World/Monster.cpp @@ -60,7 +60,14 @@ bool Monster::hurt(DamageSource *source, float dmg) if (sourceEntity != shared_from_this()) { - attackTarget = sourceEntity; + if (sourceEntity->instanceof(eTYPE_PLAYER)) + { + if (!dynamic_pointer_cast(sourceEntity)->abilities.invulnerable) + { + attackTarget = sourceEntity; + } + } + else attackTarget = sourceEntity; } return true; } diff --git a/Minecraft.World/OldChunkStorage.cpp b/Minecraft.World/OldChunkStorage.cpp index 9a8822fa4b..15b4c734c9 100644 --- a/Minecraft.World/OldChunkStorage.cpp +++ b/Minecraft.World/OldChunkStorage.cpp @@ -403,6 +403,7 @@ void OldChunkStorage::loadEntities(LevelChunk *lc, Level *level, CompoundTag *ta if (te != nullptr) { lc->addEntity(te); + lc->addRidingEntities(te, teTag); } } } diff --git a/Minecraft.World/PathfinderMob.cpp b/Minecraft.World/PathfinderMob.cpp index 840a602083..983494bee5 100644 --- a/Minecraft.World/PathfinderMob.cpp +++ b/Minecraft.World/PathfinderMob.cpp @@ -40,6 +40,7 @@ PathfinderMob::~PathfinderMob() void PathfinderMob::serverAiStep() { + auto self = shared_from_this(); if (fleeTime > 0) { if (--fleeTime == 0) @@ -56,14 +57,14 @@ void PathfinderMob::serverAiStep() attackTarget = findAttackTarget(); if (attackTarget != nullptr) { - setPath(level->findPath(shared_from_this(), attackTarget, maxDist, true, false, false, true)); // 4J - changed to setPath from path = + setPath(level->findPath(self, attackTarget, maxDist, true, false, false, true)); // 4J - changed to setPath from path = } } else { if (attackTarget->isAlive()) { - float d = attackTarget->distanceTo(shared_from_this()); + float d = attackTarget->distanceTo(self); if (canSee(attackTarget)) { checkHurtTarget(attackTarget, d); @@ -86,7 +87,7 @@ void PathfinderMob::serverAiStep() if (!holdGround && (attackTarget != nullptr && (path == nullptr || random->nextInt(20) == 0))) { - setPath(level->findPath(shared_from_this(), attackTarget, maxDist, true, false, false, true));// 4J - changed to setPath from path = + setPath(level->findPath(self, attackTarget, maxDist, true, false, false, true));// 4J - changed to setPath from path = } else if (!holdGround && ((path == nullptr && (random->nextInt(180) == 0) || fleeTime > 0) || (random->nextInt(120) == 0 || fleeTime > 0))) { @@ -111,18 +112,17 @@ void PathfinderMob::serverAiStep() considerForExtraWandering( isDespawnProtected() ); int yFloor = Mth::floor(bb->y0 + 0.5f); - + xRot = 0; + if (path == nullptr || random->nextInt(100) == 0) + { + this->Mob::serverAiStep(); + setPath(nullptr); // 4J - changed to setPath from path = + return; + } bool inWater = isInWater(); bool inLava = isInLava(); - xRot = 0; - if (path == nullptr || random->nextInt(100) == 0) - { - this->Mob::serverAiStep(); - setPath(nullptr);// 4J - changed to setPath from path = - return; - } - Vec3 *target = path->currentPos(shared_from_this()); + Vec3 *target = path->currentPos(self); double r = bbWidth * 2; while (target != nullptr && target->distanceToSqr(x, target->y, z) < r * r) { @@ -132,7 +132,7 @@ void PathfinderMob::serverAiStep() target = nullptr; setPath(nullptr); // 4J - changed to setPath from path = } - else target = path->currentPos(shared_from_this()); + else target = path->currentPos(self); } jumping = false; @@ -221,7 +221,7 @@ void PathfinderMob::findRandomStrollLocation(int quadrant/*=-1*/) // 4J - added } if (hasBest) { - setPath(level->findPath(shared_from_this(), xBest, yBest, zBest, 10, true, false, false, true)); // 4J - changed to setPath from path = + setPath(level->findPath(shared_from_this(), xBest, yBest, zBest, 10, true, false, false, true)); // 4J - changed to setPath from path = } } diff --git a/Minecraft.World/RegionFileCache.cpp b/Minecraft.World/RegionFileCache.cpp index ab0492b489..bd6405fa32 100644 --- a/Minecraft.World/RegionFileCache.cpp +++ b/Minecraft.World/RegionFileCache.cpp @@ -12,6 +12,11 @@ bool RegionFileCache::useSplitSaves(ESavePlatform platform) case SAVE_FILE_PLATFORM_XBONE: case SAVE_FILE_PLATFORM_PS4: return true; + case SAVE_FILE_PLATFORM_WIN64: + { + LevelGenerationOptions* lgo = app.getLevelGenerationOptions(); + return (lgo != nullptr && lgo->isFromDLC()); + } default: return false; }; diff --git a/Minecraft.World/TileItem.cpp b/Minecraft.World/TileItem.cpp index 8d22594db6..77a2d279cd 100644 --- a/Minecraft.World/TileItem.cpp +++ b/Minecraft.World/TileItem.cpp @@ -82,6 +82,7 @@ bool TileItem::useOn(shared_ptr instance, shared_ptr playe Tile *tile = Tile::tiles[tileId]; // 4J - Adding this from 1.6 int itemValue = getLevelDataForAuxValue(instance->getAuxValue()); + ButtonTile::lastPlayer = player; // STARSEED- used for retrieving player rotation int dataValue = Tile::tiles[tileId]->getPlacedOnFaceDataValue(level, x, y, z, face, clickX, clickY, clickZ, itemValue); if (level->setTileAndData(x, y, z, tileId, dataValue, Tile::UPDATE_ALL)) { diff --git a/Minecraft.World/ZonedChunkStorage.cpp b/Minecraft.World/ZonedChunkStorage.cpp index 1902324238..75df6a0c3c 100644 --- a/Minecraft.World/ZonedChunkStorage.cpp +++ b/Minecraft.World/ZonedChunkStorage.cpp @@ -194,7 +194,11 @@ void ZonedChunkStorage::loadEntities(Level *level, LevelChunk *lc) if (type == 0) { shared_ptr e = EntityIO::loadStatic(tag, level); - if (e != nullptr) lc->addEntity(e); + if (e != nullptr) + { + lc->addEntity(e); + lc->addRidingEntities(e, tag); + } } else if (type == 1) { diff --git a/README.md b/README.md index 122157ba87..0c476666e5 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,10 @@ ## Introduction -This project contains the source code of Minecraft Legacy Console Edition v1.6.0560.0 (TU19) from https://archive.org/details/minecraft-legacy-console-edition-source-code, with some fixes and improvements applied. +This project contains the source code of Minecraft Legacy Console Edition v1.6.0560.0 (TU19) with some fixes and improvements applied. ## Download -Windows users can download our [Nightly Build](https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly)! Simply download the `.zip` file and extract it to a folder where you'd like to keep the game. You can set your username in `username.txt` (you'll have to make this file) and add servers to connect to in `servers.txt` +Windows users can download our [Nightly Build](https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly)! Simply download the `.zip` file and extract it to a folder where you'd like to keep the game. You can set your username in `username.txt` (you'll have to make this file) ## Platform Support @@ -35,30 +35,11 @@ Basic LAN multiplayer is available on the Windows build - Other players on the same LAN can discover the session from the in-game Join Game menu - Game connections use TCP port `25565` by default - LAN discovery uses UDP port `25566` -- Add servers to your server list with `servers.txt` (temp solution) +- Add servers to your server list with the in-game Add Server button (temp) - Rename yourself without losing data by keeping your `uid.dat` Parts of this feature are based on code from [LCEMP](https://github.com/LCEMP/LCEMP) (thanks!) -### servers.txt - -To add a server to your game, create the `servers.txt` file in the same directory as you have `Minecraft.Client.exe`. Inside, follow this format: -``` -serverip.example.com -25565 -The name of your server in UI! -``` - -For example, here's a valid servers.txt -``` -1.1.1.1 -25565 -Cloudflare's Very Own LCE Server -127.0.0.1 -25565 -Localhost Test Crap -``` - ### Launch Arguments | Argument | Description | @@ -100,7 +81,7 @@ Minecraft.Client.exe -name Steve -fullscreen 2. Clone the repository. 3. Open the project by double-clicking `MinecraftConsoles.sln`. 4. Make sure `Minecraft.Client` is set as the Startup Project. -5. Set the build configuration to **Debug** (Release is also OK but has some bugs) and the target platform to **Windows64**, then build and run. +5. Set the build configuration to **Debug** (Release is also ok but missing some debug features) and the target platform to **Windows64**, then build and run. ### CMake (Windows x64) diff --git a/x64/Debug/Effects.msscmp b/x64/Debug/Effects.msscmp deleted file mode 100644 index 8eb4b9155d..0000000000 Binary files a/x64/Debug/Effects.msscmp and /dev/null differ diff --git a/x64/Debug/redist64/binkawin64.asi b/x64/Debug/redist64/binkawin64.asi deleted file mode 100644 index d363b31db5..0000000000 Binary files a/x64/Debug/redist64/binkawin64.asi and /dev/null differ diff --git a/x64/Debug/redist64/mss64dolby.flt b/x64/Debug/redist64/mss64dolby.flt deleted file mode 100644 index 7e9eb6054a..0000000000 Binary files a/x64/Debug/redist64/mss64dolby.flt and /dev/null differ diff --git a/x64/Debug/redist64/mss64ds3d.flt b/x64/Debug/redist64/mss64ds3d.flt deleted file mode 100644 index c6a6a1252f..0000000000 Binary files a/x64/Debug/redist64/mss64ds3d.flt and /dev/null differ diff --git a/x64/Debug/redist64/mss64dsp.flt b/x64/Debug/redist64/mss64dsp.flt deleted file mode 100644 index 28caa28e9e..0000000000 Binary files a/x64/Debug/redist64/mss64dsp.flt and /dev/null differ diff --git a/x64/Debug/redist64/mss64eax.flt b/x64/Debug/redist64/mss64eax.flt deleted file mode 100644 index c91b6e1632..0000000000 Binary files a/x64/Debug/redist64/mss64eax.flt and /dev/null differ diff --git a/x64/Debug/redist64/mss64srs.flt b/x64/Debug/redist64/mss64srs.flt deleted file mode 100644 index 01baef15ab..0000000000 Binary files a/x64/Debug/redist64/mss64srs.flt and /dev/null differ diff --git a/x64/Release/Effects.msscmp b/x64/Release/Effects.msscmp deleted file mode 100644 index 8eb4b9155d..0000000000 Binary files a/x64/Release/Effects.msscmp and /dev/null differ diff --git a/x64/Release/redist64/binkawin64.asi b/x64/Release/redist64/binkawin64.asi deleted file mode 100644 index d363b31db5..0000000000 Binary files a/x64/Release/redist64/binkawin64.asi and /dev/null differ diff --git a/x64/Release/redist64/mss64dolby.flt b/x64/Release/redist64/mss64dolby.flt deleted file mode 100644 index 7e9eb6054a..0000000000 Binary files a/x64/Release/redist64/mss64dolby.flt and /dev/null differ diff --git a/x64/Release/redist64/mss64ds3d.flt b/x64/Release/redist64/mss64ds3d.flt deleted file mode 100644 index c6a6a1252f..0000000000 Binary files a/x64/Release/redist64/mss64ds3d.flt and /dev/null differ diff --git a/x64/Release/redist64/mss64dsp.flt b/x64/Release/redist64/mss64dsp.flt deleted file mode 100644 index 28caa28e9e..0000000000 Binary files a/x64/Release/redist64/mss64dsp.flt and /dev/null differ diff --git a/x64/Release/redist64/mss64eax.flt b/x64/Release/redist64/mss64eax.flt deleted file mode 100644 index c91b6e1632..0000000000 Binary files a/x64/Release/redist64/mss64eax.flt and /dev/null differ diff --git a/x64/Release/redist64/mss64srs.flt b/x64/Release/redist64/mss64srs.flt deleted file mode 100644 index 01baef15ab..0000000000 Binary files a/x64/Release/redist64/mss64srs.flt and /dev/null differ