From bc6013ab709804f9d3ffb850c6137ec9049b6f58 Mon Sep 17 00:00:00 2001 From: MatthewBeshay <92357869+MatthewBeshay@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:45:55 +1100 Subject: [PATCH 1/7] Replace all CRITICAL_SECTION usage with std::mutex and std::lock_guard Migrates 59 files from WinAPI CRITICAL_SECTION to portable C++ std::mutex/std::lock_guard/std::unique_lock. Removes Linux CRITICAL_SECTION shims from winapi_stubs.h. --- Minecraft.Client/Level/MultiPlayerLevel.cpp | 142 ++++++------- Minecraft.Client/Level/ServerLevel.cpp | 194 +++++++----------- Minecraft.Client/Level/ServerLevel.h | 9 +- Minecraft.Client/Minecraft.cpp | 9 +- Minecraft.Client/Minecraft.h | 3 +- Minecraft.Client/MinecraftServer.cpp | 71 +++---- Minecraft.Client/MinecraftServer.h | 3 +- .../Network/MultiPlayerChunkCache.cpp | 19 +- .../Network/MultiPlayerChunkCache.h | 3 +- Minecraft.Client/Network/PlayerConnection.cpp | 10 +- Minecraft.Client/Network/PlayerConnection.h | 3 +- Minecraft.Client/Network/PlayerList.cpp | 20 +- Minecraft.Client/Network/PlayerList.h | 5 +- Minecraft.Client/Network/ServerChunkCache.cpp | 20 +- Minecraft.Client/Network/ServerChunkCache.h | 3 +- Minecraft.Client/Network/ServerConnection.cpp | 22 +- Minecraft.Client/Network/ServerConnection.h | 3 +- .../Platform/Common/C4JMemoryPool.h | 6 - .../Platform/Common/Consoles_App.cpp | 118 ++++------- .../Platform/Common/Consoles_App.h | 17 +- .../Leaderboards/SonyLeaderboardManager.cpp | 27 ++- .../Leaderboards/SonyLeaderboardManager.h | 3 +- .../Common/UI/UIComponent_Panorama.cpp | 30 +-- .../Platform/Common/UI/UIController.cpp | 71 +++---- .../Platform/Common/UI/UIController.h | 9 +- .../Platform/Common/UI/UIScene.cpp | 12 +- .../Platform/Linux/Linux_Minecraft.cpp | 81 ++++---- .../Platform/Linux/Stubs/winapi_stubs.h | 40 ---- .../Windows64/Windows64_Minecraft.cpp | 81 ++++---- Minecraft.Client/Rendering/Chunk.cpp | 91 ++++---- Minecraft.Client/Rendering/Chunk.h | 4 +- .../EntityRenderers/ProgressRenderer.cpp | 69 ++++--- .../EntityRenderers/ProgressRenderer.h | 3 +- Minecraft.Client/Rendering/GameRenderer.cpp | 47 ++--- Minecraft.Client/Rendering/GameRenderer.h | 3 +- Minecraft.Client/Rendering/LevelRenderer.cpp | 105 ++++------ Minecraft.Client/Rendering/LevelRenderer.h | 9 +- .../IO/Files/ConsoleSaveFileOriginal.cpp | 4 +- .../IO/Files/ConsoleSaveFileOriginal.h | 3 +- .../IO/Files/ConsoleSaveFileSplit.cpp | 6 +- .../IO/Files/ConsoleSaveFileSplit.h | 3 +- Minecraft.World/IO/Streams/Compression.cpp | 21 +- Minecraft.World/IO/Streams/Compression.h | 5 +- Minecraft.World/Level/Level.cpp | 83 ++++---- Minecraft.World/Level/Level.h | 7 +- Minecraft.World/Level/LevelChunk.cpp | 127 +++++------- Minecraft.World/Level/LevelChunk.h | 8 +- .../Level/Storage/CompressedTileStorage.cpp | 26 +-- .../Level/Storage/CompressedTileStorage.h | 3 +- .../Level/Storage/McRegionChunkStorage.cpp | 63 +++--- .../Level/Storage/McRegionChunkStorage.h | 4 +- .../Level/Storage/OldChunkStorage.cpp | 34 ++- .../Level/Storage/ZonedChunkStorage.cpp | 32 ++- Minecraft.World/Network/Connection.cpp | 127 ++++++------ Minecraft.World/Network/Connection.h | 8 +- Minecraft.World/Network/Socket.cpp | 134 ++++++------ Minecraft.World/Network/Socket.h | 5 +- .../WorldGen/Biomes/BiomeCache.cpp | 9 +- Minecraft.World/WorldGen/Biomes/BiomeCache.h | 3 +- 59 files changed, 952 insertions(+), 1128 deletions(-) diff --git a/Minecraft.Client/Level/MultiPlayerLevel.cpp b/Minecraft.Client/Level/MultiPlayerLevel.cpp index a34ba8ec5..69315def1 100644 --- a/Minecraft.Client/Level/MultiPlayerLevel.cpp +++ b/Minecraft.Client/Level/MultiPlayerLevel.cpp @@ -1,4 +1,5 @@ #include "../Platform/stdafx.h" +#include #include "MultiPlayerLevel.h" #include "../Player/MultiPlayerLocalPlayer.h" #include "../Network/ClientConnection.h" @@ -117,14 +118,15 @@ void MultiPlayerLevel::tick() { PIXEndNamedEvent(); PIXBeginNamedEvent(0, "Entity re-entry"); - EnterCriticalSection(&m_entitiesCS); - for (int i = 0; i < 10 && !reEntries.empty(); i++) { - std::shared_ptr e = *(reEntries.begin()); + { + std::lock_guard lock(m_entitiesCS); + for (int i = 0; i < 10 && !reEntries.empty(); i++) { + std::shared_ptr e = *(reEntries.begin()); - if (find(entities.begin(), entities.end(), e) == entities.end()) - addEntity(e); + if (find(entities.begin(), entities.end(), e) == entities.end()) + addEntity(e); + } } - LeaveCriticalSection(&m_entitiesCS); PIXEndNamedEvent(); PIXBeginNamedEvent(0, "Connection ticking"); @@ -808,23 +810,24 @@ void MultiPlayerLevel::setDayTime(int64_t newTime) { void MultiPlayerLevel::removeAllPendingEntityRemovals() { // entities.removeAll(entitiesToRemove); - EnterCriticalSection(&m_entitiesCS); - for (auto it = entities.begin(); it != entities.end();) { - bool found = false; - for (auto it2 = entitiesToRemove.begin(); - it2 != entitiesToRemove.end(); it2++) { - if ((*it) == (*it2)) { - found = true; - break; + { + std::lock_guard lock(m_entitiesCS); + for (auto it = entities.begin(); it != entities.end();) { + bool found = false; + for (auto it2 = entitiesToRemove.begin(); + it2 != entitiesToRemove.end(); it2++) { + if ((*it) == (*it2)) { + found = true; + break; + } + } + if (found) { + it = entities.erase(it); + } else { + it++; } } - if (found) { - it = entities.erase(it); - } else { - it++; - } } - LeaveCriticalSection(&m_entitiesCS); auto endIt = entitiesToRemove.end(); for (auto it = entitiesToRemove.begin(); it != endIt; it++) { @@ -845,36 +848,37 @@ void MultiPlayerLevel::removeAllPendingEntityRemovals() { entitiesToRemove.clear(); // for (int i = 0; i < entities.size(); i++) - EnterCriticalSection(&m_entitiesCS); - std::vector >::iterator it = entities.begin(); - while (it != entities.end()) { - std::shared_ptr e = *it; // entities.at(i); + { + std::lock_guard lock(m_entitiesCS); + std::vector >::iterator it = entities.begin(); + while (it != entities.end()) { + std::shared_ptr e = *it; // entities.at(i); - if (e->riding != nullptr) { - if (e->riding->removed || e->riding->rider.lock() != e) { - e->riding->rider = std::weak_ptr(); - e->riding = nullptr; + if (e->riding != nullptr) { + if (e->riding->removed || e->riding->rider.lock() != e) { + e->riding->rider = std::weak_ptr(); + e->riding = nullptr; + } else { + ++it; + continue; + } + } + + if (e->removed) { + int xc = e->xChunk; + int zc = e->zChunk; + if (e->inChunk && hasChunk(xc, zc)) { + getChunk(xc, zc)->removeEntity(e); + } + // entities.remove(i--); + + it = entities.erase(it); + entityRemoved(e); } else { - ++it; - continue; + it++; } } - - if (e->removed) { - int xc = e->xChunk; - int zc = e->zChunk; - if (e->inChunk && hasChunk(xc, zc)) { - getChunk(xc, zc)->removeEntity(e); - } - // entities.remove(i--); - - it = entities.erase(it); - entityRemoved(e); - } else { - it++; - } } - LeaveCriticalSection(&m_entitiesCS); } void MultiPlayerLevel::removeClientConnection(ClientConnection* c, @@ -907,34 +911,34 @@ void MultiPlayerLevel::dataReceivedForChunk(int x, int z) { void MultiPlayerLevel::removeUnusedTileEntitiesInRegion(int x0, int y0, int z0, int x1, int y1, int z1) { - EnterCriticalSection(&m_tileEntityListCS); + { + std::lock_guard lock(m_tileEntityListCS); - for (unsigned int i = 0; i < tileEntityList.size();) { - bool removed = false; - std::shared_ptr te = tileEntityList[i]; - if (te->x >= x0 && te->y >= y0 && te->z >= z0 && te->x < x1 && - te->y < y1 && te->z < z1) { - LevelChunk* lc = getChunk(te->x >> 4, te->z >> 4); - if (lc != nullptr) { - // Only remove tile entities where this is no longer a tile - // entity - int tileId = lc->getTile(te->x & 15, te->y, te->z & 15); - if (Tile::tiles[tileId] == nullptr || - !Tile::tiles[tileId]->isEntityTile()) { - tileEntityList[i] = tileEntityList.back(); - tileEntityList.pop_back(); + for (unsigned int i = 0; i < tileEntityList.size();) { + bool removed = false; + std::shared_ptr te = tileEntityList[i]; + if (te->x >= x0 && te->y >= y0 && te->z >= z0 && te->x < x1 && + te->y < y1 && te->z < z1) { + LevelChunk* lc = getChunk(te->x >> 4, te->z >> 4); + if (lc != nullptr) { + // Only remove tile entities where this is no longer a tile + // entity + int tileId = lc->getTile(te->x & 15, te->y, te->z & 15); + if (Tile::tiles[tileId] == nullptr || + !Tile::tiles[tileId]->isEntityTile()) { + tileEntityList[i] = tileEntityList.back(); + tileEntityList.pop_back(); - // 4J Stu - Chests can create new tile entities when being - // removed, so disable this - m_bDisableAddNewTileEntities = true; - lc->removeTileEntity(te->x & 15, te->y, te->z & 15); - m_bDisableAddNewTileEntities = false; - removed = true; + // 4J Stu - Chests can create new tile entities when being + // removed, so disable this + m_bDisableAddNewTileEntities = true; + lc->removeTileEntity(te->x & 15, te->y, te->z & 15); + m_bDisableAddNewTileEntities = false; + removed = true; + } } } + if (!removed) i++; } - if (!removed) i++; } - - LeaveCriticalSection(&m_tileEntityListCS); } diff --git a/Minecraft.Client/Level/ServerLevel.cpp b/Minecraft.Client/Level/ServerLevel.cpp index 3fae07502..6108d2405 100644 --- a/Minecraft.Client/Level/ServerLevel.cpp +++ b/Minecraft.Client/Level/ServerLevel.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "../Platform/stdafx.h" #include "ServerLevel.h" @@ -45,7 +46,7 @@ WeighedTreasureArray ServerLevel::RANDOM_BONUS_ITEMS; C4JThread* ServerLevel::m_updateThread = nullptr; C4JThread::EventArray* ServerLevel::m_updateTrigger; -CRITICAL_SECTION ServerLevel::m_updateCS[3]; +std::mutex ServerLevel::m_updateCS[3]; Level* ServerLevel::m_level[3]; int ServerLevel::m_updateChunkX[3][LEVEL_CHUNKS_TO_UPDATE_MAX]; @@ -59,9 +60,6 @@ int ServerLevel::m_randValue[3]; void ServerLevel::staticCtor() { m_updateTrigger = new C4JThread::EventArray(3); - InitializeCriticalSection(&m_updateCS[0]); - InitializeCriticalSection(&m_updateCS[1]); - InitializeCriticalSection(&m_updateCS[2]); m_updateThread = new C4JThread(runUpdate, nullptr, "Tile update"); m_updateThread->SetProcessor(CPU_CORE_TILE_UPDATE); @@ -107,9 +105,6 @@ ServerLevel::ServerLevel(MinecraftServer* server, LevelSettings* levelSettings) : Level(levelStorage, levelName, levelSettings, Dimension::getNew(dimension), false) { - InitializeCriticalSection(&m_limiterCS); - InitializeCriticalSection(&m_tickNextTickCS); - InitializeCriticalSection(&m_csQueueSendTileUpdates); m_fallingTileCount = 0; m_primedTntCount = 0; @@ -188,30 +183,24 @@ ServerLevel::~ServerLevel() { delete portalForcer; delete mobSpawner; - EnterCriticalSection(&m_csQueueSendTileUpdates); - for (auto it = m_queuedSendTileUpdates.begin(); - it != m_queuedSendTileUpdates.end(); ++it) { - Pos* p = *it; - delete p; + { + std::lock_guard lock(m_csQueueSendTileUpdates); + for (auto it = m_queuedSendTileUpdates.begin(); + it != m_queuedSendTileUpdates.end(); ++it) { + Pos* p = *it; + delete p; + } + m_queuedSendTileUpdates.clear(); + + delete this->tracker; // MGH - added, we were losing about 500K going in + // and out the menus + delete this->chunkMap; } - m_queuedSendTileUpdates.clear(); - - delete this->tracker; // MGH - added, we were losing about 500K going in - // and out the menus - delete this->chunkMap; - - LeaveCriticalSection(&m_csQueueSendTileUpdates); - DeleteCriticalSection(&m_csQueueSendTileUpdates); - DeleteCriticalSection(&m_limiterCS); - DeleteCriticalSection(&m_tickNextTickCS); // Make sure that the update thread isn't actually doing any updating - EnterCriticalSection(&m_updateCS[0]); - LeaveCriticalSection(&m_updateCS[0]); - EnterCriticalSection(&m_updateCS[1]); - LeaveCriticalSection(&m_updateCS[1]); - EnterCriticalSection(&m_updateCS[2]); - LeaveCriticalSection(&m_updateCS[2]); + { std::lock_guard lock(m_updateCS[0]); } + { std::lock_guard lock(m_updateCS[1]); } + { std::lock_guard lock(m_updateCS[2]); } m_updateTrigger->ClearAll(); } @@ -450,31 +439,32 @@ void ServerLevel::tickTiles() { unsigned int tickCount = 0; - EnterCriticalSection(&m_updateCS[iLev]); - // This section processes the tiles that need to be ticked, which we worked - // out in the previous tick (or haven't yet, if this is the first frame) - /*int grassTicks = 0; - int lavaTicks = 0; - int otherTicks = 0;*/ - for (int i = 0; i < m_updateTileCount[iLev]; i++) { - int x = m_updateTileX[iLev][i]; - int y = m_updateTileY[iLev][i]; - int z = m_updateTileZ[iLev][i]; - if (hasChunkAt(x, y, z)) { - int id = getTile(x, y, z); - if (Tile::tiles[id] != nullptr && Tile::tiles[id]->isTicking()) { - /*if(id == 2) ++grassTicks; - else if(id == 11) ++lavaTicks; - else ++otherTicks;*/ - Tile::tiles[id]->tick(this, x, y, z, random); + { + std::lock_guard lock(m_updateCS[iLev]); + // This section processes the tiles that need to be ticked, which we worked + // out in the previous tick (or haven't yet, if this is the first frame) + /*int grassTicks = 0; + int lavaTicks = 0; + int otherTicks = 0;*/ + for (int i = 0; i < m_updateTileCount[iLev]; i++) { + int x = m_updateTileX[iLev][i]; + int y = m_updateTileY[iLev][i]; + int z = m_updateTileZ[iLev][i]; + if (hasChunkAt(x, y, z)) { + int id = getTile(x, y, z); + if (Tile::tiles[id] != nullptr && Tile::tiles[id]->isTicking()) { + /*if(id == 2) ++grassTicks; + else if(id == 11) ++lavaTicks; + else ++otherTicks;*/ + Tile::tiles[id]->tick(this, x, y, z, random); + } } } + // printf("Total ticks - Grass: %d, Lava: %d, Other: %d, Total: %d\n", + // grassTicks, lavaTicks, otherTicks, grassTicks + lavaTicks + otherTicks); + m_updateTileCount[iLev] = 0; + m_updateChunkCount[iLev] = 0; } - // printf("Total ticks - Grass: %d, Lava: %d, Other: %d, Total: %d\n", - // grassTicks, lavaTicks, otherTicks, grassTicks + lavaTicks + otherTicks); - m_updateTileCount[iLev] = 0; - m_updateChunkCount[iLev] = 0; - LeaveCriticalSection(&m_updateCS[iLev]); Level::tickTiles(); @@ -603,12 +593,13 @@ void ServerLevel::addToTickNextTick(int x, int y, int z, int tileId, td.delay(tickDelay + levelData->getGameTime()); td.setPriorityTilt(priorityTilt); } - EnterCriticalSection(&m_tickNextTickCS); - if (tickNextTickSet.find(td) == tickNextTickSet.end()) { - tickNextTickSet.insert(td); - tickNextTickList.insert(td); + { + std::lock_guard lock(m_tickNextTickCS); + if (tickNextTickSet.find(td) == tickNextTickSet.end()) { + tickNextTickSet.insert(td); + tickNextTickList.insert(td); + } } - LeaveCriticalSection(&m_tickNextTickCS); } MemSect(0); } @@ -621,12 +612,13 @@ void ServerLevel::forceAddTileTick(int x, int y, int z, int tileId, if (tileId > 0) { td.delay(tickDelay + levelData->getGameTime()); } - EnterCriticalSection(&m_tickNextTickCS); - if (tickNextTickSet.find(td) == tickNextTickSet.end()) { - tickNextTickSet.insert(td); - tickNextTickList.insert(td); + { + std::lock_guard lock(m_tickNextTickCS); + if (tickNextTickSet.find(td) == tickNextTickSet.end()) { + tickNextTickSet.insert(td); + tickNextTickList.insert(td); + } } - LeaveCriticalSection(&m_tickNextTickCS); } void ServerLevel::tickEntities() { @@ -644,7 +636,7 @@ void ServerLevel::tickEntities() { void ServerLevel::resetEmptyTime() { emptyTime = 0; } bool ServerLevel::tickPendingTicks(bool force) { - EnterCriticalSection(&m_tickNextTickCS); + std::lock_guard lock(m_tickNextTickCS); int count = (int)tickNextTickList.size(); int count2 = (int)tickNextTickSet.size(); if (count != tickNextTickSet.size()) { @@ -687,14 +679,13 @@ bool ServerLevel::tickPendingTicks(bool force) { int count4 = (int)tickNextTickSet.size(); bool retval = tickNextTickList.size() != 0; - LeaveCriticalSection(&m_tickNextTickCS); return retval; } std::vector* ServerLevel::fetchTicksInChunk(LevelChunk* chunk, bool remove) { - EnterCriticalSection(&m_tickNextTickCS); + std::lock_guard lock(m_tickNextTickCS); std::vector* results = new std::vector; ChunkPos* pos = chunk->getPos(); @@ -749,7 +740,6 @@ std::vector* ServerLevel::fetchTicksInChunk(LevelChunk* chunk, } } - LeaveCriticalSection(&m_tickNextTickCS); return results; } @@ -1225,13 +1215,12 @@ void ServerLevel::sendParticles(const std::wstring& name, double x, double y, // 4J Stu - Sometimes we want to update tiles on the server from the main thread // (eg SignTileEntity when string verify returns) void ServerLevel::queueSendTileUpdate(int x, int y, int z) { - EnterCriticalSection(&m_csQueueSendTileUpdates); + std::lock_guard lock(m_csQueueSendTileUpdates); m_queuedSendTileUpdates.push_back(new Pos(x, y, z)); - LeaveCriticalSection(&m_csQueueSendTileUpdates); } void ServerLevel::runQueuedSendTileUpdates() { - EnterCriticalSection(&m_csQueueSendTileUpdates); + std::lock_guard lock(m_csQueueSendTileUpdates); for (auto it = m_queuedSendTileUpdates.begin(); it != m_queuedSendTileUpdates.end(); ++it) { Pos* p = *it; @@ -1239,7 +1228,6 @@ void ServerLevel::runQueuedSendTileUpdates() { delete p; } m_queuedSendTileUpdates.clear(); - LeaveCriticalSection(&m_csQueueSendTileUpdates); } // 4J - added special versions of addEntity and extra processing on entity @@ -1249,53 +1237,48 @@ bool ServerLevel::addEntity(std::shared_ptr e) { if (e->instanceof(eTYPE_ITEMENTITY)) { // printf("Adding item entity count //%d\n",m_itemEntities.size()); - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_itemEntities.size() >= MAX_ITEM_ENTITIES) { // printf("Adding - doing remove\n"); removeEntityImmediately(m_itemEntities.front()); } - LeaveCriticalSection(&m_limiterCS); } // If its an hanging entity, and we've got to our capacity, delete the // oldest else if (e->instanceof(eTYPE_HANGING_ENTITY)) { // printf("Adding item entity count //%d\n",m_itemEntities.size()); - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_hangingEntities.size() >= MAX_HANGING_ENTITIES) { // printf("Adding - doing remove\n"); // 4J-PB - refuse to add the entity, since we'll be removing one // already there, and it may be an item frame with something in it. - LeaveCriticalSection(&m_limiterCS); return false; // removeEntityImmediately(m_hangingEntities.front()); } - LeaveCriticalSection(&m_limiterCS); } // If its an arrow entity, and we've got to our capacity, delete the oldest else if (e->instanceof(eTYPE_ARROW)) { // printf("Adding arrow entity count //%d\n",m_arrowEntities.size()); - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_arrowEntities.size() >= MAX_ARROW_ENTITIES) { // printf("Adding - doing remove\n"); removeEntityImmediately(m_arrowEntities.front()); } - LeaveCriticalSection(&m_limiterCS); } // If its an experience orb entity, and we've got to our capacity, delete // the oldest else if (e->instanceof(eTYPE_EXPERIENCEORB)) { // printf("Adding arrow entity count //%d\n",m_arrowEntities.size()); - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_experienceOrbEntities.size() >= MAX_EXPERIENCEORB_ENTITIES) { // printf("Adding - doing remove\n"); removeEntityImmediately(m_experienceOrbEntities.front()); } - LeaveCriticalSection(&m_limiterCS); } return Level::addEntity(e); } @@ -1308,21 +1291,17 @@ bool ServerLevel::atEntityLimit(std::shared_ptr e) { bool atLimit = false; if (e->instanceof(eTYPE_ITEMENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_itemEntities.size() >= MAX_ITEM_ENTITIES; - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_HANGING_ENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_hangingEntities.size() >= MAX_HANGING_ENTITIES; - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_ARROW)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_arrowEntities.size() >= MAX_ARROW_ENTITIES; - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_EXPERIENCEORB)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_experienceOrbEntities.size() >= MAX_EXPERIENCEORB_ENTITIES; - LeaveCriticalSection(&m_limiterCS); } return atLimit; @@ -1331,37 +1310,31 @@ bool ServerLevel::atEntityLimit(std::shared_ptr e) { // Maintain a cound of primed tnt & falling tiles in this level void ServerLevel::entityAddedExtra(std::shared_ptr e) { if (e->instanceof(eTYPE_ITEMENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_itemEntities.push_back(e); // printf("entity added: item entity count now //%d\n",m_itemEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_HANGING_ENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_hangingEntities.push_back(e); // printf("entity added: item entity count now //%d\n",m_itemEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_ARROW)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_arrowEntities.push_back(e); // printf("entity added: arrow entity count now //%d\n",m_arrowEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_EXPERIENCEORB)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_experienceOrbEntities.push_back(e); // printf("entity added: experience orb entity count now //%d\n",m_arrowEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_PRIMEDTNT)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_primedTntCount++; - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_FALLINGTILE)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_fallingTileCount++; - LeaveCriticalSection(&m_limiterCS); } } @@ -1369,7 +1342,7 @@ void ServerLevel::entityAddedExtra(std::shared_ptr e) { // item entities from our list void ServerLevel::entityRemovedExtra(std::shared_ptr e) { if (e->instanceof(eTYPE_ITEMENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: item entity count //%d\n",m_itemEntities.size()); auto it = find(m_itemEntities.begin(), m_itemEntities.end(), e); @@ -1379,9 +1352,8 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { } // printf("entity removed: item entity count now //%d\n",m_itemEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_HANGING_ENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: item entity count //%d\n",m_itemEntities.size()); auto it = @@ -1392,9 +1364,8 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { } // printf("entity removed: item entity count now //%d\n",m_itemEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_ARROW)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: arrow entity count //%d\n",m_arrowEntities.size()); auto it = find(m_arrowEntities.begin(), m_arrowEntities.end(), e); @@ -1404,9 +1375,8 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { } // printf("entity removed: arrow entity count now //%d\n",m_arrowEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_EXPERIENCEORB)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: experience orb entity count //%d\n",m_arrowEntities.size()); auto it = find(m_experienceOrbEntities.begin(), @@ -1417,29 +1387,24 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { } // printf("entity removed: experience orb entity count now //%d\n",m_arrowEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_PRIMEDTNT)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_primedTntCount--; - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_FALLINGTILE)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_fallingTileCount--; - LeaveCriticalSection(&m_limiterCS); } } bool ServerLevel::newPrimedTntAllowed() { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); bool retval = m_primedTntCount < MAX_PRIMED_TNT; - LeaveCriticalSection(&m_limiterCS); return retval; } bool ServerLevel::newFallingTileAllowed() { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); bool retval = m_fallingTileCount < MAX_FALLING_TILE; - LeaveCriticalSection(&m_limiterCS); return retval; } @@ -1458,7 +1423,7 @@ int ServerLevel::runUpdate(void* lpParam) { int grassTicks = 0; int lavaTicks = 0; for (unsigned int iLev = 0; iLev < 3; ++iLev) { - EnterCriticalSection(&m_updateCS[iLev]); + std::lock_guard lock(m_updateCS[iLev]); for (int i = 0; i < m_updateChunkCount[iLev]; i++) { // 4J - some of these tile ticks will check things in // neighbouring tiles, causing chunks to load/create that aren't @@ -1548,7 +1513,6 @@ int ServerLevel::runUpdate(void* lpParam) { } } } - LeaveCriticalSection(&m_updateCS[iLev]); } PIXEndNamedEvent(); } diff --git a/Minecraft.Client/Level/ServerLevel.h b/Minecraft.Client/Level/ServerLevel.h index a704d6ed7..74b5e87dd 100644 --- a/Minecraft.Client/Level/ServerLevel.h +++ b/Minecraft.Client/Level/ServerLevel.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../../Minecraft.World/Headers/net.minecraft.world.level.h" #include "../../Minecraft.World/Util/JavaIntHash.h" class ServerChunkCache; @@ -16,7 +17,7 @@ private: EntityTracker* tracker; PlayerChunkMap* chunkMap; - CRITICAL_SECTION m_tickNextTickCS; // 4J added + std::mutex m_tickNextTickCS; // 4J added std::set tickNextTickList; // 4J Was TreeSet std::unordered_set m_queuedSendTileUpdates; // 4J added - CRITICAL_SECTION m_csQueueSendTileUpdates; + std::mutex m_csQueueSendTileUpdates; protected: int saveInterval; @@ -177,7 +178,7 @@ public: int m_primedTntCount; int m_fallingTileCount; - CRITICAL_SECTION m_limiterCS; + std::mutex m_limiterCS; std::list > m_itemEntities; std::list > m_hangingEntities; std::list > m_arrowEntities; @@ -211,7 +212,7 @@ public: static int m_randValue[3]; static C4JThread::EventArray* m_updateTrigger; - static CRITICAL_SECTION m_updateCS[3]; + static std::mutex m_updateCS[3]; static C4JThread* m_updateThread; static int runUpdate(void* lpParam); diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 1d97f3e47..65075ecee 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -121,8 +121,6 @@ Minecraft::Minecraft(Component* mouseComponent, Canvas* parent, rightClickDelay = 0; // 4J Stu Added - InitializeCriticalSection(&ProgressRenderer::s_progress); - InitializeCriticalSection(&m_setLevelCS); // m_hPlayerRespawned = CreateEvent(nullptr, false, false, nullptr); progressRenderer = nullptr; @@ -987,7 +985,7 @@ void Minecraft::run_middle() { } #endif - EnterCriticalSection(&m_setLevelCS); + { std::lock_guard lock(m_setLevelCS); if (running) { if (reloadTextures) { @@ -1734,7 +1732,7 @@ void Minecraft::run_middle() { } */ } - LeaveCriticalSection(&m_setLevelCS); + } // lock_guard scope } void Minecraft::run_end() { destroy(); } @@ -3670,7 +3668,7 @@ void Minecraft::setLevel(MultiPlayerLevel* level, int message /*=-1*/, std::shared_ptr forceInsertPlayer /*=nullptr*/, bool doForceStatsSave /*=true*/, bool bPrimaryPlayerSignedOut /*=false*/) { - EnterCriticalSection(&m_setLevelCS); + std::lock_guard lock(m_setLevelCS); bool playerAdded = false; this->cameraTargetPlayer = nullptr; @@ -3842,7 +3840,6 @@ void Minecraft::setLevel(MultiPlayerLevel* level, int message /*=-1*/, // System.gc(); // 4J - removed // 4J removed // this->lastTickTime = 0; - LeaveCriticalSection(&m_setLevelCS); } void Minecraft::prepareLevel(int title) { diff --git a/Minecraft.Client/Minecraft.h b/Minecraft.Client/Minecraft.h index b496e1c5b..7b738e7bb 100644 --- a/Minecraft.Client/Minecraft.h +++ b/Minecraft.Client/Minecraft.h @@ -1,4 +1,5 @@ #pragma once +#include class Timer; class MultiPlayerLevel; class LevelRenderer; @@ -347,7 +348,7 @@ public: // 4J Stu void forceStatsSave(int idx); - CRITICAL_SECTION m_setLevelCS; + std::mutex m_setLevelCS; private: // A bit field that store whether a particular quadrant is in the full diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index 39f47ac36..59d72e68f 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -243,38 +243,39 @@ int MinecraftServer::runPostUpdate(void* lpParam) { // Update lights for both levels until we are signalled to terminate do { - EnterCriticalSection(&server->m_postProcessCS); - if (server->m_postProcessRequests.size()) { - MinecraftServer::postProcessRequest request = - server->m_postProcessRequests.back(); - server->m_postProcessRequests.pop_back(); - LeaveCriticalSection(&server->m_postProcessCS); - static int count = 0; - PIXBeginNamedEvent(0, "Post processing %d ", (count++) % 8); - request.chunkSource->postProcess(request.chunkSource, request.x, - request.z); - PIXEndNamedEvent(); - } else { - LeaveCriticalSection(&server->m_postProcessCS); + { + std::unique_lock lock(server->m_postProcessCS); + if (server->m_postProcessRequests.size()) { + MinecraftServer::postProcessRequest request = + server->m_postProcessRequests.back(); + server->m_postProcessRequests.pop_back(); + lock.unlock(); + static int count = 0; + PIXBeginNamedEvent(0, "Post processing %d ", (count++) % 8); + request.chunkSource->postProcess(request.chunkSource, request.x, + request.z); + PIXEndNamedEvent(); + } } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } while (!server->m_postUpdateTerminate && ShutdownManager::ShouldRun(ShutdownManager::ePostProcessThread)); // #ifndef 0 // One final pass through updates to make sure we're done - EnterCriticalSection(&server->m_postProcessCS); - int maxRequests = server->m_postProcessRequests.size(); - while (server->m_postProcessRequests.size() && - ShutdownManager::ShouldRun(ShutdownManager::ePostProcessThread)) { - MinecraftServer::postProcessRequest request = - server->m_postProcessRequests.back(); - server->m_postProcessRequests.pop_back(); - LeaveCriticalSection(&server->m_postProcessCS); - request.chunkSource->postProcess(request.chunkSource, request.x, - request.z); - EnterCriticalSection(&server->m_postProcessCS); + { + std::unique_lock lock(server->m_postProcessCS); + int maxRequests = server->m_postProcessRequests.size(); + while (server->m_postProcessRequests.size() && + ShutdownManager::ShouldRun(ShutdownManager::ePostProcessThread)) { + MinecraftServer::postProcessRequest request = + server->m_postProcessRequests.back(); + server->m_postProcessRequests.pop_back(); + lock.unlock(); + request.chunkSource->postProcess(request.chunkSource, request.x, + request.z); + lock.lock(); + } } - LeaveCriticalSection(&server->m_postProcessCS); // #endif //0 Tile::ReleaseThreadStorage(); Level::destroyLightingCache(); @@ -286,26 +287,28 @@ int MinecraftServer::runPostUpdate(void* lpParam) { void MinecraftServer::addPostProcessRequest(ChunkSource* chunkSource, int x, int z) { - EnterCriticalSection(&m_postProcessCS); + { std::lock_guard lock(m_postProcessCS); m_postProcessRequests.push_back( MinecraftServer::postProcessRequest(x, z, chunkSource)); - LeaveCriticalSection(&m_postProcessCS); + } } void MinecraftServer::postProcessTerminate(ProgressRenderer* mcprogress) { std::uint32_t status = 0; + size_t postProcessItemCount = 0; + size_t postProcessItemRemaining = 0; - EnterCriticalSection(&server->m_postProcessCS); - size_t postProcessItemCount = server->m_postProcessRequests.size(); - LeaveCriticalSection(&server->m_postProcessCS); + { std::lock_guard lock(server->m_postProcessCS); + postProcessItemCount = server->m_postProcessRequests.size(); + } do { status = m_postUpdateThread->WaitForCompletion(50); if (status == WAIT_TIMEOUT) { - EnterCriticalSection(&server->m_postProcessCS); - size_t postProcessItemRemaining = + { std::lock_guard lock(server->m_postProcessCS); + postProcessItemRemaining = server->m_postProcessRequests.size(); - LeaveCriticalSection(&server->m_postProcessCS); + } if (postProcessItemCount) { mcprogress->progressStagePercentage( @@ -319,7 +322,6 @@ void MinecraftServer::postProcessTerminate(ProgressRenderer* mcprogress) { } while (status == WAIT_TIMEOUT); delete m_postUpdateThread; m_postUpdateThread = nullptr; - DeleteCriticalSection(&m_postProcessCS); } bool MinecraftServer::loadLevel(LevelStorageSource* storageSource, @@ -481,7 +483,6 @@ bool MinecraftServer::loadLevel(LevelStorageSource* storageSource, if (s_bServerHalted || !g_NetworkManager.IsInSession()) return false; // 4J - Make a new thread to do post processing - InitializeCriticalSection(&m_postProcessCS); // 4J-PB - fix for 108310 - TCR #001 BAS Game Stability: TU12: Code: // Compliance: Crash after creating world on "journey" seed. Stack gets very diff --git a/Minecraft.Client/MinecraftServer.h b/Minecraft.Client/MinecraftServer.h index 737f49fd2..8a91dd724 100644 --- a/Minecraft.Client/MinecraftServer.h +++ b/Minecraft.Client/MinecraftServer.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "Input/ConsoleInputSource.h" #include "../Minecraft.World/Util/ArrayWithLength.h" @@ -247,7 +248,7 @@ private: : x(x), z(z), chunkSource(chunkSource) {} }; std::vector m_postProcessRequests; - CRITICAL_SECTION m_postProcessCS; + std::mutex m_postProcessCS; public: void addPostProcessRequest(ChunkSource* chunkSource, int x, int z); diff --git a/Minecraft.Client/Network/MultiPlayerChunkCache.cpp b/Minecraft.Client/Network/MultiPlayerChunkCache.cpp index c8537b5aa..be1a0cae8 100644 --- a/Minecraft.Client/Network/MultiPlayerChunkCache.cpp +++ b/Minecraft.Client/Network/MultiPlayerChunkCache.cpp @@ -89,7 +89,6 @@ MultiPlayerChunkCache::MultiPlayerChunkCache(Level* level) { this->cache = new LevelChunk*[XZSIZE * XZSIZE]; memset(this->cache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk*)); - InitializeCriticalSectionAndSpinCount(&m_csLoadCreate, 4000); } MultiPlayerChunkCache::~MultiPlayerChunkCache() { @@ -100,8 +99,6 @@ MultiPlayerChunkCache::~MultiPlayerChunkCache() { auto itEnd = loadedChunkList.end(); for (auto it = loadedChunkList.begin(); it != itEnd; it++) delete *it; - - DeleteCriticalSection(&m_csLoadCreate); } bool MultiPlayerChunkCache::hasChunk(int x, int z) { @@ -158,7 +155,7 @@ LevelChunk* MultiPlayerChunkCache::create(int x, int z) { LevelChunk* lastChunk = chunk; if (chunk == nullptr) { - EnterCriticalSection(&m_csLoadCreate); + { std::unique_lock lock(m_csLoadCreate); // LevelChunk *chunk; if (g_NetworkManager.IsHost()) // force here to disable sharing of data @@ -199,8 +196,7 @@ LevelChunk* MultiPlayerChunkCache::create(int x, int z) { } chunk->loaded = true; - - LeaveCriticalSection(&m_csLoadCreate); + } #if (defined _WIN64 || defined __LP64__) if (InterlockedCompareExchangeRelease64( @@ -220,9 +216,9 @@ LevelChunk* MultiPlayerChunkCache::create(int x, int z) { } // Successfully updated the cache - EnterCriticalSection(&m_csLoadCreate); + { std::lock_guard lock(m_csLoadCreate); loadedChunkList.push_back(chunk); - LeaveCriticalSection(&m_csLoadCreate); + } } else { // Something else must have updated the cache. Return that chunk and // discard this one. This really shouldn't be happening in @@ -281,9 +277,10 @@ void MultiPlayerChunkCache::recreateLogicStructuresForChunk(int chunkX, int chunkZ) {} std::wstring MultiPlayerChunkCache::gatherStats() { - EnterCriticalSection(&m_csLoadCreate); - int size = (int)loadedChunkList.size(); - LeaveCriticalSection(&m_csLoadCreate); + int size; + { std::lock_guard lock(m_csLoadCreate); + size = (int)loadedChunkList.size(); + } return L"MultiplayerChunkCache: " + _toString(size); } diff --git a/Minecraft.Client/Network/MultiPlayerChunkCache.h b/Minecraft.Client/Network/MultiPlayerChunkCache.h index ef14a168f..63b114bf9 100644 --- a/Minecraft.Client/Network/MultiPlayerChunkCache.h +++ b/Minecraft.Client/Network/MultiPlayerChunkCache.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../../Minecraft.World/Headers/net.minecraft.world.level.h" #include "../../Minecraft.World/Headers/net.minecraft.world.level.chunk.h" #include "../../Minecraft.World/Level/RandomLevelSource.h" @@ -18,7 +19,7 @@ private: LevelChunk** cache; // 4J - added for multithreaded support - CRITICAL_SECTION m_csLoadCreate; + std::mutex m_csLoadCreate; // 4J - size of cache is defined by size of one side - must be even int XZSIZE; int XZOFFSET; diff --git a/Minecraft.Client/Network/PlayerConnection.cpp b/Minecraft.Client/Network/PlayerConnection.cpp index f4f1cab17..f517299be 100644 --- a/Minecraft.Client/Network/PlayerConnection.cpp +++ b/Minecraft.Client/Network/PlayerConnection.cpp @@ -57,8 +57,6 @@ PlayerConnection::PlayerConnection(MinecraftServer* server, this->player = player; // player->connection = this; // 4J - moved out as we can't // assign in a ctor - InitializeCriticalSection(&done_cs); - m_bCloseOnTick = false; m_bWasKicked = false; @@ -73,7 +71,6 @@ PlayerConnection::PlayerConnection(MinecraftServer* server, PlayerConnection::~PlayerConnection() { delete connection; - DeleteCriticalSection(&done_cs); } void PlayerConnection::tick() { @@ -106,9 +103,8 @@ void PlayerConnection::tick() { } void PlayerConnection::disconnect(DisconnectPacket::eDisconnectReason reason) { - EnterCriticalSection(&done_cs); + std::lock_guard lock(done_cs); if (done) { - LeaveCriticalSection(&done_cs); return; } @@ -135,7 +131,6 @@ void PlayerConnection::disconnect(DisconnectPacket::eDisconnectReason reason) { server->getPlayers()->remove(player); done = true; - LeaveCriticalSection(&done_cs); } void PlayerConnection::handlePlayerInput( @@ -555,7 +550,7 @@ void PlayerConnection::handleUseItem(std::shared_ptr packet) { void PlayerConnection::onDisconnect(DisconnectPacket::eDisconnectReason reason, void* reasonObjects) { - EnterCriticalSection(&done_cs); + std::lock_guard lock(done_cs); if (done) return; // logger.info(player.name + " lost connection: " + reason); // 4J-PB - removed, since it needs to be localised in the language the @@ -572,7 +567,6 @@ void PlayerConnection::onDisconnect(DisconnectPacket::eDisconnectReason reason, } server->getPlayers()->remove(player); done = true; - LeaveCriticalSection(&done_cs); } void PlayerConnection::onUnhandledPacket(std::shared_ptr packet) { diff --git a/Minecraft.Client/Network/PlayerConnection.h b/Minecraft.Client/Network/PlayerConnection.h index cdc5f4e9f..b3956acba 100644 --- a/Minecraft.Client/Network/PlayerConnection.h +++ b/Minecraft.Client/Network/PlayerConnection.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../Input/ConsoleInputSource.h" #include "../../Minecraft.World/Network/Packets/PacketListener.h" #include "../../Minecraft.World/Util/JavaIntHash.h" @@ -14,7 +15,7 @@ class PlayerConnection : public PacketListener, public ConsoleInputSource { public: Connection* connection; bool done; - CRITICAL_SECTION done_cs; + std::mutex done_cs; // 4J Stu - Added this so that we can manage UGC privileges PlayerUID m_offlineXUID, m_onlineXUID; diff --git a/Minecraft.Client/Network/PlayerList.cpp b/Minecraft.Client/Network/PlayerList.cpp index 9d9eda446..efdf6e2fb 100644 --- a/Minecraft.Client/Network/PlayerList.cpp +++ b/Minecraft.Client/Network/PlayerList.cpp @@ -49,8 +49,6 @@ PlayerList::PlayerList(MinecraftServer* server) { maxPlayers = server->settings->getInt(L"max-players", 20); doWhiteList = false; - InitializeCriticalSection(&m_kickPlayersCS); - InitializeCriticalSection(&m_closePlayersCS); } PlayerList::~PlayerList() { @@ -62,8 +60,6 @@ PlayerList::~PlayerList() { (*it)->gameMode = nullptr; } - DeleteCriticalSection(&m_kickPlayersCS); - DeleteCriticalSection(&m_closePlayersCS); } void PlayerList::placeNewPlayer(Connection* connection, @@ -997,7 +993,7 @@ void PlayerList::tick() { } } - EnterCriticalSection(&m_closePlayersCS); + { std::lock_guard lock(m_closePlayersCS); while (!m_smallIdsToClose.empty()) { std::uint8_t smallId = m_smallIdsToClose.front(); m_smallIdsToClose.pop_front(); @@ -1023,9 +1019,9 @@ void PlayerList::tick() { DisconnectPacket::eDisconnect_Closed); } } - LeaveCriticalSection(&m_closePlayersCS); + } - EnterCriticalSection(&m_kickPlayersCS); + { std::lock_guard lock(m_kickPlayersCS); while (!m_smallIdsToKick.empty()) { std::uint8_t smallId = m_smallIdsToKick.front(); m_smallIdsToKick.pop_front(); @@ -1063,7 +1059,7 @@ void PlayerList::tick() { } } } - LeaveCriticalSection(&m_kickPlayersCS); + } // Check our receiving players, and if they are dead see if we can replace // them @@ -1628,15 +1624,15 @@ bool PlayerList::canReceiveAllPackets(std::shared_ptr player) { } void PlayerList::kickPlayerByShortId(std::uint8_t networkSmallId) { - EnterCriticalSection(&m_kickPlayersCS); + { std::lock_guard lock(m_kickPlayersCS); m_smallIdsToKick.push_back(networkSmallId); - LeaveCriticalSection(&m_kickPlayersCS); + } } void PlayerList::closePlayerConnectionBySmallId(std::uint8_t networkSmallId) { - EnterCriticalSection(&m_closePlayersCS); + { std::lock_guard lock(m_closePlayersCS); m_smallIdsToClose.push_back(networkSmallId); - LeaveCriticalSection(&m_closePlayersCS); + } } bool PlayerList::isXuidBanned(PlayerUID xuid) { diff --git a/Minecraft.Client/Network/PlayerList.h b/Minecraft.Client/Network/PlayerList.h index b430128a9..77371f3cb 100644 --- a/Minecraft.Client/Network/PlayerList.h +++ b/Minecraft.Client/Network/PlayerList.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include "../../Minecraft.World/Util/ArrayWithLength.h" class ServerPlayer; @@ -31,9 +32,9 @@ private: // 4J Added std::vector m_bannedXuids; std::deque m_smallIdsToKick; - CRITICAL_SECTION m_kickPlayersCS; + std::mutex m_kickPlayersCS; std::deque m_smallIdsToClose; - CRITICAL_SECTION m_closePlayersCS; + std::mutex m_closePlayersCS; /* 4J - removed Set bans = new HashSet(); Set ipBans = new HashSet(); diff --git a/Minecraft.Client/Network/ServerChunkCache.cpp b/Minecraft.Client/Network/ServerChunkCache.cpp index 685133744..148857e6c 100644 --- a/Minecraft.Client/Network/ServerChunkCache.cpp +++ b/Minecraft.Client/Network/ServerChunkCache.cpp @@ -39,7 +39,6 @@ ServerChunkCache::ServerChunkCache(ServerLevel* level, ChunkStorage* storage, memset(m_unloadedCache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk*)); #endif - InitializeCriticalSectionAndSpinCount(&m_csLoadCreate, 4000); } // 4J-PB added @@ -58,7 +57,6 @@ ServerChunkCache::~ServerChunkCache() { auto itEnd = m_loadedChunkList.end(); for (auto it = m_loadedChunkList.begin(); it != itEnd; it++) delete *it; - DeleteCriticalSection(&m_csLoadCreate); } bool ServerChunkCache::hasChunk(int x, int z) { @@ -146,7 +144,7 @@ LevelChunk* ServerChunkCache::create( LevelChunk* lastChunk = chunk; if ((chunk == nullptr) || (chunk->x != x) || (chunk->z != z)) { - EnterCriticalSection(&m_csLoadCreate); + { std::lock_guard lock(m_csLoadCreate); chunk = load(x, z); if (chunk == nullptr) { if (source == nullptr) { @@ -158,8 +156,7 @@ LevelChunk* ServerChunkCache::create( if (chunk != nullptr) { chunk->load(); } - - LeaveCriticalSection(&m_csLoadCreate); + } #if defined(_WIN64) || defined(__LP64__) if (InterlockedCompareExchangeRelease64( @@ -172,7 +169,7 @@ LevelChunk* ServerChunkCache::create( #endif { // Successfully updated the cache - EnterCriticalSection(&m_csLoadCreate); + std::lock_guard lock(m_csLoadCreate); // 4J - added - this will run a recalcHeightmap if source is a // randomlevelsource, which has been split out from source::getChunk // so that we are doing it after the chunk has been added to the @@ -269,7 +266,6 @@ LevelChunk* ServerChunkCache::create( hasChunk(x, z - 1) && hasChunk(x, z + 1)) chunk->checkChests(this, x, z); - LeaveCriticalSection(&m_csLoadCreate); } else { // Something else must have updated the cache. Return that chunk and // discard this one @@ -653,12 +649,12 @@ bool ServerChunkCache::saveAllEntities() { PIXBeginNamedEvent(0, "Save all entities"); PIXBeginNamedEvent(0, "saving to NBT"); - EnterCriticalSection(&m_csLoadCreate); + { std::lock_guard lock(m_csLoadCreate); for (auto it = m_loadedChunkList.begin(); it != m_loadedChunkList.end(); ++it) { storage->saveEntities(level, *it); } - LeaveCriticalSection(&m_csLoadCreate); + } PIXEndNamedEvent(); PIXBeginNamedEvent(0, "Flushing"); @@ -670,7 +666,7 @@ bool ServerChunkCache::saveAllEntities() { } bool ServerChunkCache::save(bool force, ProgressListener* progressListener) { - EnterCriticalSection(&m_csLoadCreate); + std::lock_guard lock(m_csLoadCreate); int saves = 0; // 4J - added this to support progressListner @@ -701,7 +697,6 @@ bool ServerChunkCache::save(bool force, ProgressListener* progressListener) { save(chunk); chunk->setUnsaved(false); if (++saves == MAX_SAVES && !force) { - LeaveCriticalSection(&m_csLoadCreate); return false; } @@ -751,7 +746,6 @@ bool ServerChunkCache::save(bool force, ProgressListener* progressListener) { save(chunk); chunk->setUnsaved(false); if (++saves == MAX_SAVES && !force) { - LeaveCriticalSection(&m_csLoadCreate); return false; } @@ -776,13 +770,11 @@ bool ServerChunkCache::save(bool force, ProgressListener* progressListener) { if (force) { if (storage == nullptr) { - LeaveCriticalSection(&m_csLoadCreate); return true; } storage->flush(); } - LeaveCriticalSection(&m_csLoadCreate); return !maxSavesReached; } diff --git a/Minecraft.Client/Network/ServerChunkCache.h b/Minecraft.Client/Network/ServerChunkCache.h index abd7cb4b7..d39049ac6 100644 --- a/Minecraft.Client/Network/ServerChunkCache.h +++ b/Minecraft.Client/Network/ServerChunkCache.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../../Minecraft.World/Headers/net.minecraft.world.level.h" #include "../../Minecraft.World/IO/Files/File.h" #include "../../Minecraft.World/Headers/net.minecraft.world.level.storage.h" @@ -30,7 +31,7 @@ private: #endif // 4J - added for multithreaded support - CRITICAL_SECTION m_csLoadCreate; + std::mutex m_csLoadCreate; // 4J - size of cache is defined by size of one side - must be even int XZSIZE; int XZOFFSET; diff --git a/Minecraft.Client/Network/ServerConnection.cpp b/Minecraft.Client/Network/ServerConnection.cpp index 04285c507..270722a07 100644 --- a/Minecraft.Client/Network/ServerConnection.cpp +++ b/Minecraft.Client/Network/ServerConnection.cpp @@ -12,12 +12,11 @@ ServerConnection::ServerConnection(MinecraftServer* server) { // 4J - added initialiser connectionCounter = 0; - InitializeCriticalSection(&pending_cs); this->server = server; } -ServerConnection::~ServerConnection() { DeleteCriticalSection(&pending_cs); } +ServerConnection::~ServerConnection() {} // 4J - added to handle incoming connections, to replace thread that original // used to have @@ -35,18 +34,18 @@ void ServerConnection::addPlayerConnection( } void ServerConnection::handleConnection(std::shared_ptr uc) { - EnterCriticalSection(&pending_cs); + { std::lock_guard lock(pending_cs); pending.push_back(uc); - LeaveCriticalSection(&pending_cs); + } } void ServerConnection::stop() { - EnterCriticalSection(&pending_cs); + { std::lock_guard lock(pending_cs); for (unsigned int i = 0; i < pending.size(); i++) { std::shared_ptr uc = pending[i]; uc->connection->close(DisconnectPacket::eDisconnect_Closed); } - LeaveCriticalSection(&pending_cs); + } for (unsigned int i = 0; i < players.size(); i++) { std::shared_ptr player = players[i]; @@ -58,9 +57,10 @@ void ServerConnection::tick() { { // MGH - changed this so that the the CS lock doesn't cover the tick // (was causing a lockup when 2 players tried to join) - EnterCriticalSection(&pending_cs); - std::vector > tempPending = pending; - LeaveCriticalSection(&pending_cs); + std::vector > tempPending; + { std::lock_guard lock(pending_cs); + tempPending = pending; + } for (unsigned int i = 0; i < tempPending.size(); i++) { std::shared_ptr uc = tempPending[i]; @@ -76,13 +76,13 @@ void ServerConnection::tick() { } // now remove from the pending list - EnterCriticalSection(&pending_cs); + { std::lock_guard lock(pending_cs); for (unsigned int i = 0; i < pending.size(); i++) if (pending[i]->done) { pending.erase(pending.begin() + i); i--; } - LeaveCriticalSection(&pending_cs); + } for (unsigned int i = 0; i < players.size(); i++) { std::shared_ptr player = players[i]; diff --git a/Minecraft.Client/Network/ServerConnection.h b/Minecraft.Client/Network/ServerConnection.h index 68ab89448..c5dd92998 100644 --- a/Minecraft.Client/Network/ServerConnection.h +++ b/Minecraft.Client/Network/ServerConnection.h @@ -1,4 +1,5 @@ #pragma once +#include class PendingConnection; class PlayerConnection; class MinecraftServer; @@ -18,7 +19,7 @@ private: int connectionCounter; private: - CRITICAL_SECTION pending_cs; // 4J added + std::mutex pending_cs; // 4J added std::vector > pending; std::vector > players; diff --git a/Minecraft.Client/Platform/Common/C4JMemoryPool.h b/Minecraft.Client/Platform/Common/C4JMemoryPool.h index 9e9b4db95..2a9e08522 100644 --- a/Minecraft.Client/Platform/Common/C4JMemoryPool.h +++ b/Minecraft.Client/Platform/Common/C4JMemoryPool.h @@ -28,7 +28,6 @@ class C4JMemoryPoolFixed : public C4JMemoryPool uchar* m_memStart; // Beginning of memory pool uchar* m_memEnd; // End of memory pool uchar* m_next; // Num of next free block -// CRITICAL_SECTION m_CS; public: C4JMemoryPoolFixed() { @@ -59,7 +58,6 @@ public: m_numOfBlocks ]; m_memEnd = m_memStart + (m_sizeOfEachBlock * m_numOfBlocks); m_next = m_memStart; -// InitializeCriticalSection(&m_CS); } void DestroyPool() @@ -82,7 +80,6 @@ public: { if(size > m_sizeOfEachBlock) return ::malloc(size); -// EnterCriticalSection(&m_CS); if (m_numInitialized < m_numOfBlocks ) { uint* p = (uint*)AddrFromIndex( m_numInitialized ); @@ -103,7 +100,6 @@ public: m_next = nullptr; } } -// LeaveCriticalSection(&m_CS); return ret; } @@ -114,7 +110,6 @@ public: ::free(ptr); return; } -// EnterCriticalSection(&m_CS); if (m_next != nullptr) { (*(uint*)ptr) = IndexFromAddr( m_next ); @@ -126,7 +121,6 @@ public: m_next = (uchar*)ptr; } ++m_numFreeBlocks; -// LeaveCriticalSection(&m_CS); } }; // End pool class diff --git a/Minecraft.Client/Platform/Common/Consoles_App.cpp b/Minecraft.Client/Platform/Common/Consoles_App.cpp index 1c9fbfbbc..b8e05780a 100644 --- a/Minecraft.Client/Platform/Common/Consoles_App.cpp +++ b/Minecraft.Client/Platform/Common/Consoles_App.cpp @@ -178,17 +178,8 @@ CMinecraftApp::CMinecraftApp() { m_iDLCOfferC = 0; m_bAllDLCContentRetrieved = true; - InitializeCriticalSection(&csDLCDownloadQueue); m_bAllTMSContentRetrieved = true; m_bTickTMSDLCFiles = true; - InitializeCriticalSection(&csTMSPPDownloadQueue); - InitializeCriticalSection(&csAdditionalModelParts); - InitializeCriticalSection(&csAdditionalSkinBoxes); - InitializeCriticalSection(&csAnimOverrideBitmask); - InitializeCriticalSection(&csMemFilesLock); - InitializeCriticalSection(&csMemTPDLock); - - InitializeCriticalSection(&m_saveNotificationCriticalSection); m_saveNotificationDepth = 0; m_dwRequiredTexturePackID = 0; @@ -4579,7 +4570,7 @@ bool CMinecraftApp::isXuidDeadmau5(PlayerUID xuid) { void CMinecraftApp::AddMemoryTextureFile(const std::wstring& wName, std::uint8_t* pbData, unsigned int byteCount) { - EnterCriticalSection(&csMemFilesLock); + std::lock_guard lock(csMemFilesLock); // check it's not already in PMEMDATA pData = nullptr; auto it = m_MEM_Files.find(wName); @@ -4599,7 +4590,6 @@ void CMinecraftApp::AddMemoryTextureFile(const std::wstring& wName, } ++pData->ucRefCount; - LeaveCriticalSection(&csMemFilesLock); return; } @@ -4618,12 +4608,10 @@ void CMinecraftApp::AddMemoryTextureFile(const std::wstring& wName, // use the xuid to access the skin data m_MEM_Files[wName] = pData; - - LeaveCriticalSection(&csMemFilesLock); } void CMinecraftApp::RemoveMemoryTextureFile(const std::wstring& wName) { - EnterCriticalSection(&csMemFilesLock); + std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wName); if (it != m_MEM_Files.end()) { @@ -4642,17 +4630,16 @@ void CMinecraftApp::RemoveMemoryTextureFile(const std::wstring& wName) { m_MEM_Files.erase(wName); } } - LeaveCriticalSection(&csMemFilesLock); } bool CMinecraftApp::DefaultCapeExists() { std::wstring wTex = L"Special_Cape.png"; bool val = false; - EnterCriticalSection(&csMemFilesLock); + { std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wTex); if (it != m_MEM_Files.end()) val = true; - LeaveCriticalSection(&csMemFilesLock); + } return val; } @@ -4660,10 +4647,10 @@ bool CMinecraftApp::DefaultCapeExists() { bool CMinecraftApp::IsFileInMemoryTextures(const std::wstring& wName) { bool val = false; - EnterCriticalSection(&csMemFilesLock); + { std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wName); if (it != m_MEM_Files.end()) val = true; - LeaveCriticalSection(&csMemFilesLock); + } return val; } @@ -4671,19 +4658,18 @@ bool CMinecraftApp::IsFileInMemoryTextures(const std::wstring& wName) { void CMinecraftApp::GetMemFileDetails(const std::wstring& wName, std::uint8_t** ppbData, unsigned int* pByteCount) { - EnterCriticalSection(&csMemFilesLock); + std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wName); if (it != m_MEM_Files.end()) { PMEMDATA pData = (*it).second; *ppbData = pData->pbData; *pByteCount = pData->byteCount; } - LeaveCriticalSection(&csMemFilesLock); } void CMinecraftApp::AddMemoryTPDFile(int iConfig, std::uint8_t* pbData, unsigned int byteCount) { - EnterCriticalSection(&csMemTPDLock); + std::lock_guard lock(csMemTPDLock); // check it's not already in PMEMDATA pData = nullptr; auto it = m_MEM_TPD.find(iConfig); @@ -4695,12 +4681,10 @@ void CMinecraftApp::AddMemoryTPDFile(int iConfig, std::uint8_t* pbData, m_MEM_TPD[iConfig] = pData; } - - LeaveCriticalSection(&csMemTPDLock); } void CMinecraftApp::RemoveMemoryTPDFile(int iConfig) { - EnterCriticalSection(&csMemTPDLock); + std::lock_guard lock(csMemTPDLock); // check it's not already in PMEMDATA pData = nullptr; auto it = m_MEM_TPD.find(iConfig); @@ -4709,8 +4693,6 @@ void CMinecraftApp::RemoveMemoryTPDFile(int iConfig) { delete pData; m_MEM_TPD.erase(iConfig); } - - LeaveCriticalSection(&csMemTPDLock); } #if defined(_WINDOWS64) @@ -4719,24 +4701,23 @@ int CMinecraftApp::GetTPConfigVal(wchar_t* pwchDataFile) { return -1; } bool CMinecraftApp::IsFileInTPD(int iConfig) { bool val = false; - EnterCriticalSection(&csMemTPDLock); + { std::lock_guard lock(csMemTPDLock); auto it = m_MEM_TPD.find(iConfig); if (it != m_MEM_TPD.end()) val = true; - LeaveCriticalSection(&csMemTPDLock); + } return val; } void CMinecraftApp::GetTPD(int iConfig, std::uint8_t** ppbData, unsigned int* pByteCount) { - EnterCriticalSection(&csMemTPDLock); + std::lock_guard lock(csMemTPDLock); auto it = m_MEM_TPD.find(iConfig); if (it != m_MEM_TPD.end()) { PMEMDATA pData = (*it).second; *ppbData = pData->pbData; *pByteCount = pData->byteCount; } - LeaveCriticalSection(&csMemTPDLock); } // bool CMinecraftApp::UploadFileToGlobalStorage(int iQuadrant, @@ -5691,7 +5672,7 @@ DLC_INFO* CMinecraftApp::GetDLCInfoForFullOfferID(uint64_t ullOfferID_Full) { } void CMinecraftApp::EnterSaveNotificationSection() { - EnterCriticalSection(&m_saveNotificationCriticalSection); + std::lock_guard lock(m_saveNotificationCriticalSection); if (m_saveNotificationDepth++ == 0) { if (g_NetworkManager .IsInSession()) // this can be triggered from the front end if @@ -5707,11 +5688,10 @@ void CMinecraftApp::EnterSaveNotificationSection() { } } } - LeaveCriticalSection(&m_saveNotificationCriticalSection); } void CMinecraftApp::LeaveSaveNotificationSection() { - EnterCriticalSection(&m_saveNotificationCriticalSection); + std::lock_guard lock(m_saveNotificationCriticalSection); if (--m_saveNotificationDepth == 0) { if (g_NetworkManager .IsInSession()) // this can be triggered from the front end if @@ -5727,7 +5707,6 @@ void CMinecraftApp::LeaveSaveNotificationSection() { } } } - LeaveCriticalSection(&m_saveNotificationCriticalSection); } int CMinecraftApp::RemoteSaveThreadProc(void* lpParameter) { @@ -6662,7 +6641,7 @@ std::uint32_t CMinecraftApp::m_dwContentTypeA[e_Marketplace_MAX] = { unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, bool bPromote) { // lock access - EnterCriticalSection(&csDLCDownloadQueue); + { std::lock_guard lock(csDLCDownloadQueue); // If it's already in there, promote it to the top of the list int iPosition = 0; @@ -6675,7 +6654,6 @@ unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, if (pCurrent->eState == e_DLC_ContentState_Retrieving || pCurrent->eState == e_DLC_ContentState_Retrieved) { // already retrieved this - LeaveCriticalSection(&csDLCDownloadQueue); return 0; } else { // promote @@ -6685,7 +6663,6 @@ unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, m_DLCDownloadQueue.insert(m_DLCDownloadQueue.begin(), pCurrent); } - LeaveCriticalSection(&csDLCDownloadQueue); return 0; } } @@ -6699,7 +6676,7 @@ unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, m_DLCDownloadQueue.push_back(pDLCreq); m_bAllDLCContentRetrieved = false; - LeaveCriticalSection(&csDLCDownloadQueue); + } app.DebugPrintf("[Consoles_App] Added DLC request.\n"); return 1; @@ -6708,7 +6685,7 @@ unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, unsigned int CMinecraftApp::AddTMSPPFileTypeRequest(eDLCContentType eType, bool bPromote) { // lock access - EnterCriticalSection(&csTMSPPDownloadQueue); + std::lock_guard lock(csTMSPPDownloadQueue); // If it's already in there, promote it to the top of the list int iPosition = 0; @@ -6742,7 +6719,6 @@ unsigned int CMinecraftApp::AddTMSPPFileTypeRequest(eDLCContentType eType, if(bPromoted) { // re-ordered the list, so leave now - LeaveCriticalSection(&csTMSPPDownloadQueue); return 0; } */ @@ -6889,22 +6865,19 @@ unsigned int CMinecraftApp::AddTMSPPFileTypeRequest(eDLCContentType eType, } } - LeaveCriticalSection(&csTMSPPDownloadQueue); return 1; } bool CMinecraftApp::CheckTMSDLCCanStop() { - EnterCriticalSection(&csTMSPPDownloadQueue); + std::lock_guard lock(csTMSPPDownloadQueue); for (auto it = m_TMSPPDownloadQueue.begin(); it != m_TMSPPDownloadQueue.end(); ++it) { TMSPPRequest* pCurrent = *it; if (pCurrent->eState == e_TMS_ContentState_Retrieving) { - LeaveCriticalSection(&csTMSPPDownloadQueue); return false; } } - LeaveCriticalSection(&csTMSPPDownloadQueue); return true; } @@ -6920,13 +6893,12 @@ bool CMinecraftApp::RetrieveNextDLCContent() { // online. } - EnterCriticalSection(&csDLCDownloadQueue); + { std::lock_guard lock(csDLCDownloadQueue); for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); ++it) { DLCRequest* pCurrent = *it; if (pCurrent->eState == e_DLC_ContentState_Retrieving) { - LeaveCriticalSection(&csDLCDownloadQueue); return true; } } @@ -6952,11 +6924,10 @@ bool CMinecraftApp::RetrieveNextDLCContent() { app.DebugPrintf("RetrieveNextDLCContent - PROBLEM\n"); pCurrent->eState = e_DLC_ContentState_Retrieved; } - LeaveCriticalSection(&csDLCDownloadQueue); return true; } } - LeaveCriticalSection(&csDLCDownloadQueue); + } app.DebugPrintf("[Consoles_App] Finished downloading dlc content.\n"); return false; @@ -6969,7 +6940,7 @@ int CMinecraftApp::TMSPPFileReturned(void* pParam, int iPad, int iUserData, CMinecraftApp* pClass = (CMinecraftApp*)pParam; // find the right one in the vector - EnterCriticalSection(&pClass->csTMSPPDownloadQueue); + { std::lock_guard lock(pClass->csTMSPPDownloadQueue); for (auto it = pClass->m_TMSPPDownloadQueue.begin(); it != pClass->m_TMSPPDownloadQueue.end(); ++it) { TMSPPRequest* pCurrent = *it; @@ -7008,7 +6979,7 @@ int CMinecraftApp::TMSPPFileReturned(void* pParam, int iPad, int iUserData, break; } } - LeaveCriticalSection(&pClass->csTMSPPDownloadQueue); + } return 0; } @@ -7029,7 +7000,7 @@ void CMinecraftApp::ClearAndResetDLCDownloadQueue() { app.DebugPrintf("[Consoles_App] Clear and reset download queue.\n"); int iPosition = 0; - EnterCriticalSection(&csTMSPPDownloadQueue); + { std::lock_guard lock(csTMSPPDownloadQueue); for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); ++it) { DLCRequest* pCurrent = *it; @@ -7039,7 +7010,7 @@ void CMinecraftApp::ClearAndResetDLCDownloadQueue() { } m_DLCDownloadQueue.clear(); m_bAllDLCContentRetrieved = true; - LeaveCriticalSection(&csTMSPPDownloadQueue); + } } void CMinecraftApp::TickTMSPPFilesRetrieved() { @@ -7051,7 +7022,7 @@ void CMinecraftApp::TickTMSPPFilesRetrieved() { } void CMinecraftApp::ClearTMSPPFilesRetrieved() { int iPosition = 0; - EnterCriticalSection(&csTMSPPDownloadQueue); + { std::lock_guard lock(csTMSPPDownloadQueue); for (auto it = m_TMSPPDownloadQueue.begin(); it != m_TMSPPDownloadQueue.end(); ++it) { TMSPPRequest* pCurrent = *it; @@ -7061,7 +7032,7 @@ void CMinecraftApp::ClearTMSPPFilesRetrieved() { } m_TMSPPDownloadQueue.clear(); m_bAllTMSContentRetrieved = true; - LeaveCriticalSection(&csTMSPPDownloadQueue); + } } int CMinecraftApp::DLCOffersReturned(void* pParam, int iOfferC, @@ -7069,7 +7040,7 @@ int CMinecraftApp::DLCOffersReturned(void* pParam, int iOfferC, CMinecraftApp* pClass = (CMinecraftApp*)pParam; // find the right one in the vector - EnterCriticalSection(&pClass->csTMSPPDownloadQueue); + { std::lock_guard lock(pClass->csTMSPPDownloadQueue); for (auto it = pClass->m_DLCDownloadQueue.begin(); it != pClass->m_DLCDownloadQueue.end(); ++it) { DLCRequest* pCurrent = *it; @@ -7086,7 +7057,7 @@ int CMinecraftApp::DLCOffersReturned(void* pParam, int iOfferC, break; } } - LeaveCriticalSection(&pClass->csTMSPPDownloadQueue); + } return 0; } @@ -7101,18 +7072,16 @@ eDLCContentType CMinecraftApp::Find_eDLCContentType(std::uint32_t dwType) { bool CMinecraftApp::DLCContentRetrieved(eDLCMarketplaceType eType) { // If there's already a retrieve in progress, quit // we may have re-ordered the list, so need to check every item - EnterCriticalSection(&csDLCDownloadQueue); + std::lock_guard lock(csDLCDownloadQueue); for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); ++it) { DLCRequest* pCurrent = *it; if ((pCurrent->dwType == m_dwContentTypeA[eType]) && (pCurrent->eState == e_DLC_ContentState_Retrieved)) { - LeaveCriticalSection(&csDLCDownloadQueue); return true; } } - LeaveCriticalSection(&csDLCDownloadQueue); return false; } @@ -7125,8 +7094,8 @@ void CMinecraftApp::SetAdditionalSkinBoxes(std::uint32_t dwSkinID, std::vector* pvModelPart = new std::vector; std::vector* pvSkinBoxes = new std::vector; - EnterCriticalSection(&csAdditionalModelParts); - EnterCriticalSection(&csAdditionalSkinBoxes); + { std::lock_guard lock_mp(csAdditionalModelParts); + std::lock_guard lock_sb(csAdditionalSkinBoxes); app.DebugPrintf( "*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from " @@ -7148,9 +7117,7 @@ void CMinecraftApp::SetAdditionalSkinBoxes(std::uint32_t dwSkinID, m_AdditionalSkinBoxes.insert( std::pair*>(dwSkinID, pvSkinBoxes)); - - LeaveCriticalSection(&csAdditionalSkinBoxes); - LeaveCriticalSection(&csAdditionalModelParts); + } } std::vector* CMinecraftApp::SetAdditionalSkinBoxes( @@ -7160,8 +7127,8 @@ std::vector* CMinecraftApp::SetAdditionalSkinBoxes( Model* pModel = renderer->getModel(); std::vector* pvModelPart = new std::vector; - EnterCriticalSection(&csAdditionalModelParts); - EnterCriticalSection(&csAdditionalSkinBoxes); + { std::lock_guard lock_mp(csAdditionalModelParts); + std::lock_guard lock_sb(csAdditionalSkinBoxes); app.DebugPrintf( "*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from " "array of Skin Boxes\n", @@ -7181,15 +7148,13 @@ std::vector* CMinecraftApp::SetAdditionalSkinBoxes( m_AdditionalSkinBoxes.insert( std::pair*>(dwSkinID, pvSkinBoxA)); - - LeaveCriticalSection(&csAdditionalSkinBoxes); - LeaveCriticalSection(&csAdditionalModelParts); + } return pvModelPart; } std::vector* CMinecraftApp::GetAdditionalModelParts( std::uint32_t dwSkinID) { - EnterCriticalSection(&csAdditionalModelParts); + std::lock_guard lock(csAdditionalModelParts); std::vector* pvModelParts = nullptr; if (m_AdditionalModelParts.size() > 0) { auto it = m_AdditionalModelParts.find(dwSkinID); @@ -7198,13 +7163,12 @@ std::vector* CMinecraftApp::GetAdditionalModelParts( } } - LeaveCriticalSection(&csAdditionalModelParts); return pvModelParts; } std::vector* CMinecraftApp::GetAdditionalSkinBoxes( std::uint32_t dwSkinID) { - EnterCriticalSection(&csAdditionalSkinBoxes); + std::lock_guard lock(csAdditionalSkinBoxes); std::vector* pvSkinBoxes = nullptr; if (m_AdditionalSkinBoxes.size() > 0) { auto it = m_AdditionalSkinBoxes.find(dwSkinID); @@ -7213,12 +7177,11 @@ std::vector* CMinecraftApp::GetAdditionalSkinBoxes( } } - LeaveCriticalSection(&csAdditionalSkinBoxes); return pvSkinBoxes; } unsigned int CMinecraftApp::GetAnimOverrideBitmask(std::uint32_t dwSkinID) { - EnterCriticalSection(&csAnimOverrideBitmask); + std::lock_guard lock(csAnimOverrideBitmask); unsigned int uiAnimOverrideBitmask = 0L; if (m_AnimOverrides.size() > 0) { @@ -7228,25 +7191,22 @@ unsigned int CMinecraftApp::GetAnimOverrideBitmask(std::uint32_t dwSkinID) { } } - LeaveCriticalSection(&csAnimOverrideBitmask); return uiAnimOverrideBitmask; } void CMinecraftApp::SetAnimOverrideBitmask(std::uint32_t dwSkinID, unsigned int uiAnimOverrideBitmask) { // Make thread safe - EnterCriticalSection(&csAnimOverrideBitmask); + std::lock_guard lock(csAnimOverrideBitmask); if (m_AnimOverrides.size() > 0) { auto it = m_AnimOverrides.find(dwSkinID); if (it != m_AnimOverrides.end()) { - LeaveCriticalSection(&csAnimOverrideBitmask); return; // already in here } } m_AnimOverrides.insert(std::pair( dwSkinID, uiAnimOverrideBitmask)); - LeaveCriticalSection(&csAnimOverrideBitmask); } std::uint32_t CMinecraftApp::getSkinIdFromPath(const std::wstring& skin) { diff --git a/Minecraft.Client/Platform/Common/Consoles_App.h b/Minecraft.Client/Platform/Common/Consoles_App.h index b293dc8d5..41d289d65 100644 --- a/Minecraft.Client/Platform/Common/Consoles_App.h +++ b/Minecraft.Client/Platform/Common/Consoles_App.h @@ -1,6 +1,7 @@ #pragma once #include +#include // using namespace std; @@ -462,8 +463,8 @@ private: std::unordered_map m_MEM_Files; // for storing texture pack data files std::unordered_map m_MEM_TPD; - CRITICAL_SECTION csMemFilesLock; // For locking access to the above map - CRITICAL_SECTION csMemTPDLock; // For locking access to the above map + std::mutex csMemFilesLock; // For locking access to the above map + std::mutex csMemTPDLock; // For locking access to the above map VNOTIFICATIONS m_vNotifications; @@ -885,7 +886,7 @@ public: void LeaveSaveNotificationSection(); private: - CRITICAL_SECTION m_saveNotificationCriticalSection; + std::mutex m_saveNotificationCriticalSection; int m_saveNotificationDepth; // Download Status @@ -897,11 +898,11 @@ private: bool m_bAllDLCContentRetrieved; bool m_bAllTMSContentRetrieved; bool m_bTickTMSDLCFiles; - CRITICAL_SECTION csDLCDownloadQueue; - CRITICAL_SECTION csTMSPPDownloadQueue; - CRITICAL_SECTION csAdditionalModelParts; - CRITICAL_SECTION csAdditionalSkinBoxes; - CRITICAL_SECTION csAnimOverrideBitmask; + std::mutex csDLCDownloadQueue; + std::mutex csTMSPPDownloadQueue; + std::mutex csAdditionalModelParts; + std::mutex csAdditionalSkinBoxes; + std::mutex csAnimOverrideBitmask; bool m_bCorruptSaveDeleted; std::uint32_t m_dwAdditionalModelParts[XUSER_MAX_COUNT]; diff --git a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp index b0415e64e..ec14637b4 100644 --- a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp +++ b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp @@ -33,7 +33,6 @@ SonyLeaderboardManager::SonyLeaderboardManager() { m_openSessions = 0; - InitializeCriticalSection(&m_csViewsLock); m_running = false; m_threadScoreboard = nullptr; @@ -51,7 +50,6 @@ SonyLeaderboardManager::~SonyLeaderboardManager() { delete m_threadScoreboard; - DeleteCriticalSection(&m_csViewsLock); } int SonyLeaderboardManager::scoreboardThreadEntry(void* lpParam) { @@ -68,9 +66,9 @@ int SonyLeaderboardManager::scoreboardThreadEntry(void* lpParam) { self->scoreboardThreadInternal(); } - EnterCriticalSection(&self->m_csViewsLock); + { std::lock_guard lock(self->m_csViewsLock); needsWriting = self->m_views.size() > 0; - LeaveCriticalSection(&self->m_csViewsLock); + } // 4J Stu - We can't write while we aren't signed in to live if (!ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())) { @@ -166,9 +164,10 @@ void SonyLeaderboardManager::scoreboardThreadInternal() { // 4J-JEV: Writing no longer changes the manager state, // we'll manage the write queue seperately. - EnterCriticalSection(&m_csViewsLock); - bool hasWork = !m_views.empty(); - LeaveCriticalSection(&m_csViewsLock); + bool hasWork; + { std::lock_guard lock(m_csViewsLock); + hasWork = !m_views.empty(); + } if (hasWork) { setScore(); @@ -495,10 +494,11 @@ bool SonyLeaderboardManager::setScore() { // Get next job. - EnterCriticalSection(&m_csViewsLock); - RegisterScore rscore = m_views.front(); + RegisterScore rscore; + { std::lock_guard lock(m_csViewsLock); + rscore = m_views.front(); m_views.pop(); - LeaveCriticalSection(&m_csViewsLock); + } if (ProfileManager.IsGuest(rscore.m_iPad)) { app.DebugPrintf( @@ -521,9 +521,8 @@ bool SonyLeaderboardManager::setScore() { // Start emptying queue if leaderboards has been closed. if (ret == SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED) { - EnterCriticalSection(&m_csViewsLock); + std::lock_guard lock(m_csViewsLock); m_views.pop(); - LeaveCriticalSection(&m_csViewsLock); } // Error handling. @@ -685,7 +684,7 @@ bool SonyLeaderboardManager::WriteStats(unsigned int viewCount, ViewIn views) { // Write relevant parameters. // RegisterScore *regScore = reinterpret_cast(views); - EnterCriticalSection(&m_csViewsLock); + { std::lock_guard lock(m_csViewsLock); for (int i = 0; i < viewCount; i++) { app.DebugPrintf( "[SonyLeaderboardManager] WriteStats(), starting. difficulty=%i, " @@ -695,7 +694,7 @@ bool SonyLeaderboardManager::WriteStats(unsigned int viewCount, ViewIn views) { m_views.push(views[i]); } - LeaveCriticalSection(&m_csViewsLock); + } delete[] views; //*regScore; diff --git a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.h b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.h index f7946c510..258ab60c4 100644 --- a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.h +++ b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.h @@ -1,4 +1,5 @@ #pragma once +#include #include "Common/Leaderboards/LeaderboardManager.h" @@ -40,7 +41,7 @@ protected: std::queue m_views; - CRITICAL_SECTION m_csViewsLock; + std::mutex m_csViewsLock; EStatsState m_eStatsState; // State of the stats read // EFilterMode m_eFilterMode; diff --git a/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp b/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp index 4c1bbfca7..e54781483 100644 --- a/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp @@ -5,6 +5,7 @@ #include "../../Minecraft.Client/Level/MultiPlayerLevel.h" #include "../../Minecraft.World/Headers/net.minecraft.world.level.dimension.h" #include "../../Minecraft.World/Headers/net.minecraft.world.level.storage.h" +#include UIComponent_Panorama::UIComponent_Panorama(int iPad, void* initData, UILayer* parentLayer) @@ -42,25 +43,26 @@ void UIComponent_Panorama::tick() { if (!hasMovie()) return; Minecraft* pMinecraft = Minecraft::GetInstance(); - EnterCriticalSection(&pMinecraft->m_setLevelCS); - if (pMinecraft->level != nullptr) { - int64_t i64TimeOfDay = 0; - // are we in the Nether? - Leave the time as 0 if we are, so we show - // daylight - if (pMinecraft->level->dimension->id == 0) { - i64TimeOfDay = - pMinecraft->level->getLevelData()->getGameTime() % 24000; - } + { + std::lock_guard lock(pMinecraft->m_setLevelCS); + if (pMinecraft->level != nullptr) { + int64_t i64TimeOfDay = 0; + // are we in the Nether? - Leave the time as 0 if we are, so we show + // daylight + if (pMinecraft->level->dimension->id == 0) { + i64TimeOfDay = + pMinecraft->level->getLevelData()->getGameTime() % 24000; + } - if (i64TimeOfDay > 14000) { - setPanorama(false); + if (i64TimeOfDay > 14000) { + setPanorama(false); + } else { + setPanorama(true); + } } else { setPanorama(true); } - } else { - setPanorama(true); } - LeaveCriticalSection(&pMinecraft->m_setLevelCS); UIScene::tick(); } diff --git a/Minecraft.Client/Platform/Common/UI/UIController.cpp b/Minecraft.Client/Platform/Common/UI/UIController.cpp index 5e77f549d..ff8747a5c 100644 --- a/Minecraft.Client/Platform/Common/UI/UIController.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIController.cpp @@ -34,7 +34,7 @@ #endif -CRITICAL_SECTION UIController::ms_reloadSkinCS; +std::mutex UIController::ms_reloadSkinCS; bool UIController::ms_bReloadSkinCSInitialised = false; std::uint32_t UIController::m_dwTrialTimerLimitSecs = @@ -125,7 +125,7 @@ static void* RADLINK AllocateFunction(void* alloc_callback_user_data, size_t size_requested, size_t* size_returned) { UIController* controller = (UIController*)alloc_callback_user_data; - EnterCriticalSection(&controller->m_Allocatorlock); + std::lock_guard lock(controller->m_Allocatorlock); #if defined(EXCLUDE_IGGY_ALLOCATIONS_FROM_HEAP_INSPECTOR) void* alloc = __real_malloc(size_requested); #else @@ -136,14 +136,13 @@ static void* RADLINK AllocateFunction(void* alloc_callback_user_data, allocations[alloc] = size_requested; app.DebugPrintf(app.USER_SR, "Allocating %d, new total: %d\n", size_requested, UIController::iggyAllocCount); - LeaveCriticalSection(&controller->m_Allocatorlock); return alloc; } static void RADLINK DeallocateFunction(void* alloc_callback_user_data, void* ptr) { UIController* controller = (UIController*)alloc_callback_user_data; - EnterCriticalSection(&controller->m_Allocatorlock); + std::lock_guard lock(controller->m_Allocatorlock); size_t size = allocations[ptr]; UIController::iggyAllocCount -= size; allocations.erase(ptr); @@ -154,7 +153,6 @@ static void RADLINK DeallocateFunction(void* alloc_callback_user_data, #else free(ptr); #endif - LeaveCriticalSection(&controller->m_Allocatorlock); } UIController::UIController() { @@ -173,7 +171,7 @@ UIController::UIController() { m_eCurrentFont = m_eTargetFont = eFont_NotLoaded; #if defined(ENABLE_IGGY_ALLOCATOR) - InitializeCriticalSection(&m_Allocatorlock); + // std::mutex is default-constructed, no initialization needed #endif // 4J Stu - This is a bit of a hack until we change the Minecraft @@ -214,15 +212,12 @@ UIController::UIController() { m_accumulatedTicks = 0; m_lastUiSfx = 0; - InitializeCriticalSection(&m_navigationLock); - InitializeCriticalSection(&m_registeredCallbackScenesCS); // m_bSysUIShowing=false; m_bSystemUIShowing = false; if (!ms_bReloadSkinCSInitialised) { // MGH - added to prevent crash loading Iggy movies while the skins were // being reloaded - InitializeCriticalSection(&ms_reloadSkinCS); ms_bReloadSkinCSInitialised = true; } } @@ -620,27 +615,27 @@ void UIController::StartReloadSkinThread() { } int UIController::reloadSkinThreadProc(void* lpParam) { - EnterCriticalSection( - &ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy movies - // while the skins were being reloaded - UIController* controller = (UIController*)lpParam; - // Load new skin - controller->loadSkins(); + { + std::lock_guard lock(ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy movies + // while the skins were being reloaded + UIController* controller = (UIController*)lpParam; + // Load new skin + controller->loadSkins(); - // Reload all scene swf - for (int i = eUIGroup_Player1; i < eUIGroup_COUNT; ++i) { - controller->m_groups[i]->ReloadAll(); - } + // Reload all scene swf + for (int i = eUIGroup_Player1; i < eUIGroup_COUNT; ++i) { + controller->m_groups[i]->ReloadAll(); + } - // Always reload the fullscreen group - controller->m_groups[eUIGroup_Fullscreen]->ReloadAll(); + // Always reload the fullscreen group + controller->m_groups[eUIGroup_Fullscreen]->ReloadAll(); - // 4J Stu - Don't do this on windows, as we never navigated forwards to - // start with + // 4J Stu - Don't do this on windows, as we never navigated forwards to + // start with #if !(defined(_WINDOWS64) || defined(__linux__)) - controller->NavigateBack(0, false, eUIScene_COUNT, eUILayer_Tooltips); + controller->NavigateBack(0, false, eUIScene_COUNT, eUILayer_Tooltips); #endif - LeaveCriticalSection(&ms_reloadSkinCS); + } return 0; } @@ -1256,13 +1251,15 @@ bool UIController::NavigateToScene(int iPad, EUIScene scene, void* initData, PerformanceTimer timer; - EnterCriticalSection(&m_navigationLock); - SetMenuDisplayed(menuDisplayedPad, true); - bool success = - m_groups[(int)group]->NavigateToScene(iPad, scene, initData, layer); - if (success && group == eUIGroup_Fullscreen) - setFullscreenMenuDisplayed(true); - LeaveCriticalSection(&m_navigationLock); + bool success; + { + std::lock_guard lock(m_navigationLock); + SetMenuDisplayed(menuDisplayedPad, true); + success = + m_groups[(int)group]->NavigateToScene(iPad, scene, initData, layer); + if (success && group == eUIGroup_Fullscreen) + setFullscreenMenuDisplayed(true); + } timer.PrintElapsedTime(L"Navigate to scene"); @@ -1380,24 +1377,22 @@ UIScene* UIController::GetTopScene(int iPad, EUILayer layer, EUIGroup group) { } size_t UIController::RegisterForCallbackId(UIScene* scene) { - EnterCriticalSection(&m_registeredCallbackScenesCS); + std::lock_guard lock(m_registeredCallbackScenesCS); size_t newId = GetTickCount(); newId &= 0xFFFFFF; // Chop off the top byte, we don't need any more // accuracy than that newId |= (scene->getSceneType() << 24); // Add in the scene's type to help keep this unique m_registeredCallbackScenes[newId] = scene; - LeaveCriticalSection(&m_registeredCallbackScenesCS); return newId; } void UIController::UnregisterCallbackId(size_t id) { - EnterCriticalSection(&m_registeredCallbackScenesCS); + std::lock_guard lock(m_registeredCallbackScenesCS); auto it = m_registeredCallbackScenes.find(id); if (it != m_registeredCallbackScenes.end()) { m_registeredCallbackScenes.erase(it); } - LeaveCriticalSection(&m_registeredCallbackScenesCS); } UIScene* UIController::GetSceneFromCallbackId(size_t id) { @@ -1410,11 +1405,11 @@ UIScene* UIController::GetSceneFromCallbackId(size_t id) { } void UIController::EnterCallbackIdCriticalSection() { - EnterCriticalSection(&m_registeredCallbackScenesCS); + m_registeredCallbackScenesCS.lock(); } void UIController::LeaveCallbackIdCriticalSection() { - LeaveCriticalSection(&m_registeredCallbackScenesCS); + m_registeredCallbackScenesCS.unlock(); } void UIController::CloseAllPlayersScenes() { diff --git a/Minecraft.Client/Platform/Common/UI/UIController.h b/Minecraft.Client/Platform/Common/UI/UIController.h index 3eb04a6d4..c934e42cf 100644 --- a/Minecraft.Client/Platform/Common/UI/UIController.h +++ b/Minecraft.Client/Platform/Common/UI/UIController.h @@ -1,6 +1,7 @@ #pragma once // using namespace std; #include +#include #include "IUIController.h" #include "UIEnums.h" @@ -20,7 +21,7 @@ public: // MGH - added to prevent crash loading Iggy movies while the skins were // being reloaded - static CRITICAL_SECTION ms_reloadSkinCS; + static std::mutex ms_reloadSkinCS; static bool ms_bReloadSkinCSInitialised; protected: @@ -28,7 +29,7 @@ protected: UIComponent_DebugUIMarketingGuide* m_uiDebugMarketingGuide; private: - CRITICAL_SECTION m_navigationLock; + std::mutex m_navigationLock; static const int UI_REPEAT_KEY_DELAY_MS = 300; // How long from press until the first repeat @@ -165,7 +166,7 @@ private: // that are used in async callbacks so we // can safely handle when they get // destroyed - CRITICAL_SECTION m_registeredCallbackScenesCS; + std::mutex m_registeredCallbackScenesCS; ; public: @@ -190,7 +191,7 @@ protected: void postInit(); public: - CRITICAL_SECTION m_Allocatorlock; + std::mutex m_Allocatorlock; void SetupFont(); bool PendingFontChange(); bool UsingBitmapFont(); diff --git a/Minecraft.Client/Platform/Common/UI/UIScene.cpp b/Minecraft.Client/Platform/Common/UI/UIScene.cpp index f033acdb8..4c99ef35f 100644 --- a/Minecraft.Client/Platform/Common/UI/UIScene.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIScene.cpp @@ -1,4 +1,5 @@ #include "../../Minecraft.World/Platform/stdafx.h" +#include #include "UI.h" #include "UIScene.h" @@ -245,12 +246,11 @@ bool UIScene::mapElementsAndNames() { return true; } -extern CRITICAL_SECTION s_loadSkinCS; +extern std::mutex s_loadSkinCS; void UIScene::loadMovie() { - EnterCriticalSection( - &UIController::ms_reloadSkinCS); // MGH - added to prevent crash - // loading Iggy movies while the skins - // were being reloaded + UIController::ms_reloadSkinCS.lock(); // MGH - added to prevent crash + // loading Iggy movies while the skins + // were being reloaded std::wstring moviePath = getMoviePath(); #if defined(_WINDOWS64) @@ -320,7 +320,7 @@ void UIScene::loadMovie() { IggyPlayerSetUserdata(swf, this); // #ifdef _DEBUG - LeaveCriticalSection(&UIController::ms_reloadSkinCS); + UIController::ms_reloadSkinCS.unlock(); } void UIScene::getDebugMemoryUseRecursive(const std::wstring& moviePath, diff --git a/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp b/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp index 608c6b1b7..fce89e4d9 100644 --- a/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp +++ b/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp @@ -4,6 +4,7 @@ #include "../../../Minecraft.World/Platform/stdafx.h" #include +#include // #include #if defined(__linux__) && defined(__GLIBC__) #include @@ -1046,7 +1047,7 @@ bool trackStarted = false; volatile size_t sizeCheckMin = 1160; volatile size_t sizeCheckMax = 1160; volatile int sectCheck = 48; -CRITICAL_SECTION memCS; +std::mutex memCS; uint32_t tlsIdx; void* XMemAlloc(size_t dwSize, uint32_t dwAllocAttributes) { @@ -1057,33 +1058,34 @@ void* XMemAlloc(size_t dwSize, uint32_t dwAllocAttributes) { return p; } - EnterCriticalSection(&memCS); + void* p; + { + std::lock_guard lock(memCS); - void* p = XMemAllocDefault(dwSize + 16, dwAllocAttributes); - size_t realSize = XMemSizeDefault(p, dwAllocAttributes) - 16; + p = XMemAllocDefault(dwSize + 16, dwAllocAttributes); + size_t realSize = XMemSizeDefault(p, dwAllocAttributes) - 16; - if (trackEnable) { - int sect = ((int)TlsGetValue(tlsIdx)) & 0x3f; - *(((unsigned char*)p) + realSize) = sect; + if (trackEnable) { + int sect = ((int)TlsGetValue(tlsIdx)) & 0x3f; + *(((unsigned char*)p) + realSize) = sect; - if ((realSize >= sizeCheckMin) && (realSize <= sizeCheckMax) && - ((sect == sectCheck) || (sectCheck == -1))) { - app.DebugPrintf("Found one\n"); - } + if ((realSize >= sizeCheckMin) && (realSize <= sizeCheckMax) && + ((sect == sectCheck) || (sectCheck == -1))) { + app.DebugPrintf("Found one\n"); + } - if (p) { - totalAllocGen += realSize; - trackEnable = false; - int key = (sect << 26) | realSize; - int oldCount = allocCounts[key]; - allocCounts[key] = oldCount + 1; + if (p) { + totalAllocGen += realSize; + trackEnable = false; + int key = (sect << 26) | realSize; + int oldCount = allocCounts[key]; + allocCounts[key] = oldCount + 1; - trackEnable = true; + trackEnable = true; + } } } - LeaveCriticalSection(&memCS); - return p; } @@ -1114,22 +1116,23 @@ void WINAPI XMemFree(void* pAddress, uint32_t dwAllocAttributes) { totalAllocGen -= realSize; return; } - EnterCriticalSection(&memCS); - if (pAddress) { - size_t realSize = XMemSizeDefault(pAddress, dwAllocAttributes) - 16; + { + std::lock_guard lock(memCS); + if (pAddress) { + size_t realSize = XMemSizeDefault(pAddress, dwAllocAttributes) - 16; - if (trackEnable) { - int sect = *(((unsigned char*)pAddress) + realSize); - totalAllocGen -= realSize; - trackEnable = false; - int key = (sect << 26) | realSize; - int oldCount = allocCounts[key]; - allocCounts[key] = oldCount - 1; - trackEnable = true; + if (trackEnable) { + int sect = *(((unsigned char*)pAddress) + realSize); + totalAllocGen -= realSize; + trackEnable = false; + int key = (sect << 26) | realSize; + int oldCount = allocCounts[key]; + allocCounts[key] = oldCount - 1; + trackEnable = true; + } + XMemFreeDefault(pAddress, dwAllocAttributes); } - XMemFreeDefault(pAddress, dwAllocAttributes); } - LeaveCriticalSection(&memCS); } size_t WINAPI XMemSize(void* pAddress, uint32_t dwAllocAttributes) { @@ -1158,14 +1161,14 @@ void ResetMem() { trackEnable = true; trackStarted = true; totalAllocGen = 0; - InitializeCriticalSection(&memCS); tlsIdx = TlsAlloc(); } - EnterCriticalSection(&memCS); - trackEnable = false; - allocCounts.clear(); - trackEnable = true; - LeaveCriticalSection(&memCS); + { + std::lock_guard lock(memCS); + trackEnable = false; + allocCounts.clear(); + trackEnable = true; + } } void MemSect(int section) { diff --git a/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h b/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h index 1cd6dc5c8..91530b893 100644 --- a/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h +++ b/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h @@ -249,46 +249,6 @@ typedef HINSTANCE HMODULE; #define E_ABORT _HRESULT_TYPEDEF_(0x80004004L) #define E_NOINTERFACE _HRESULT_TYPEDEF_(0x80004002L) -typedef pthread_mutex_t RTL_CRITICAL_SECTION; -typedef pthread_mutex_t* PRTL_CRITICAL_SECTION; - -typedef RTL_CRITICAL_SECTION CRITICAL_SECTION; -typedef PRTL_CRITICAL_SECTION PCRITICAL_SECTION; -typedef PRTL_CRITICAL_SECTION LPCRITICAL_SECTION; - -static inline void InitializeCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(CriticalSection, &attr); - pthread_mutexattr_destroy(&attr); -} - -static inline void InitializeCriticalSectionAndSpinCount( - PRTL_CRITICAL_SECTION CriticalSection, ULONG SpinCount) { - // no spin count required because we use a recursive mutex - InitializeCriticalSection(CriticalSection); -} - -static inline void DeleteCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) { - pthread_mutex_destroy(CriticalSection); -} - -static inline void EnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) { - pthread_mutex_lock(CriticalSection); -} - -static inline void LeaveCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) { - pthread_mutex_unlock(CriticalSection); -} - -static inline ULONG TryEnterCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) { - return pthread_mutex_trylock(CriticalSection) == 0; -} - // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalmemorystatus static inline void GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer) { // TODO: Parse /proc/meminfo and set lpBuffer based on that. Probably will diff --git a/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp index 1c90eca18..b3ff25707 100644 --- a/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp @@ -4,6 +4,7 @@ #include "../../../Minecraft.World/Platform/stdafx.h" #include +#include #include "GameConfig/Minecraft.spa.h" #include "../../MinecraftServer.h" #include "../../Player/LocalPlayer.h" @@ -932,7 +933,7 @@ bool trackStarted = false; volatile size_t sizeCheckMin = 1160; volatile size_t sizeCheckMax = 1160; volatile int sectCheck = 48; -CRITICAL_SECTION memCS; +std::mutex memCS; uint32_t tlsIdx; void* XMemAlloc(size_t dwSize, uint32_t dwAllocAttributes) { @@ -943,33 +944,34 @@ void* XMemAlloc(size_t dwSize, uint32_t dwAllocAttributes) { return p; } - EnterCriticalSection(&memCS); + void* p; + { + std::lock_guard lock(memCS); - void* p = XMemAllocDefault(dwSize + 16, dwAllocAttributes); - size_t realSize = XMemSizeDefault(p, dwAllocAttributes) - 16; + p = XMemAllocDefault(dwSize + 16, dwAllocAttributes); + size_t realSize = XMemSizeDefault(p, dwAllocAttributes) - 16; - if (trackEnable) { - int sect = ((int)TlsGetValue(tlsIdx)) & 0x3f; - *(((unsigned char*)p) + realSize) = sect; + if (trackEnable) { + int sect = ((int)TlsGetValue(tlsIdx)) & 0x3f; + *(((unsigned char*)p) + realSize) = sect; - if ((realSize >= sizeCheckMin) && (realSize <= sizeCheckMax) && - ((sect == sectCheck) || (sectCheck == -1))) { - app.DebugPrintf("Found one\n"); - } + if ((realSize >= sizeCheckMin) && (realSize <= sizeCheckMax) && + ((sect == sectCheck) || (sectCheck == -1))) { + app.DebugPrintf("Found one\n"); + } - if (p) { - totalAllocGen += realSize; - trackEnable = false; - int key = (sect << 26) | realSize; - int oldCount = allocCounts[key]; - allocCounts[key] = oldCount + 1; + if (p) { + totalAllocGen += realSize; + trackEnable = false; + int key = (sect << 26) | realSize; + int oldCount = allocCounts[key]; + allocCounts[key] = oldCount + 1; - trackEnable = true; + trackEnable = true; + } } } - LeaveCriticalSection(&memCS); - return p; } @@ -1000,22 +1002,23 @@ void WINAPI XMemFree(void* pAddress, uint32_t dwAllocAttributes) { totalAllocGen -= realSize; return; } - EnterCriticalSection(&memCS); - if (pAddress) { - size_t realSize = XMemSizeDefault(pAddress, dwAllocAttributes) - 16; + { + std::lock_guard lock(memCS); + if (pAddress) { + size_t realSize = XMemSizeDefault(pAddress, dwAllocAttributes) - 16; - if (trackEnable) { - int sect = *(((unsigned char*)pAddress) + realSize); - totalAllocGen -= realSize; - trackEnable = false; - int key = (sect << 26) | realSize; - int oldCount = allocCounts[key]; - allocCounts[key] = oldCount - 1; - trackEnable = true; + if (trackEnable) { + int sect = *(((unsigned char*)pAddress) + realSize); + totalAllocGen -= realSize; + trackEnable = false; + int key = (sect << 26) | realSize; + int oldCount = allocCounts[key]; + allocCounts[key] = oldCount - 1; + trackEnable = true; + } + XMemFreeDefault(pAddress, dwAllocAttributes); } - XMemFreeDefault(pAddress, dwAllocAttributes); } - LeaveCriticalSection(&memCS); } size_t WINAPI XMemSize(void* pAddress, uint32_t dwAllocAttributes) { @@ -1044,14 +1047,14 @@ void ResetMem() { trackEnable = true; trackStarted = true; totalAllocGen = 0; - InitializeCriticalSection(&memCS); tlsIdx = TlsAlloc(); } - EnterCriticalSection(&memCS); - trackEnable = false; - allocCounts.clear(); - trackEnable = true; - LeaveCriticalSection(&memCS); + { + std::lock_guard lock(memCS); + trackEnable = false; + allocCounts.clear(); + trackEnable = true; + } } void MemSect(int section) { diff --git a/Minecraft.Client/Rendering/Chunk.cpp b/Minecraft.Client/Rendering/Chunk.cpp index 1743b524b..419454d62 100644 --- a/Minecraft.Client/Rendering/Chunk.cpp +++ b/Minecraft.Client/Rendering/Chunk.cpp @@ -9,6 +9,7 @@ #include "LevelRenderer.h" #include "../Utils/FrameProfiler.h" #include +#include int Chunk::updates = 0; @@ -92,7 +93,7 @@ void Chunk::reconcileRenderableTileEntities( // TODO - 4J see how input entity vector is set up and decide what way is best // to pass this to the function Chunk::Chunk(Level* level, LevelRenderer::rteMap& globalRenderableTileEntities, - CRITICAL_SECTION& globalRenderableTileEntities_cs, int x, int y, + std::mutex& globalRenderableTileEntities_cs, int x, int y, int z, ClipChunk* clipChunk) : globalRenderableTileEntities(&globalRenderableTileEntities), globalRenderableTileEntities_cs(&globalRenderableTileEntities_cs) { @@ -149,31 +150,31 @@ void Chunk::setPos(int x, int y, int z) { assigned = true; - EnterCriticalSection(&levelRenderer->m_csDirtyChunks); - unsigned char refCount = - levelRenderer->incGlobalChunkRefCount(x, y, z, level); - // printf("\t\t [inc] refcount %d at %d, %d, %d\n",refCount,x,y,z); + { + std::lock_guard lock(levelRenderer->m_csDirtyChunks); + unsigned char refCount = + levelRenderer->incGlobalChunkRefCount(x, y, z, level); + // printf("\t\t [inc] refcount %d at %d, %d, %d\n",refCount,x,y,z); - // int idx = levelRenderer->getGlobalIndexForChunk(x, y, z, level); + // int idx = levelRenderer->getGlobalIndexForChunk(x, y, z, level); - // If we're the first thing to be referencing this, mark it up as dirty to - // get rebuilt - if (refCount == 1) { - // printf("Setting %d %d %d dirty [%d]\n",x,y,z, idx); - // Chunks being made dirty in this way can be very numerous (eg the full - // visible area of the world at start up, or a whole edge of the world - // when moving). On account of this, don't want to stick them into our - // lock free queue that we would normally use for letting the render - // update thread know about this chunk. Instead, just set the flag to - // say this is dirty, and then pass a special value of 1 through to the - // lock free stack which lets that thread know that at least one chunk - // other than the ones in the stack itself have been made dirty. - levelRenderer->setGlobalChunkFlag(x, y, z, level, - LevelRenderer::CHUNK_FLAG_DIRTY); - PIXSetMarkerDeprecated(0, "Non-stack event pushed"); + // If we're the first thing to be referencing this, mark it up as dirty to + // get rebuilt + if (refCount == 1) { + // printf("Setting %d %d %d dirty [%d]\n",x,y,z, idx); + // Chunks being made dirty in this way can be very numerous (eg the full + // visible area of the world at start up, or a whole edge of the world + // when moving). On account of this, don't want to stick them into our + // lock free queue that we would normally use for letting the render + // update thread know about this chunk. Instead, just set the flag to + // say this is dirty, and then pass a special value of 1 through to the + // lock free stack which lets that thread know that at least one chunk + // other than the ones in the stack itself have been made dirty. + levelRenderer->setGlobalChunkFlag(x, y, z, level, + LevelRenderer::CHUNK_FLAG_DIRTY); + PIXSetMarkerDeprecated(0, "Non-stack event pushed"); + } } - - LeaveCriticalSection(&levelRenderer->m_csDirtyChunks); } void Chunk::translateToPos() { @@ -533,9 +534,10 @@ void Chunk::rebuild() { // globally in the levelrenderer, in a hashmap with a special key made up // from the dimension and chunk position (using same index as is used for // global flags) - EnterCriticalSection(globalRenderableTileEntities_cs); - reconcileRenderableTileEntities(renderableTileEntities); - LeaveCriticalSection(globalRenderableTileEntities_cs); + { + std::lock_guard lock(*globalRenderableTileEntities_cs); + reconcileRenderableTileEntities(renderableTileEntities); + } PIXEndNamedEvent(); // 4J - These removed items are now also removed from @@ -710,27 +712,28 @@ void Chunk::reset() { int oldKey = -1; bool retireRenderableTileEntities = false; - EnterCriticalSection(&levelRenderer->m_csDirtyChunks); - oldKey = levelRenderer->getGlobalIndexForChunk(x, y, z, level); - unsigned char refCount = - levelRenderer->decGlobalChunkRefCount(x, y, z, level); - assigned = false; - // printf("\t\t [dec] refcount %d at %d, %d, - //%d\n",refCount,x,y,z); - if (refCount == 0 && oldKey != -1) { - retireRenderableTileEntities = true; - int lists = oldKey * 2; - if (lists >= 0) { - lists += levelRenderer->chunkLists; - for (int i = 0; i < 2; i++) { - // 4J - added - clear any renderer data associated with this - // unused list - RenderManager.CBuffClear(lists + i); + { + std::lock_guard lock(levelRenderer->m_csDirtyChunks); + oldKey = levelRenderer->getGlobalIndexForChunk(x, y, z, level); + unsigned char refCount = + levelRenderer->decGlobalChunkRefCount(x, y, z, level); + assigned = false; + // printf("\t\t [dec] refcount %d at %d, %d, + //%d\n",refCount,x,y,z); + if (refCount == 0 && oldKey != -1) { + retireRenderableTileEntities = true; + int lists = oldKey * 2; + if (lists >= 0) { + lists += levelRenderer->chunkLists; + for (int i = 0; i < 2; i++) { + // 4J - added - clear any renderer data associated with this + // unused list + RenderManager.CBuffClear(lists + i); + } + levelRenderer->setGlobalChunkFlags(x, y, z, level, 0); } - levelRenderer->setGlobalChunkFlags(x, y, z, level, 0); } } - LeaveCriticalSection(&levelRenderer->m_csDirtyChunks); if (retireRenderableTileEntities) { levelRenderer->retireRenderableTileEntitiesForChunkKey(oldKey); diff --git a/Minecraft.Client/Rendering/Chunk.h b/Minecraft.Client/Rendering/Chunk.h index ea24723b7..a73808eeb 100644 --- a/Minecraft.Client/Rendering/Chunk.h +++ b/Minecraft.Client/Rendering/Chunk.h @@ -56,12 +56,12 @@ public: private: LevelRenderer::rteMap* globalRenderableTileEntities; - CRITICAL_SECTION* globalRenderableTileEntities_cs; + std::mutex* globalRenderableTileEntities_cs; bool assigned; public: Chunk(Level* level, LevelRenderer::rteMap& globalRenderableTileEntities, - CRITICAL_SECTION& globalRenderableTileEntities_cs, int x, int y, + std::mutex& globalRenderableTileEntities_cs, int x, int y, int z, ClipChunk* clipChunk); Chunk(); diff --git a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp index e90405934..616f770a8 100644 --- a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp +++ b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp @@ -4,7 +4,7 @@ #include "ProgressRenderer.h" #include "../../../Minecraft.World/Platform/System.h" -CRITICAL_SECTION ProgressRenderer::s_progress; +std::mutex ProgressRenderer::s_progress; ProgressRenderer::ProgressRenderer(Minecraft* minecraft) { status = -1; @@ -33,10 +33,11 @@ void ProgressRenderer::_progressStart(int title) { // throw new StopGameException(); // 4J - removed } - EnterCriticalSection(&ProgressRenderer::s_progress); - lastPercent = 0; - this->title = title; - LeaveCriticalSection(&ProgressRenderer::s_progress); + { + std::lock_guard lock(ProgressRenderer::s_progress); + lastPercent = 0; + this->title = title; + } } @@ -47,10 +48,11 @@ void ProgressRenderer::progressStage(int status) { } lastTime = 0; - EnterCriticalSection(&ProgressRenderer::s_progress); - setType(eProgressStringType_ID); - this->status = status; - LeaveCriticalSection(&ProgressRenderer::s_progress); + { + std::lock_guard lock(ProgressRenderer::s_progress); + m_eType = eProgressStringType_ID; + this->status = status; + } progressStagePercentage(-1); lastTime = 0; } @@ -58,57 +60,62 @@ void ProgressRenderer::progressStage(int status) { void ProgressRenderer::progressStagePercentage(int i) { // 4J Stu - Removing all progressRenderer rendering. This will be replaced // on the xbox - EnterCriticalSection(&ProgressRenderer::s_progress); - lastPercent = i; - LeaveCriticalSection(&ProgressRenderer::s_progress); + { + std::lock_guard lock(ProgressRenderer::s_progress); + lastPercent = i; + } } int ProgressRenderer::getCurrentPercent() { int returnValue = 0; - EnterCriticalSection(&ProgressRenderer::s_progress); - returnValue = lastPercent; - LeaveCriticalSection(&ProgressRenderer::s_progress); + { + std::lock_guard lock(ProgressRenderer::s_progress); + returnValue = lastPercent; + } return returnValue; } int ProgressRenderer::getCurrentTitle() { - EnterCriticalSection(&ProgressRenderer::s_progress); - int returnValue = title; - LeaveCriticalSection(&ProgressRenderer::s_progress); + int returnValue; + { + std::lock_guard lock(ProgressRenderer::s_progress); + returnValue = title; + } return returnValue; } int ProgressRenderer::getCurrentStatus() { - EnterCriticalSection(&ProgressRenderer::s_progress); - int returnValue = status; - LeaveCriticalSection(&ProgressRenderer::s_progress); + int returnValue; + { + std::lock_guard lock(ProgressRenderer::s_progress); + returnValue = status; + } return returnValue; } ProgressRenderer::eProgressStringType ProgressRenderer::getType() { - EnterCriticalSection(&ProgressRenderer::s_progress); - eProgressStringType returnValue = m_eType; - LeaveCriticalSection(&ProgressRenderer::s_progress); + eProgressStringType returnValue; + { + std::lock_guard lock(ProgressRenderer::s_progress); + returnValue = m_eType; + } return returnValue; } void ProgressRenderer::setType(eProgressStringType eType) { - EnterCriticalSection(&ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); m_eType = eType; - LeaveCriticalSection(&ProgressRenderer::s_progress); } void ProgressRenderer::progressStage(std::wstring& wstrText) { - EnterCriticalSection(&ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); m_wstrText = wstrText; - setType(eProgressStringType_String); - LeaveCriticalSection(&ProgressRenderer::s_progress); + m_eType = eProgressStringType_String; } std::wstring& ProgressRenderer::getProgressString(void) { - EnterCriticalSection(&ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); std::wstring& temp = m_wstrText; - LeaveCriticalSection(&ProgressRenderer::s_progress); return temp; } diff --git a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h index 978ffeefc..97d35f0ef 100644 --- a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h +++ b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../../../Minecraft.World/Util/ProgressListener.h" class ProgressRenderer : public ProgressListener { @@ -9,7 +10,7 @@ public: // on a save transfer }; - static CRITICAL_SECTION s_progress; + static std::mutex s_progress; int getCurrentPercent(); int getCurrentTitle(); diff --git a/Minecraft.Client/Rendering/GameRenderer.cpp b/Minecraft.Client/Rendering/GameRenderer.cpp index fc429f5c2..bbd65503c 100644 --- a/Minecraft.Client/Rendering/GameRenderer.cpp +++ b/Minecraft.Client/Rendering/GameRenderer.cpp @@ -66,7 +66,7 @@ std::vector GameRenderer::m_deleteStackCompressedTileStorage; std::vector GameRenderer::m_deleteStackSparseDataStorage; #endif -CRITICAL_SECTION GameRenderer::m_csDeleteStack; +std::mutex GameRenderer::m_csDeleteStack; ResourceLocation GameRenderer::RAIN_LOCATION = ResourceLocation(TN_ENVIRONMENT_RAIN); @@ -170,7 +170,6 @@ GameRenderer::GameRenderer(Minecraft* mc) { eUpdateEventCount, C4JThread::EventArray::e_modeAutoClear); m_updateEvents->Set(eUpdateEventIsFinished); - InitializeCriticalSection(&m_csDeleteStack); m_updateThread = new C4JThread(runUpdate, nullptr, "Chunk update"); m_updateThread->SetProcessor(CPU_CORE_CHUNK_UPDATE); m_updateThread->Run(); @@ -1045,27 +1044,27 @@ void GameRenderer::renderLevel(float a) { renderLevel(a, 0); } #if defined(MULTITHREAD_ENABLE) // Request that an item be deleted, when it is safe to do so void GameRenderer::AddForDelete(uint8_t* deleteThis) { - EnterCriticalSection(&m_csDeleteStack); + m_csDeleteStack.lock(); m_deleteStackByte.push_back(deleteThis); } void GameRenderer::AddForDelete(SparseLightStorage* deleteThis) { - EnterCriticalSection(&m_csDeleteStack); + m_csDeleteStack.lock(); m_deleteStackSparseLightStorage.push_back(deleteThis); } void GameRenderer::AddForDelete(CompressedTileStorage* deleteThis) { - EnterCriticalSection(&m_csDeleteStack); + m_csDeleteStack.lock(); m_deleteStackCompressedTileStorage.push_back(deleteThis); } void GameRenderer::AddForDelete(SparseDataStorage* deleteThis) { - EnterCriticalSection(&m_csDeleteStack); + m_csDeleteStack.lock(); m_deleteStackSparseDataStorage.push_back(deleteThis); } void GameRenderer::FinishedReassigning() { - LeaveCriticalSection(&m_csDeleteStack); + m_csDeleteStack.unlock(); } int GameRenderer::runUpdate(void* lpParam) { @@ -1124,22 +1123,24 @@ int GameRenderer::runUpdate(void* lpParam) { // We've got stacks for things that can only safely be deleted whilst // this thread isn't updating things - delete those things now - EnterCriticalSection(&m_csDeleteStack); - for (unsigned int i = 0; i < m_deleteStackByte.size(); i++) - delete m_deleteStackByte[i]; - m_deleteStackByte.clear(); - for (unsigned int i = 0; i < m_deleteStackSparseLightStorage.size(); - i++) - delete m_deleteStackSparseLightStorage[i]; - m_deleteStackSparseLightStorage.clear(); - for (unsigned int i = 0; i < m_deleteStackCompressedTileStorage.size(); - i++) - delete m_deleteStackCompressedTileStorage[i]; - m_deleteStackCompressedTileStorage.clear(); - for (unsigned int i = 0; i < m_deleteStackSparseDataStorage.size(); i++) - delete m_deleteStackSparseDataStorage[i]; - m_deleteStackSparseDataStorage.clear(); - LeaveCriticalSection(&m_csDeleteStack); + { + std::lock_guard lock(m_csDeleteStack); + for (unsigned int i = 0; i < m_deleteStackByte.size(); i++) + delete m_deleteStackByte[i]; + m_deleteStackByte.clear(); + for (unsigned int i = 0; i < m_deleteStackSparseLightStorage.size(); + i++) + delete m_deleteStackSparseLightStorage[i]; + m_deleteStackSparseLightStorage.clear(); + for (unsigned int i = 0; + i < m_deleteStackCompressedTileStorage.size(); i++) + delete m_deleteStackCompressedTileStorage[i]; + m_deleteStackCompressedTileStorage.clear(); + for (unsigned int i = 0; + i < m_deleteStackSparseDataStorage.size(); i++) + delete m_deleteStackSparseDataStorage[i]; + m_deleteStackSparseDataStorage.clear(); + } // PIXEndNamedEvent(); diff --git a/Minecraft.Client/Rendering/GameRenderer.h b/Minecraft.Client/Rendering/GameRenderer.h index 0659f53af..c92136b3b 100644 --- a/Minecraft.Client/Rendering/GameRenderer.h +++ b/Minecraft.Client/Rendering/GameRenderer.h @@ -9,6 +9,7 @@ class SparseLightStorage; class CompressedTileStorage; class SparseDataStorage; +#include #include "../../Minecraft.World/Util/SmoothFloat.h" #include "../../Minecraft.World/Util/C4JThread.h" #include "../Textures/ResourceLocation.h" @@ -191,7 +192,7 @@ public: static std::vector m_deleteStackCompressedTileStorage; static std::vector m_deleteStackSparseDataStorage; - static CRITICAL_SECTION m_csDeleteStack; + static std::mutex m_csDeleteStack; static void AddForDelete(uint8_t* deleteThis); static void AddForDelete(SparseLightStorage* deleteThis); static void AddForDelete(CompressedTileStorage* deleteThis); diff --git a/Minecraft.Client/Rendering/LevelRenderer.cpp b/Minecraft.Client/Rendering/LevelRenderer.cpp index 38405101d..293bbaca6 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.cpp +++ b/Minecraft.Client/Rendering/LevelRenderer.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "../Platform/stdafx.h" #include "LevelRenderer.h" @@ -163,11 +164,7 @@ LevelRenderer::LevelRenderer(Minecraft* mc, Textures* textures) { lastPlayerCount[i] = 0; } - InitializeCriticalSection(&m_csDirtyChunks); - InitializeCriticalSection(&m_csRenderableTileEntities); -#if defined(_LARGE_WORLDS) - InitializeCriticalSection(&m_csChunkFlags); -#endif + // std::mutex members are default-constructed dirtyChunkPresent = false; lastDirtyChunkFound = 0; @@ -395,10 +392,11 @@ void LevelRenderer::setLevel(int playerIndex, MultiPlayerLevel* level) { // actually exiting the game, so only when the primary player sets there // level to nullptr if (playerIndex == ProfileManager.GetPrimaryPad()) { - EnterCriticalSection(&m_csRenderableTileEntities); - renderableTileEntities.clear(); - m_renderableTileEntitiesPendingRemoval.clear(); - LeaveCriticalSection(&m_csRenderableTileEntities); + { + std::lock_guard lock(m_csRenderableTileEntities); + renderableTileEntities.clear(); + m_renderableTileEntitiesPendingRemoval.clear(); + } } } } @@ -428,7 +426,6 @@ void LevelRenderer::allChanged(int playerIndex) { // to add it back then: If this CS is entered before DisableUpdateThread is // called then (on 360 at least) we can get a deadlock when starting a game // in splitscreen. - // EnterCriticalSection(&m_csDirtyChunks); if (level[playerIndex] == nullptr) { return; } @@ -517,8 +514,6 @@ void LevelRenderer::allChanged(int playerIndex) { Minecraft::GetInstance()->gameRenderer->EnableUpdateThread(); - // 4J Stu - Remove. See comment above. - // LeaveCriticalSection(&m_csDirtyChunks); } void LevelRenderer::renderEntities(Vec3* cam, Culler* culler, float a) { @@ -619,21 +614,21 @@ void LevelRenderer::renderEntities(Vec3* cam, Culler* culler, float a) { // 4J - have restructed this so that the tile entities are stored within a // hashmap by chunk/dimension index. The index is calculated in the same way // as the global flags. - EnterCriticalSection(&m_csRenderableTileEntities); - for (auto it = renderableTileEntities.begin(); - it != renderableTileEntities.end(); it++) { - int idx = it->first; - // Don't render if it isn't in the same dimension as this player - if (!isGlobalIndexInSameDimension(idx, level[playerIndex])) continue; + { + std::lock_guard lock(m_csRenderableTileEntities); + for (auto it = renderableTileEntities.begin(); + it != renderableTileEntities.end(); it++) { + int idx = it->first; + // Don't render if it isn't in the same dimension as this player + if (!isGlobalIndexInSameDimension(idx, level[playerIndex])) continue; - for (auto it2 = it->second.tiles.begin(); - it2 != it->second.tiles.end(); it2++) { - TileEntityRenderDispatcher::instance->render(*it2, a); + for (auto it2 = it->second.tiles.begin(); + it2 != it->second.tiles.end(); it2++) { + TileEntityRenderDispatcher::instance->render(*it2, a); + } } } - LeaveCriticalSection(&m_csRenderableTileEntities); - mc->gameRenderer->turnOffLightLayer(a); // 4J - brought forward from 1.8.2 } @@ -653,7 +648,7 @@ std::wstring LevelRenderer::gatherStats2() { } void LevelRenderer::resortChunks(int xc, int yc, int zc) { - EnterCriticalSection(&m_csDirtyChunks); + std::lock_guard lock(m_csDirtyChunks); xc -= CHUNK_XZSIZE / 2; yc -= CHUNK_SIZE / 2; zc -= CHUNK_XZSIZE / 2; @@ -702,7 +697,6 @@ void LevelRenderer::resortChunks(int xc, int yc, int zc) { } } nonStackDirtyChunksAdded(); - LeaveCriticalSection(&m_csDirtyChunks); } int LevelRenderer::render(std::shared_ptr player, int layer, @@ -1730,7 +1724,7 @@ bool LevelRenderer::updateDirtyChunks() { PIXAddNamedCounter(((float)memAlloc) / (1024.0f * 1024.0f), "Command buffer allocations"); bool onlyRebuild = (memAlloc >= MAX_COMMANDBUFFER_ALLOCATIONS); - EnterCriticalSection(&m_csDirtyChunks); + std::unique_lock dirtyChunksLock(m_csDirtyChunks); // Move any dirty chunks stored in the lock free stack into global flags int index = 0; @@ -1952,7 +1946,7 @@ bool LevelRenderer::updateDirtyChunks() { permaChunk[index].makeCopyForRebuild(chunk); ++index; } - LeaveCriticalSection(&m_csDirtyChunks); + dirtyChunksLock.unlock(); --index; // Bring it back into 0 counted range @@ -2043,7 +2037,7 @@ bool LevelRenderer::updateDirtyChunks() { // this copy. The copy will then be guaranteed to be consistent // whilst rebuilding takes place outside of that critical section. permaChunk.makeCopyForRebuild(chunk); - LeaveCriticalSection(&m_csDirtyChunks); + dirtyChunksLock.unlock(); } // static int64_t totalTime = 0; // static int64_t countTime = 0; @@ -2070,7 +2064,7 @@ bool LevelRenderer::updateDirtyChunks() { } else { dirtyChunkPresent = false; } - LeaveCriticalSection(&m_csDirtyChunks); + dirtyChunksLock.unlock(); return false; } @@ -2295,7 +2289,6 @@ void LevelRenderer::setDirty(int x0, int y0, int z0, int x1, int y1, int z1, // come from when connection is being ticked outside of normal level tick, // and player won't be set up if (level == nullptr) level = this->level[mc->player->GetXboxPad()]; - // EnterCriticalSection(&m_csDirtyChunks); int _x0 = Mth::intFloorDiv(x0, CHUNK_XZSIZE); int _y0 = Mth::intFloorDiv(y0, CHUNK_SIZE); int _z0 = Mth::intFloorDiv(z0, CHUNK_XZSIZE); @@ -2385,7 +2378,6 @@ void LevelRenderer::setDirty(int x0, int y0, int z0, int x1, int y1, int z1, } } } - // LeaveCriticalSection(&m_csDirtyChunks); } void LevelRenderer::tileChanged(int x, int y, int z) { @@ -3687,12 +3679,9 @@ void LevelRenderer::setGlobalChunkFlags(int x, int y, int z, Level* level, int index = getGlobalIndexForChunk(x, y, z, level); if (index != -1) { #if defined(_LARGE_WORLDS) - EnterCriticalSection(&m_csChunkFlags); + std::lock_guard lock(m_csChunkFlags); #endif globalChunkFlags[index] = flags; -#if defined(_LARGE_WORLDS) - LeaveCriticalSection(&m_csChunkFlags); -#endif } } @@ -3702,12 +3691,9 @@ void LevelRenderer::setGlobalChunkFlag(int index, unsigned char flag, if (index != -1) { #if defined(_LARGE_WORLDS) - EnterCriticalSection(&m_csChunkFlags); + std::lock_guard lock(m_csChunkFlags); #endif globalChunkFlags[index] |= sflag; -#if defined(_LARGE_WORLDS) - LeaveCriticalSection(&m_csChunkFlags); -#endif } } @@ -3718,12 +3704,9 @@ void LevelRenderer::setGlobalChunkFlag(int x, int y, int z, Level* level, int index = getGlobalIndexForChunk(x, y, z, level); if (index != -1) { #if defined(_LARGE_WORLDS) - EnterCriticalSection(&m_csChunkFlags); + std::lock_guard lock(m_csChunkFlags); #endif globalChunkFlags[index] |= sflag; -#if defined(_LARGE_WORLDS) - LeaveCriticalSection(&m_csChunkFlags); -#endif } } @@ -3747,12 +3730,9 @@ void LevelRenderer::clearGlobalChunkFlag(int x, int y, int z, Level* level, int index = getGlobalIndexForChunk(x, y, z, level); if (index != -1) { #if defined(_LARGE_WORLDS) - EnterCriticalSection(&m_csChunkFlags); + std::lock_guard lock(m_csChunkFlags); #endif globalChunkFlags[index] &= ~sflag; -#if defined(_LARGE_WORLDS) - LeaveCriticalSection(&m_csChunkFlags); -#endif } } @@ -3844,19 +3824,19 @@ void LevelRenderer::eraseRenderableTileEntity_Locked( void LevelRenderer::retireRenderableTileEntitiesForChunkKey(int key) { if (key == -1) return; - EnterCriticalSection(&m_csRenderableTileEntities); - renderableTileEntities.erase(key); - m_renderableTileEntitiesPendingRemoval.erase(key); - LeaveCriticalSection(&m_csRenderableTileEntities); + { + std::lock_guard lock(m_csRenderableTileEntities); + renderableTileEntities.erase(key); + m_renderableTileEntitiesPendingRemoval.erase(key); + } } // 4J added void LevelRenderer::fullyFlagRenderableTileEntitiesToBeRemoved() { FRAME_PROFILE_SCOPE(RenderableTileEntityCleanup); - EnterCriticalSection(&m_csRenderableTileEntities); + std::lock_guard lock(m_csRenderableTileEntities); if (m_renderableTileEntitiesPendingRemoval.empty()) { - LeaveCriticalSection(&m_csRenderableTileEntities); return; } @@ -3886,7 +3866,6 @@ void LevelRenderer::fullyFlagRenderableTileEntitiesToBeRemoved() { } } m_renderableTileEntitiesPendingRemoval.clear(); - LeaveCriticalSection(&m_csRenderableTileEntities); } LevelRenderer::DestroyedTileManager::RecentTile::RecentTile(int x, int y, int z, @@ -3897,11 +3876,10 @@ LevelRenderer::DestroyedTileManager::RecentTile::RecentTile(int x, int y, int z, } LevelRenderer::DestroyedTileManager::DestroyedTileManager() { - InitializeCriticalSection(&m_csDestroyedTiles); + // std::mutex is default-constructed } LevelRenderer::DestroyedTileManager::~DestroyedTileManager() { - DeleteCriticalSection(&m_csDestroyedTiles); for (unsigned int i = 0; i < m_destroyedTiles.size(); i++) { delete m_destroyedTiles[i]; } @@ -3911,7 +3889,7 @@ LevelRenderer::DestroyedTileManager::~DestroyedTileManager() { // be called before it actually is) void LevelRenderer::DestroyedTileManager::destroyingTileAt(Level* level, int x, int y, int z) { - EnterCriticalSection(&m_csDestroyedTiles); + std::lock_guard lock(m_csDestroyedTiles); // Store a list of AABBs that the tile to be destroyed would have made, // before we go and destroy it. This is made slightly more complicated as @@ -3928,8 +3906,6 @@ void LevelRenderer::DestroyedTileManager::destroyingTileAt(Level* level, int x, } m_destroyedTiles.push_back(recentTile); - - LeaveCriticalSection(&m_csDestroyedTiles); } // For chunk rebuilding to inform the manager that a chunk (a 16x16x16 tile @@ -3937,7 +3913,7 @@ void LevelRenderer::DestroyedTileManager::destroyingTileAt(Level* level, int x, void LevelRenderer::DestroyedTileManager::updatedChunkAt(Level* level, int x, int y, int z, int veryNearCount) { - EnterCriticalSection(&m_csDestroyedTiles); + std::lock_guard lock(m_csDestroyedTiles); // There's 2 stages to this. This function is called when a renderer chunk // has been rebuilt, but that chunk's render data might be grouped @@ -3979,15 +3955,13 @@ void LevelRenderer::DestroyedTileManager::updatedChunkAt(Level* level, int x, } } } - - LeaveCriticalSection(&m_csDestroyedTiles); } // For game to get any AABBs that the user should be colliding with as render // data has not yet been updated void LevelRenderer::DestroyedTileManager::addAABBs(Level* level, AABB* box, AABBList* boxes) { - EnterCriticalSection(&m_csDestroyedTiles); + std::lock_guard lock(m_csDestroyedTiles); for (unsigned int i = 0; i < m_destroyedTiles.size(); i++) { if (m_destroyedTiles[i]->level == level) { @@ -4009,11 +3983,10 @@ void LevelRenderer::DestroyedTileManager::addAABBs(Level* level, AABB* box, } } - LeaveCriticalSection(&m_csDestroyedTiles); } void LevelRenderer::DestroyedTileManager::tick() { - EnterCriticalSection(&m_csDestroyedTiles); + std::lock_guard lock(m_csDestroyedTiles); // Remove any tiles that have timed out for (unsigned int i = 0; i < m_destroyedTiles.size();) { @@ -4025,8 +3998,6 @@ void LevelRenderer::DestroyedTileManager::tick() { i++; } } - - LeaveCriticalSection(&m_csDestroyedTiles); } #if defined(_LARGE_WORLDS) diff --git a/Minecraft.Client/Rendering/LevelRenderer.h b/Minecraft.Client/Rendering/LevelRenderer.h index 006d357f4..7e187e998 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.h +++ b/Minecraft.Client/Rendering/LevelRenderer.h @@ -8,6 +8,7 @@ #include #endif #include +#include class MultiPlayerLevel; class Textures; class Chunk; @@ -164,7 +165,7 @@ private: typedef std::unordered_map rtePendingRemovalMap; rtePendingRemovalMap m_renderableTileEntitiesPendingRemoval; - CRITICAL_SECTION m_csRenderableTileEntities; + std::mutex m_csRenderableTileEntities; MultiPlayerLevel* level[4]; // 4J - now one per player Textures* textures; // std::vector *sortedChunks[4]; // 4J - removed - not @@ -215,7 +216,7 @@ private: public: void fullyFlagRenderableTileEntitiesToBeRemoved(); // 4J added - CRITICAL_SECTION m_csDirtyChunks; + std::mutex m_csDirtyChunks; bool m_nearDirtyChunk; // 4J - Destroyed Tile Management - these things added so we can track tiles @@ -235,7 +236,7 @@ public: RecentTile(int x, int y, int z, Level* level); ~RecentTile() = default; }; - CRITICAL_SECTION m_csDestroyedTiles; + std::mutex m_csDestroyedTiles; std::vector m_destroyedTiles; public: @@ -343,7 +344,7 @@ public: static void staticCtor(); static int rebuildChunkThreadProc(void* lpParam); - CRITICAL_SECTION m_csChunkFlags; + std::mutex m_csChunkFlags; #endif void nonStackDirtyChunksAdded(); diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp index 7abb318cf..eaafbcc2d 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp +++ b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp @@ -777,11 +777,11 @@ int ConsoleSaveFileOriginal::getOriginalSaveVersion() { } void ConsoleSaveFileOriginal::LockSaveAccess() { - EnterCriticalSection(&m_lock); + m_lock.lock(); } void ConsoleSaveFileOriginal::ReleaseSaveAccess() { - LeaveCriticalSection(&m_lock); + m_lock.unlock(); } ESavePlatform ConsoleSaveFileOriginal::getSavePlatform() { diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h index 7ca7e7cf6..eaada76a9 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h +++ b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h @@ -1,4 +1,5 @@ #pragma once +#include #include "FileHeader.h" #include "ConsoleSavePath.h" @@ -23,7 +24,7 @@ private: #endif void* pvSaveMem; - CRITICAL_SECTION m_lock; + std::mutex m_lock; void PrepareForWrite(FileEntry* file, unsigned int nNumberOfBytesToWrite); void MoveDataBeyond(FileEntry* file, unsigned int nNumberOfBytesToWrite); diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp index 31bc923f1..8f4b16446 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp +++ b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp @@ -397,7 +397,6 @@ ConsoleSaveFileSplit::ConsoleSaveFileSplit(ConsoleSaveFile* sourceSave, void ConsoleSaveFileSplit::_init(const std::wstring& fileName, void* pvSaveData, unsigned int fileSize, ESavePlatform plat) { - InitializeCriticalSectionAndSpinCount(&m_lock, 5120); m_lastTickTime = 0; @@ -550,7 +549,6 @@ ConsoleSaveFileSplit::~ConsoleSaveFileSplit() { } StorageManager.ResetSubfiles(); - DeleteCriticalSection(&m_lock); } // Add the file to our table of internal files if not already there @@ -1508,10 +1506,10 @@ int ConsoleSaveFileSplit::getOriginalSaveVersion() { return header.getOriginalSaveVersion(); } -void ConsoleSaveFileSplit::LockSaveAccess() { EnterCriticalSection(&m_lock); } +void ConsoleSaveFileSplit::LockSaveAccess() { m_lock.lock(); } void ConsoleSaveFileSplit::ReleaseSaveAccess() { - LeaveCriticalSection(&m_lock); + m_lock.unlock(); } ESavePlatform ConsoleSaveFileSplit::getSavePlatform() { diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h index 971d859b5..701f17895 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h +++ b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h @@ -1,4 +1,5 @@ #pragma once +#include #include "FileHeader.h" #include "ConsoleSavePath.h" @@ -79,7 +80,7 @@ private: #endif void* pvSaveMem; - CRITICAL_SECTION m_lock; + std::mutex m_lock; void PrepareForWrite(FileEntry* file, unsigned int nNumberOfBytesToWrite); void MoveDataBeyond(FileEntry* file, unsigned int nNumberOfBytesToWrite); diff --git a/Minecraft.World/IO/Streams/Compression.cpp b/Minecraft.World/IO/Streams/Compression.cpp index da7662638..656724fa8 100644 --- a/Minecraft.World/IO/Streams/Compression.cpp +++ b/Minecraft.World/IO/Streams/Compression.cpp @@ -41,7 +41,7 @@ Compression* Compression::getCompression() { int32_t Compression::CompressLZXRLE(void* pDestination, unsigned int* pDestSize, void* pSource, unsigned int SrcSize) { - EnterCriticalSection(&rleCompressLock); + std::lock_guard lock(rleCompressLock); // static unsigned char rleBuf[1024*100]; unsigned char* pucIn = (unsigned char*)pSource; @@ -83,7 +83,6 @@ int32_t Compression::CompressLZXRLE(void* pDestination, unsigned int* pDestSize, PIXBeginNamedEvent(0, "Secondary compression"); Compress(pDestination, pDestSize, rleCompressBuf, rleSize); PIXEndNamedEvent(); - LeaveCriticalSection(&rleCompressLock); // printf("Compressed from %d to %d to %d\n",SrcSize,rleSize,*pDestSize); return S_OK; @@ -91,7 +90,8 @@ int32_t Compression::CompressLZXRLE(void* pDestination, unsigned int* pDestSize, int32_t Compression::CompressRLE(void* pDestination, unsigned int* pDestSize, void* pSource, unsigned int SrcSize) { - EnterCriticalSection(&rleCompressLock); + unsigned int rleSize; + { std::lock_guard lock(rleCompressLock); // static unsigned char rleBuf[1024*100]; unsigned char* pucIn = (unsigned char*)pSource; @@ -127,9 +127,9 @@ int32_t Compression::CompressRLE(void* pDestination, unsigned int* pDestSize, *pucOut++ = thisOne; } } while (pucIn != pucEnd); - unsigned int rleSize = (unsigned int)(pucOut - rleCompressBuf); + rleSize = (unsigned int)(pucOut - rleCompressBuf); PIXEndNamedEvent(); - LeaveCriticalSection(&rleCompressLock); + } // Return if (rleSize <= *pDestSize) { @@ -147,7 +147,7 @@ int32_t Compression::CompressRLE(void* pDestination, unsigned int* pDestSize, int32_t Compression::DecompressLZXRLE(void* pDestination, unsigned int* pDestSize, void* pSource, unsigned int SrcSize) { - EnterCriticalSection(&rleDecompressLock); + std::lock_guard lock(rleDecompressLock); // 4J Stu - Fix for #13676 - Crash: Crash while attempting to load a world // after updating TU Some saves can have chunks that decompress into very // large sizes, so I have doubled the size of this buffer Ideally we should @@ -203,13 +203,12 @@ int32_t Compression::DecompressLZXRLE(void* pDestination, if (dynamicRleBuf != nullptr) delete[] dynamicRleBuf; - LeaveCriticalSection(&rleDecompressLock); return S_OK; } int32_t Compression::DecompressRLE(void* pDestination, unsigned int* pDestSize, void* pSource, unsigned int SrcSize) { - EnterCriticalSection(&rleDecompressLock); + std::lock_guard lock(rleDecompressLock); // unsigned char *pucIn = (unsigned char *)rleDecompressBuf; unsigned char* pucIn = (unsigned char*)pSource; @@ -238,7 +237,6 @@ int32_t Compression::DecompressRLE(void* pDestination, unsigned int* pDestSize, } *pDestSize = (unsigned int)(pucOut - (unsigned char*)pDestination); - LeaveCriticalSection(&rleDecompressLock); return S_OK; } @@ -439,17 +437,12 @@ Compression::Compression() { m_localDecompressType = eCompressionType_ZLIBRLE; m_decompressType = m_localDecompressType; - - InitializeCriticalSection(&rleCompressLock); - InitializeCriticalSection(&rleDecompressLock); } Compression::~Compression() { XMemDestroyCompressionContext(compressionContext); XMemDestroyDecompressionContext(decompressionContext); - DeleteCriticalSection(&rleCompressLock); - DeleteCriticalSection(&rleDecompressLock); } void Compression::SetDecompressionType(ESavePlatform platform) { diff --git a/Minecraft.World/IO/Streams/Compression.h b/Minecraft.World/IO/Streams/Compression.h index 980c9e6b1..2ff65a491 100644 --- a/Minecraft.World/IO/Streams/Compression.h +++ b/Minecraft.World/IO/Streams/Compression.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../Files/FileHeader.h" class Compression { @@ -67,8 +68,8 @@ private: XMEMCOMPRESSION_CONTEXT compressionContext; XMEMDECOMPRESSION_CONTEXT decompressionContext; - CRITICAL_SECTION rleCompressLock; - CRITICAL_SECTION rleDecompressLock; + std::mutex rleCompressLock; + std::mutex rleDecompressLock; unsigned char rleCompressBuf[1024 * 100]; static const unsigned int staticRleSize = 1024 * 200; diff --git a/Minecraft.World/Level/Level.cpp b/Minecraft.World/Level/Level.cpp index 2a1870696..0f3a29a3d 100644 --- a/Minecraft.World/Level/Level.cpp +++ b/Minecraft.World/Level/Level.cpp @@ -27,6 +27,7 @@ #include "../Util/WeighedRandom.h" #include "../IO/Files/ConsoleSaveFile.h" +#include #include #include "../../Minecraft.Client/Minecraft.h" #include "../../Minecraft.Client/Rendering/LevelRenderer.h" @@ -539,17 +540,12 @@ void Level::_init() { isClientSide = false; - InitializeCriticalSection(&m_entitiesCS); - InitializeCriticalSection(&m_tileEntityListCS); - updatingTileEntities = false; villageSiege = new VillageSiege(this); scoreboard = new Scoreboard(); toCheckLevel = new int[32 * 32 * 32]; // 4J - brought forward from 1.8.2 - InitializeCriticalSectionAndSpinCount( - &m_checkLightCS, 5120); // 4J - added for 1.8.2 lighting // 4J Added m_bDisableAddNewTileEntities = false; @@ -699,16 +695,11 @@ Level::~Level() { NotGateTile::removeLevelReferences(this); // 4J added } - DeleteCriticalSection(&m_checkLightCS); - // 4J-PB - savedDataStorage is shared between overworld and nether levels in // the server, so it will already have been deleted on the first level // delete if (savedDataStorage != nullptr) delete savedDataStorage; - DeleteCriticalSection(&m_entitiesCS); - DeleteCriticalSection(&m_tileEntityListCS); - // 4J Stu - At least one of the listeners is something we cannot delete, the // LevelRenderer /* @@ -1622,11 +1613,11 @@ bool Level::addEntity(std::shared_ptr e) { MemSect(42); getChunk(xc, zc)->addEntity(e); MemSect(0); - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); MemSect(43); entities.push_back(e); MemSect(0); - LeaveCriticalSection(&m_entitiesCS); + } MemSect(44); entityAdded(e); MemSect(0); @@ -1707,7 +1698,7 @@ void Level::removeEntityImmediately(std::shared_ptr e) { getChunk(xc, zc)->removeEntity(e); } - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); std::vector >::iterator it = entities.begin(); std::vector >::iterator endIt = entities.end(); while (it != endIt && *it != e) it++; @@ -1715,7 +1706,7 @@ void Level::removeEntityImmediately(std::shared_ptr e) { if (it != endIt) { entities.erase(it); } - LeaveCriticalSection(&m_entitiesCS); + } entityRemoved(e); } @@ -2084,7 +2075,7 @@ void Level::tickEntities() { } } - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); for (auto it = entities.begin(); it != entities.end();) { bool found = false; @@ -2101,7 +2092,7 @@ void Level::tickEntities() { it++; } } - LeaveCriticalSection(&m_entitiesCS); + } auto itETREnd = entitiesToRemove.end(); for (auto it = entitiesToRemove.begin(); it != itETREnd; it++) { @@ -2125,7 +2116,7 @@ void Level::tickEntities() { /* 4J Jev, using an iterator causes problems here as * the vector is modified from inside this loop. */ - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); for (unsigned int i = 0; i < entities.size();) { std::shared_ptr e = entities.at(i); @@ -2171,9 +2162,9 @@ void Level::tickEntities() { i++; } } - LeaveCriticalSection(&m_entitiesCS); + } - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); updatingTileEntities = true; for (auto it = tileEntityList.begin(); it != tileEntityList.end();) { @@ -2243,12 +2234,12 @@ void Level::tickEntities() { } pendingTileEntities.clear(); } - LeaveCriticalSection(&m_tileEntityListCS); + } } void Level::addAllPendingTileEntities( std::vector >& entities) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); if (updatingTileEntities) { for (auto it = entities.begin(); it != entities.end(); it++) { pendingTileEntities.push_back(*it); @@ -2258,7 +2249,7 @@ void Level::addAllPendingTileEntities( tileEntityList.push_back(*it); } } - LeaveCriticalSection(&m_tileEntityListCS); + } } void Level::tick(std::shared_ptr e) { tick(e, true); } @@ -2598,9 +2589,9 @@ return shared_ptr(); std::wstring Level::gatherStats() { wchar_t buf[64]; - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); swprintf(buf, 64, L"All:%d", entities.size()); - LeaveCriticalSection(&m_entitiesCS); + } return std::wstring(buf); } @@ -2615,7 +2606,7 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { std::shared_ptr tileEntity = nullptr; if (updatingTileEntities) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); for (int i = 0; i < pendingTileEntities.size(); i++) { std::shared_ptr e = pendingTileEntities.at(i); if (!e->isRemoved() && e->x == x && e->y == y && e->z == z) { @@ -2623,7 +2614,7 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { break; } } - LeaveCriticalSection(&m_tileEntityListCS); + } } if (tileEntity == nullptr) { @@ -2634,7 +2625,7 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { } if (tileEntity == nullptr) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); for (auto it = pendingTileEntities.begin(); it != pendingTileEntities.end(); it++) { std::shared_ptr e = *it; @@ -2644,7 +2635,7 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { break; } } - LeaveCriticalSection(&m_tileEntityListCS); + } } return tileEntity; } @@ -2652,7 +2643,7 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { void Level::setTileEntity(int x, int y, int z, std::shared_ptr tileEntity) { if (tileEntity != nullptr && !tileEntity->isRemoved()) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); if (updatingTileEntities) { tileEntity->x = x; tileEntity->y = y; @@ -2677,12 +2668,12 @@ void Level::setTileEntity(int x, int y, int z, LevelChunk* lc = getChunk(x >> 4, z >> 4); if (lc != nullptr) lc->setTileEntity(x & 15, y, z & 15, tileEntity); } - LeaveCriticalSection(&m_tileEntityListCS); + } } } void Level::removeTileEntity(int x, int y, int z) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); std::shared_ptr te = getTileEntity(x, y, z); if (te != nullptr && updatingTileEntities) { te->setRemoved(); @@ -2707,13 +2698,13 @@ void Level::removeTileEntity(int x, int y, int z) { LevelChunk* lc = getChunk(x >> 4, z >> 4); if (lc != nullptr) lc->removeTileEntity(x & 15, y, z & 15); } - LeaveCriticalSection(&m_tileEntityListCS); + } } void Level::markForRemoval(std::shared_ptr entity) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); tileEntitiesToUnload.insert(entity); - LeaveCriticalSection(&m_tileEntityListCS); + } } bool Level::isSolidRenderTile(int x, int y, int z) { @@ -3110,7 +3101,7 @@ void Level::checkLight(LightLayer::variety layer, int xc, int yc, int zc, } - EnterCriticalSection(&m_checkLightCS); + { std::lock_guard lock(m_checkLightCS); initCachePartial(cache, xc, yc, zc); @@ -3133,7 +3124,6 @@ void Level::checkLight(LightLayer::variety layer, int xc, int yc, int zc, int minXZ = -(dimension->getXZSize() * 16) / 2; int maxXZ = (dimension->getXZSize() * 16) / 2 - 1; if ((xc > maxXZ) || (xc < minXZ) || (zc > maxXZ) || (zc < minXZ)) { - LeaveCriticalSection(&m_checkLightCS); return; } @@ -3338,7 +3328,7 @@ void Level::checkLight(LightLayer::variety layer, int xc, int yc, int zc, // if( cache ) XUnlockL2(XLOCKL2_INDEX_TITLE); flushCache(cache, cacheUse, layer); - LeaveCriticalSection(&m_checkLightCS); + } } bool Level::tickPendingTicks(bool force) { return false; } @@ -3423,9 +3413,8 @@ std::shared_ptr Level::getClosestEntityOfClass( } std::vector > Level::getAllEntities() { - EnterCriticalSection(&m_entitiesCS); + std::lock_guard lock(m_entitiesCS); std::vector > retVec = entities; - LeaveCriticalSection(&m_entitiesCS); return retVec; } @@ -3447,7 +3436,7 @@ unsigned int Level::countInstanceOf( unsigned int count = 0; if (protectedCount) *protectedCount = 0; if (couldWanderCount) *couldWanderCount = 0; - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); auto itEnd = entities.end(); for (auto it = entities.begin(); it != itEnd; it++) { std::shared_ptr e = *it; // entities.at(i); @@ -3467,7 +3456,7 @@ unsigned int Level::countInstanceOf( if (e->instanceof(clas)) count++; } } - LeaveCriticalSection(&m_entitiesCS); + } return count; } @@ -3475,7 +3464,7 @@ unsigned int Level::countInstanceOf( unsigned int Level::countInstanceOfInRange(eINSTANCEOF clas, bool singleType, int range, int x, int y, int z) { unsigned int count = 0; - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); auto itEnd = entities.end(); for (auto it = entities.begin(); it != itEnd; it++) { std::shared_ptr e = *it; // entities.at(i); @@ -3493,14 +3482,14 @@ unsigned int Level::countInstanceOfInRange(eINSTANCEOF clas, bool singleType, if (e->instanceof(clas)) count++; } } - LeaveCriticalSection(&m_entitiesCS); + } return count; } void Level::addEntities(std::vector >* list) { // entities.addAll(list); - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); entities.insert(entities.end(), list->begin(), list->end()); auto itEnd = list->end(); bool deleteDragons = false; @@ -3528,7 +3517,7 @@ void Level::addEntities(std::vector >* list) { } } } - LeaveCriticalSection(&m_entitiesCS); + } } void Level::removeEntities(std::vector >* list) { @@ -3943,11 +3932,11 @@ void Level::ensureAdded(std::shared_ptr entity) { } // if (!entities.contains(entity)) - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); if (find(entities.begin(), entities.end(), entity) == entities.end()) { entities.push_back(entity); } - LeaveCriticalSection(&m_entitiesCS); + } } bool Level::mayInteract(std::shared_ptr player, int xt, int yt, int zt, diff --git a/Minecraft.World/Level/Level.h b/Minecraft.World/Level/Level.h index a5992f429..92470c723 100644 --- a/Minecraft.World/Level/Level.h +++ b/Minecraft.World/Level/Level.h @@ -10,6 +10,7 @@ #include "../WorldGen/Biomes/Biome.h" #include "../Util/C4JThread.h" #include +#include #include // 4J Stu - This value should be big enough that we don't get any crashes causes @@ -100,7 +101,7 @@ public: static const int TICKS_PER_DAY = 20 * 60 * 20; // ORG:20*60*20 public: - CRITICAL_SECTION m_entitiesCS; // 4J added + std::recursive_mutex m_entitiesCS; // 4J added std::vector > entities; @@ -110,7 +111,7 @@ protected: public: bool hasEntitiesToRemove(); // 4J added bool m_bDisableAddNewTileEntities; // 4J Added - CRITICAL_SECTION m_tileEntityListCS; // 4J added + std::recursive_mutex m_tileEntityListCS; // 4J added std::vector > tileEntityList; private: @@ -630,7 +631,7 @@ public: virtual bool newFallingTileAllowed() { return true; } // 4J - added for new lighting from 1.8.2 - CRITICAL_SECTION m_checkLightCS; + std::recursive_mutex m_checkLightCS; private: int m_iHighestY; // 4J-PB - for the end portal in The End diff --git a/Minecraft.World/Level/LevelChunk.cpp b/Minecraft.World/Level/LevelChunk.cpp index dc8df54fc..0ffb12f8b 100644 --- a/Minecraft.World/Level/LevelChunk.cpp +++ b/Minecraft.World/Level/LevelChunk.cpp @@ -19,29 +19,25 @@ #include "../Entities/ItemEntity.h" #include "../Entities/Mobs/Minecart.h" +#include + #if defined(SHARING_ENABLED) -CRITICAL_SECTION LevelChunk::m_csSharing; +std::mutex LevelChunk::m_csSharing; #endif #if defined(_ENTITIES_RW_SECTION) // AP - use a RW critical section so we can have multiple threads reading the // same data to avoid a clash CRITICAL_RW_SECTION LevelChunk::m_csEntities; #else -CRITICAL_SECTION LevelChunk::m_csEntities; +std::mutex LevelChunk::m_csEntities; #endif -CRITICAL_SECTION LevelChunk::m_csTileEntities; +std::mutex LevelChunk::m_csTileEntities; bool LevelChunk::touchedSky = false; void LevelChunk::staticCtor() { -#if defined(SHARING_ENABLED) - InitializeCriticalSection(&m_csSharing); -#endif #if defined(_ENTITIES_RW_SECTION) InitializeCriticalRWSection(&m_csEntities); -#else - InitializeCriticalSection(&m_csEntities); #endif - InitializeCriticalSection(&m_csTileEntities); } void LevelChunk::init(Level* level, int x, int z) { @@ -52,14 +48,14 @@ void LevelChunk::init(Level* level, int x, int z) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif entityBlocks = new std::vector >*[ENTITY_BLOCKS_LENGTH]; #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif terrainPopulated = 0; @@ -83,7 +79,7 @@ void LevelChunk::init(Level* level, int x, int z) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { entityBlocks[i] = new std::vector >(); @@ -91,7 +87,7 @@ void LevelChunk::init(Level* level, int x, int z) { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif MemSect(0); @@ -253,10 +249,9 @@ void LevelChunk::setUnsaved(bool unsaved) { void LevelChunk::stopSharingTilesAndData() { #if defined(SHARING_ENABLED) - EnterCriticalSection(&m_csSharing); + { std::lock_guard lock(m_csSharing); lastUnsharedTime = System::currentTimeMillis(); if (!sharingTilesAndData) { - LeaveCriticalSection(&m_csSharing); return; } @@ -269,7 +264,6 @@ void LevelChunk::stopSharingTilesAndData() { if ((serverTerrainPopulated) && (((*serverTerrainPopulated) & sTerrainPopulatedAllAffecting) != sTerrainPopulatedAllAffecting)) { - LeaveCriticalSection(&m_csSharing); return; } @@ -277,7 +271,6 @@ void LevelChunk::stopSharingTilesAndData() { // don't drop out here we'll end up unsharing the chunk at this location for // no reason if (isEmpty()) { - LeaveCriticalSection(&m_csSharing); return; } @@ -311,7 +304,7 @@ void LevelChunk::stopSharingTilesAndData() { sharingTilesAndData = false; MemSect(0); - LeaveCriticalSection(&m_csSharing); + } #endif } @@ -322,10 +315,9 @@ void LevelChunk::stopSharingTilesAndData() { // not sharing void LevelChunk::reSyncLighting() { #if defined(SHARING_ENABLED) - EnterCriticalSection(&m_csSharing); + { std::lock_guard lock(m_csSharing); if (isEmpty()) { - LeaveCriticalSection(&m_csSharing); return; } @@ -354,15 +346,14 @@ void LevelChunk::reSyncLighting() { upperBlockLight = new SparseLightStorage(lc->upperBlockLight); GameRenderer::FinishedReassigning(); } - LeaveCriticalSection(&m_csSharing); + } #endif } void LevelChunk::startSharingTilesAndData(int forceMs) { #if defined(SHARING_ENABLED) - EnterCriticalSection(&m_csSharing); + { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { - LeaveCriticalSection(&m_csSharing); return; } @@ -371,7 +362,6 @@ void LevelChunk::startSharingTilesAndData(int forceMs) { // doesn't make sense to go resharing the 0,0 block on behalf of an empty // chunk either if (isEmpty()) { - LeaveCriticalSection(&m_csSharing); return; } @@ -394,7 +384,6 @@ void LevelChunk::startSharingTilesAndData(int forceMs) { if (!lowerBlocks->isSameAs(lc->lowerBlocks) || (upperBlocks && lc->upperBlocks && !upperBlocks->isSameAs(lc->upperBlocks))) { - LeaveCriticalSection(&m_csSharing); return; } } else { @@ -402,7 +391,6 @@ void LevelChunk::startSharingTilesAndData(int forceMs) { // last wanted to unshare this chunk int64_t timenow = System::currentTimeMillis(); if ((timenow - lastUnsharedTime) < forceMs) { - LeaveCriticalSection(&m_csSharing); return; } } @@ -429,7 +417,7 @@ void LevelChunk::startSharingTilesAndData(int forceMs) { } sharingTilesAndData = true; - LeaveCriticalSection(&m_csSharing); + } #endif } @@ -1193,13 +1181,13 @@ void LevelChunk::addEntity(std::shared_ptr e) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif entityBlocks[yc]->push_back(e); #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif } @@ -1214,7 +1202,7 @@ void LevelChunk::removeEntity(std::shared_ptr e, int yc) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif // 4J - was entityBlocks[yc]->remove(e); @@ -1231,7 +1219,7 @@ void LevelChunk::removeEntity(std::shared_ptr e, int yc) { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif } @@ -1256,14 +1244,13 @@ std::shared_ptr LevelChunk::getTileEntity(int x, int y, int z) { // 4J Stu - Changed as we should not be using the [] accessor (causes an // insert when we don't want one) // shared_ptr tileEntity = tileEntities[pos]; - EnterCriticalSection(&m_csTileEntities); std::shared_ptr tileEntity = nullptr; + { std::unique_lock lock(m_csTileEntities); auto it = tileEntities.find(pos); if (it == tileEntities.end()) { - LeaveCriticalSection( - &m_csTileEntities); // Note: don't assume iterator is valid for - // tileEntities after this point + lock.unlock(); // Note: don't assume iterator is valid for + // tileEntities after this point // Fix for #48450 - All: Code Defect: Hang: Game hangs in tutorial, when // player arrive at the particular coordinate 4J Stu - Chests try to get @@ -1289,20 +1276,20 @@ std::shared_ptr LevelChunk::getTileEntity(int x, int y, int z) { // doesn't seem right - assignment wrong way? Check // 4J Stu - It should have been inserted by now, but check to be sure - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock2(m_csTileEntities); auto newIt = tileEntities.find(pos); if (newIt != tileEntities.end()) { tileEntity = newIt->second; } - LeaveCriticalSection(&m_csTileEntities); + } } else { tileEntity = it->second; - LeaveCriticalSection(&m_csTileEntities); + } } if (tileEntity != nullptr && tileEntity->isRemoved()) { - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); tileEntities.erase(pos); - LeaveCriticalSection(&m_csTileEntities); + } return nullptr; } @@ -1315,9 +1302,10 @@ void LevelChunk::addTileEntity(std::shared_ptr te) { int zz = (int)(te->z - this->z * 16); setTileEntity(xx, yy, zz, te); if (loaded) { - EnterCriticalSection(&level->m_tileEntityListCS); - level->tileEntityList.push_back(te); - LeaveCriticalSection(&level->m_tileEntityListCS); + { + std::lock_guard lock(level->m_tileEntityListCS); + level->tileEntityList.push_back(te); + } } } @@ -1345,9 +1333,9 @@ void LevelChunk::setTileEntity(int x, int y, int z, tileEntity->clearRemoved(); - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); tileEntities[pos] = tileEntity; - LeaveCriticalSection(&m_csTileEntities); + } } void LevelChunk::removeTileEntity(int x, int y, int z) { @@ -1359,7 +1347,7 @@ void LevelChunk::removeTileEntity(int x, int y, int z) { // if (removeThis != null) { // removeThis.setRemoved(); // } - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); auto it = tileEntities.find(pos); if (it != tileEntities.end()) { std::shared_ptr te = tileEntities[pos]; @@ -1372,7 +1360,7 @@ void LevelChunk::removeTileEntity(int x, int y, int z) { te->setRemoved(); } } - LeaveCriticalSection(&m_csTileEntities); + } } } @@ -1417,18 +1405,18 @@ void LevelChunk::load() { #endif std::vector > values; - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); for (auto it = tileEntities.begin(); it != tileEntities.end(); it++) { values.push_back(it->second); } - LeaveCriticalSection(&m_csTileEntities); + } level->addAllPendingTileEntities(values); #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { level->addEntities(entityBlocks[i]); @@ -1436,7 +1424,7 @@ void LevelChunk::load() { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif } else { #if defined(_LARGE_WORLDS) @@ -1450,12 +1438,12 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter loaded = false; if (unloadTileEntities) { std::vector > tileEntitiesToRemove; - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); for (auto it = tileEntities.begin(); it != tileEntities.end(); it++) { tileEntitiesToRemove.push_back(it->second); } - LeaveCriticalSection(&m_csTileEntities); + } auto itEnd = tileEntitiesToRemove.end(); for (auto it = tileEntitiesToRemove.begin(); it != itEnd; it++) { @@ -1467,7 +1455,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { level->removeEntities(entityBlocks[i]); @@ -1475,7 +1463,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif // app.DebugPrintf("Unloaded chunk %d, %d\n", x, z); @@ -1492,7 +1480,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter PIXBeginNamedEvent(0, "Saving entities"); ListTag* entityTags = new ListTag(); - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { auto itEnd = entityBlocks[i]->end(); for (std::vector >::iterator it = @@ -1508,7 +1496,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter // Clear out this list entityBlocks[i]->clear(); } - LeaveCriticalSection(&m_csEntities); + } m_unloadedEntitiesTag->put(L"Entities", entityTags); PIXEndNamedEvent(); @@ -1540,7 +1528,7 @@ bool LevelChunk::containsPlayer() { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { std::vector >* vecEntity = entityBlocks[i]; @@ -1549,7 +1537,6 @@ bool LevelChunk::containsPlayer() { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); #endif return true; } @@ -1558,7 +1545,7 @@ bool LevelChunk::containsPlayer() { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif return false; } @@ -1579,7 +1566,7 @@ void LevelChunk::getEntities(std::shared_ptr except, AABB* bb, // AP - RW critical sections are expensive so enter once in // Level::getEntities - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); for (int yc = yc0; yc <= yc1; yc++) { std::vector >* entities = entityBlocks[yc]; @@ -1603,7 +1590,7 @@ void LevelChunk::getEntities(std::shared_ptr except, AABB* bb, } } } - LeaveCriticalSection(&m_csEntities); + } } void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, @@ -1625,7 +1612,7 @@ void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, // AP - RW critical sections are expensive so enter once in // Level::getEntitiesOfClass - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); for (int yc = yc0; yc <= yc1; yc++) { std::vector >* entities = entityBlocks[yc]; @@ -1665,7 +1652,7 @@ void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, // baseClass.isAssignableFrom(e.getClass()) } } - LeaveCriticalSection(&m_csEntities); + } } int LevelChunk::countEntities() { @@ -1673,7 +1660,7 @@ int LevelChunk::countEntities() { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, false); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int yc = 0; yc < ENTITY_BLOCKS_LENGTH; yc++) { entityCount += (int)entityBlocks[yc]->size(); @@ -1681,7 +1668,7 @@ int LevelChunk::countEntities() { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, false); #else - LeaveCriticalSection(&m_csEntities); + } #endif return entityCount; } @@ -2226,12 +2213,12 @@ void LevelChunk::compressBlocks() { // Note - only the extraction of the pointers needs to be done in the // critical section, since even if the data is unshared whilst we are // processing this data is still valid (for the server) - EnterCriticalSection(&m_csSharing); + { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { blocksToCompressLower = lowerBlocks; blocksToCompressUpper = upperBlocks; } - LeaveCriticalSection(&m_csSharing); + } } else { // Not the host, simple case blocksToCompressLower = lowerBlocks; @@ -2325,12 +2312,12 @@ void LevelChunk::compressData() { // Note - only the extraction of the pointers needs to be done in the // critical section, since even if the data is unshared whilst we are // processing this data is still valid (for the server) - EnterCriticalSection(&m_csSharing); + { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { dataToCompressLower = lowerData; dataToCompressUpper = upperData; } - LeaveCriticalSection(&m_csSharing); + } } else { // Not the host, simple case dataToCompressLower = lowerData; diff --git a/Minecraft.World/Level/LevelChunk.h b/Minecraft.World/Level/LevelChunk.h index 820f1eac8..be32cb0b4 100644 --- a/Minecraft.World/Level/LevelChunk.h +++ b/Minecraft.World/Level/LevelChunk.h @@ -1,5 +1,7 @@ #pragma once +#include + class DataLayer; class TileEntity; class Random; @@ -269,7 +271,7 @@ public: virtual void attemptCompression(); #if defined(SHARING_ENABLED) - static CRITICAL_SECTION m_csSharing; // 4J added + static std::mutex m_csSharing; // 4J added #endif // 4J added #if defined(_ENTITIES_RW_SECTION) @@ -277,9 +279,9 @@ public: m_csEntities; // AP - we're using a RW critical so we can do multiple // reads without contention #else - static CRITICAL_SECTION m_csEntities; + static std::mutex m_csEntities; #endif - static CRITICAL_SECTION m_csTileEntities; // 4J added + static std::mutex m_csTileEntities; // 4J added static void staticCtor(); void checkPostProcess(ChunkSource* source, ChunkSource* parent, int x, int z); diff --git a/Minecraft.World/Level/Storage/CompressedTileStorage.cpp b/Minecraft.World/Level/Storage/CompressedTileStorage.cpp index 04f805208..6d9a6a07c 100644 --- a/Minecraft.World/Level/Storage/CompressedTileStorage.cpp +++ b/Minecraft.World/Level/Storage/CompressedTileStorage.cpp @@ -8,7 +8,7 @@ int CompressedTileStorage::deleteQueueIndex; XLockFreeStack CompressedTileStorage::deleteQueue[3]; -CRITICAL_SECTION CompressedTileStorage::cs_write; +std::mutex CompressedTileStorage::cs_write; #if defined(PSVITA_PRECOMPUTED_TABLE) // AP - this will create a precomputed table to speed up getData @@ -35,7 +35,7 @@ CompressedTileStorage::CompressedTileStorage() { } CompressedTileStorage::CompressedTileStorage(CompressedTileStorage* copyFrom) { - EnterCriticalSection(&cs_write); + { std::lock_guard lock(cs_write); allocatedSize = copyFrom->allocatedSize; if (allocatedSize > 0) { indicesAndData = (unsigned char*)XPhysicalAlloc( @@ -45,7 +45,7 @@ CompressedTileStorage::CompressedTileStorage(CompressedTileStorage* copyFrom) { } else { indicesAndData = nullptr; } - LeaveCriticalSection(&cs_write); + } #if defined(PSVITA_PRECOMPUTED_TABLE) CompressedTileStorage_InitTable(); @@ -141,9 +141,8 @@ bool CompressedTileStorage::isRenderChunkEmpty( } bool CompressedTileStorage::isSameAs(CompressedTileStorage* other) { - EnterCriticalSection(&cs_write); + std::lock_guard lock(cs_write); if (allocatedSize != other->allocatedSize) { - LeaveCriticalSection(&cs_write); return false; } @@ -168,7 +167,6 @@ bool CompressedTileStorage::isSameAs(CompressedTileStorage* other) { d0 |= d2; d4 |= d6; if (d0 | d4) { - LeaveCriticalSection(&cs_write); return false; } pOld += 8; @@ -180,12 +178,10 @@ bool CompressedTileStorage::isSameAs(CompressedTileStorage* other) { unsigned char* pucNew = (unsigned char*)pNew; for (int i = 0; i < allocatedSize - (quickCount * 64); i++) { if (*pucOld++ != *pucNew++) { - LeaveCriticalSection(&cs_write); return false; } } - LeaveCriticalSection(&cs_write); return true; } @@ -244,7 +240,7 @@ inline void CompressedTileStorage::getBlock(int* block, int x, int y, int z) { void CompressedTileStorage::setData(byteArray dataIn, unsigned int inOffset) { unsigned short _blockIndices[512]; - EnterCriticalSection(&cs_write); + std::lock_guard lock(cs_write); unsigned char* data = dataIn.data + inOffset; // Is the destination fully uncompressed? If so just write our data in - @@ -259,7 +255,6 @@ void CompressedTileStorage::setData(byteArray dataIn, unsigned int inOffset) { *dataOut++ = data[getIndex(i, j)]; } } - LeaveCriticalSection(&cs_write); return; } @@ -406,7 +401,6 @@ void CompressedTileStorage::setData(byteArray dataIn, unsigned int inOffset) { } indicesAndData = newIndicesAndData; allocatedSize = memToAlloc; - LeaveCriticalSection(&cs_write); } #if defined(PSVITA_PRECOMPUTED_TABLE) @@ -598,7 +592,7 @@ int CompressedTileStorage::get(int x, int y, int z) { // Set an individual tile value void CompressedTileStorage::set(int x, int y, int z, int val) { - EnterCriticalSection(&cs_write); + std::lock_guard lock(cs_write); assert(val != 255); int block, tile; getBlockAndTile(&block, &tile, x, y, z); @@ -618,7 +612,6 @@ void CompressedTileStorage::set(int x, int y, int z, int val) { // continue on to upgrade storage if (val == ((blockIndices[block] >> INDEX_TILE_SHIFT) & INDEX_TILE_MASK)) { - LeaveCriticalSection(&cs_write); return; } } else { @@ -627,7 +620,6 @@ void CompressedTileStorage::set(int x, int y, int z, int val) { data + ((blockIndices[block] >> INDEX_OFFSET_SHIFT) & INDEX_OFFSET_MASK); packed[tile] = val; - LeaveCriticalSection(&cs_write); return; } } else { @@ -660,7 +652,6 @@ void CompressedTileStorage::set(int x, int y, int z, int val) { int bit = (tile & indexmask_bits) * bitspertile; packed[idx] &= ~(tiletypemask << bit); packed[idx] |= i << bit; - LeaveCriticalSection(&cs_write); return; } } @@ -669,7 +660,6 @@ void CompressedTileStorage::set(int x, int y, int z, int val) { compress(block); } }; - LeaveCriticalSection(&cs_write); } // Sets a region of tile values with the data at offset position in the array @@ -743,7 +733,6 @@ int CompressedTileStorage::getDataRegion(byteArray dataInOut, int x0, int y0, } void CompressedTileStorage::staticCtor() { - InitializeCriticalSectionAndSpinCount(&cs_write, 5120); for (int i = 0; i < 3; i++) { deleteQueue[i].Initialize(); } @@ -793,7 +782,7 @@ void CompressedTileStorage::compress(int upgradeBlock /*=-1*/) { (upgradeBlock > -1); // If an upgrade block is specified, we'll always // need to recompress - otherwise default to false - EnterCriticalSection(&cs_write); + std::lock_guard lock(cs_write); unsigned short* blockIndices = (unsigned short*)indicesAndData; unsigned char* data = indicesAndData + 1024; @@ -1131,7 +1120,6 @@ void CompressedTileStorage::compress(int upgradeBlock /*=-1*/) { indicesAndData = newIndicesAndData; allocatedSize = memToAlloc; } - LeaveCriticalSection(&cs_write); } int CompressedTileStorage::getAllocatedSize(int* count0, int* count1, diff --git a/Minecraft.World/Level/Storage/CompressedTileStorage.h b/Minecraft.World/Level/Storage/CompressedTileStorage.h index 8ef13c61f..5ff5b5b13 100644 --- a/Minecraft.World/Level/Storage/CompressedTileStorage.h +++ b/Minecraft.World/Level/Storage/CompressedTileStorage.h @@ -1,4 +1,5 @@ #pragma once +#include #if !defined(__linux__) #include "../../Platform/x64headers/xmcore.h" #endif @@ -157,7 +158,7 @@ public: static unsigned char compressBuffer[32768 + 256]; - static CRITICAL_SECTION cs_write; + static std::mutex cs_write; int getAllocatedSize(int* count0, int* count1, int* count2, int* count4, int* count8); diff --git a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp index 041b69782..4717e00f1 100644 --- a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -8,7 +9,7 @@ #include "../LevelData.h" #include "McRegionChunkStorage.h" -CRITICAL_SECTION McRegionChunkStorage::cs_memory; +std::mutex McRegionChunkStorage::cs_memory; std::deque McRegionChunkStorage::s_chunkDataQueue; int McRegionChunkStorage::s_runningThreadCount = 0; @@ -199,14 +200,15 @@ void McRegionChunkStorage::save(Level* level, LevelChunk* levelChunk) { PIXEndNamedEvent(); PIXBeginNamedEvent(0, "Updating chunk queue"); - EnterCriticalSection(&cs_memory); + { std::lock_guard lock(cs_memory); s_chunkDataQueue.push_back(output); - LeaveCriticalSection(&cs_memory); + } PIXEndNamedEvent(); } else { - EnterCriticalSection(&cs_memory); + CompoundTag* tag; + { std::lock_guard lock(cs_memory); PIXBeginNamedEvent(0, "Creating tags\n"); - CompoundTag* tag = new CompoundTag(); + tag = new CompoundTag(); CompoundTag* levelData = new CompoundTag(); tag->put(L"Level", levelData); OldChunkStorage::save(levelChunk, level, levelData); @@ -214,7 +216,7 @@ void McRegionChunkStorage::save(Level* level, LevelChunk* levelChunk) { PIXBeginNamedEvent(0, "NbtIo writing\n"); NbtIo::write(tag, output); PIXEndNamedEvent(); - LeaveCriticalSection(&cs_memory); + } PIXBeginNamedEvent(0, "Output closing\n"); output->close(); PIXEndNamedEvent(); @@ -222,12 +224,12 @@ void McRegionChunkStorage::save(Level* level, LevelChunk* levelChunk) { // 4J Stu - getChunkDataOutputStream makes a new DataOutputStream that // points to a new ChunkBuffer( ByteArrayOutputStream ) We should clean // these up when we are done - EnterCriticalSection(&cs_memory); + { std::lock_guard lock(cs_memory); PIXBeginNamedEvent(0, "Cleaning up\n"); output->deleteChildStream(); delete output; delete tag; - LeaveCriticalSection(&cs_memory); + } PIXEndNamedEvent(); } MemSect(0); @@ -321,8 +323,6 @@ void McRegionChunkStorage::flush() { } void McRegionChunkStorage::staticCtor() { - InitializeCriticalSectionAndSpinCount(&cs_memory, 5120); - for (unsigned int i = 0; i < 3; ++i) { char threadName[256]; sprintf(threadName, "McRegion Save thread %d\n", i); @@ -355,14 +355,15 @@ int McRegionChunkStorage::runSaveThreadProc(void* lpParam) { DataOutputStream* dos = nullptr; while (running) { - if (TryEnterCriticalSection(&cs_memory)) { + { std::unique_lock lock(cs_memory, std::try_to_lock); + if (lock.owns_lock()) { lastQueueSize = s_chunkDataQueue.size(); if (lastQueueSize > 0) { dos = s_chunkDataQueue.front(); s_chunkDataQueue.pop_front(); } s_runningThreadCount++; - LeaveCriticalSection(&cs_memory); + lock.unlock(); if (dos) { PIXBeginNamedEvent(0, "Saving chunk"); @@ -375,9 +376,10 @@ int McRegionChunkStorage::runSaveThreadProc(void* lpParam) { delete dos; dos = nullptr; - EnterCriticalSection(&cs_memory); + { std::lock_guard lock2(cs_memory); s_runningThreadCount--; - LeaveCriticalSection(&cs_memory); + } + } } // If there was more than one thing in the queue last time we checked, @@ -401,30 +403,32 @@ void McRegionChunkStorage::WaitIfTooManyQueuedChunks() { WaitForSaves(); } // Static void McRegionChunkStorage::WaitForAllSaves() { // Wait for there to be no more tasks to be processed... - EnterCriticalSection(&cs_memory); - size_t queueSize = s_chunkDataQueue.size(); - LeaveCriticalSection(&cs_memory); + size_t queueSize; + { std::lock_guard lock(cs_memory); + queueSize = s_chunkDataQueue.size(); + } while (queueSize > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); - EnterCriticalSection(&cs_memory); + { std::lock_guard lock(cs_memory); queueSize = s_chunkDataQueue.size(); - LeaveCriticalSection(&cs_memory); + } } // And then wait for there to be no running threads that are processing // these tasks - EnterCriticalSection(&cs_memory); - int runningThreadCount = s_runningThreadCount; - LeaveCriticalSection(&cs_memory); + int runningThreadCount; + { std::lock_guard lock(cs_memory); + runningThreadCount = s_runningThreadCount; + } while (runningThreadCount > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); - EnterCriticalSection(&cs_memory); + { std::lock_guard lock(cs_memory); runningThreadCount = s_runningThreadCount; - LeaveCriticalSection(&cs_memory); + } } } @@ -434,17 +438,18 @@ void McRegionChunkStorage::WaitForSaves() { static const int DESIRED_QUEUE_SIZE = 6; // Wait for the queue to reduce to a level where we should add more elements - EnterCriticalSection(&cs_memory); - size_t queueSize = s_chunkDataQueue.size(); - LeaveCriticalSection(&cs_memory); + size_t queueSize; + { std::lock_guard lock(cs_memory); + queueSize = s_chunkDataQueue.size(); + } if (queueSize > MAX_QUEUE_SIZE) { while (queueSize > DESIRED_QUEUE_SIZE) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); - EnterCriticalSection(&cs_memory); + { std::lock_guard lock(cs_memory); queueSize = s_chunkDataQueue.size(); - LeaveCriticalSection(&cs_memory); + } } } } diff --git a/Minecraft.World/Level/Storage/McRegionChunkStorage.h b/Minecraft.World/Level/Storage/McRegionChunkStorage.h index b82ac6474..f651f95e5 100644 --- a/Minecraft.World/Level/Storage/McRegionChunkStorage.h +++ b/Minecraft.World/Level/Storage/McRegionChunkStorage.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "ChunkStorage.h" #include "../LevelChunk.h" #include "RegionFileCache.h" @@ -12,7 +14,7 @@ class McRegionChunkStorage : public ChunkStorage { private: const std::wstring m_prefix; ConsoleSaveFile* m_saveFile; - static CRITICAL_SECTION cs_memory; + static std::mutex cs_memory; std::unordered_map m_entityData; diff --git a/Minecraft.World/Level/Storage/OldChunkStorage.cpp b/Minecraft.World/Level/Storage/OldChunkStorage.cpp index f4b2fa155..5b6f1ae5e 100644 --- a/Minecraft.World/Level/Storage/OldChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/OldChunkStorage.cpp @@ -1,4 +1,5 @@ #include "../../Platform/stdafx.h" +#include #include "../../IO/Files/File.h" #include "../../IO/Streams/InputOutputStream.h" #include "../../Headers/net.minecraft.world.entity.h" @@ -196,29 +197,22 @@ bool OldChunkStorage::saveEntities(LevelChunk* lc, Level* level, lc->lastSaveHadEntities = false; ListTag* entityTags = new ListTag(); -#if defined(_ENTITIES_RW_SECTION) - EnterCriticalRWSection(&lc->m_csEntities, true); -#else - EnterCriticalSection(&lc->m_csEntities); -#endif - for (int i = 0; i < lc->ENTITY_BLOCKS_LENGTH; i++) { - auto itEnd = lc->entityBlocks[i]->end(); - for (std::vector >::iterator it = - lc->entityBlocks[i]->begin(); - it != itEnd; it++) { - std::shared_ptr e = *it; - lc->lastSaveHadEntities = true; - CompoundTag* teTag = new CompoundTag(); - if (e->save(teTag)) { - entityTags->add(teTag); + { + std::lock_guard lock(lc->m_csEntities); + for (int i = 0; i < lc->ENTITY_BLOCKS_LENGTH; i++) { + auto itEnd = lc->entityBlocks[i]->end(); + for (std::vector >::iterator it = + lc->entityBlocks[i]->begin(); + it != itEnd; it++) { + std::shared_ptr e = *it; + lc->lastSaveHadEntities = true; + CompoundTag* teTag = new CompoundTag(); + if (e->save(teTag)) { + entityTags->add(teTag); + } } } } -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&lc->m_csEntities, true); -#else - LeaveCriticalSection(&lc->m_csEntities); -#endif tag->put(L"Entities", entityTags); diff --git a/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp b/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp index e4b47ff2d..051343e38 100644 --- a/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp @@ -1,4 +1,5 @@ #include "../../Platform/stdafx.h" +#include #include "../../IO/Files/File.h" #include "../../IO/Streams/ByteBuffer.h" #include "../../Headers/net.minecraft.world.entity.h" @@ -214,28 +215,21 @@ void ZonedChunkStorage::saveEntities(Level* level, LevelChunk* lc) { std::vector tags; -#ifdef _ENTITIES_RW_SECTION - EnterCriticalRWSection(&lc->m_csEntities, true); -#else - EnterCriticalSection(&lc->m_csEntities); -#endif - for (int i = 0; i < LevelChunk::ENTITY_BLOCKS_LENGTH; i++) { - std::vector >* entities = lc->entityBlocks[i]; + { + std::lock_guard lock(lc->m_csEntities); + for (int i = 0; i < LevelChunk::ENTITY_BLOCKS_LENGTH; i++) { + std::vector >* entities = lc->entityBlocks[i]; - auto itEndTags = entities->end(); - for (auto it = entities->begin(); it != itEndTags; it++) { - std::shared_ptr e = *it; // entities->at(j); - CompoundTag* cp = new CompoundTag(); - cp->putInt(L"_TYPE", 0); - e->save(cp); - tags.push_back(cp); + auto itEndTags = entities->end(); + for (auto it = entities->begin(); it != itEndTags; it++) { + std::shared_ptr e = *it; // entities->at(j); + CompoundTag* cp = new CompoundTag(); + cp->putInt(L"_TYPE", 0); + e->save(cp); + tags.push_back(cp); + } } } -#ifdef _ENTITIES_RW_SECTION - LeaveCriticalRWSection(&lc->m_csEntities, true); -#else - LeaveCriticalSection(&lc->m_csEntities); -#endif for (std::unordered_map, TilePosKeyHash, TilePosKeyEq>::iterator it = diff --git a/Minecraft.World/Network/Connection.cpp b/Minecraft.World/Network/Connection.cpp index cb7ab6c61..e90443f25 100644 --- a/Minecraft.World/Network/Connection.cpp +++ b/Minecraft.World/Network/Connection.cpp @@ -22,10 +22,6 @@ int Connection::writeSizes[256]; void Connection::_init() { // printf("Con:0x%x init\n",this); - InitializeCriticalSection(&writeLock); - InitializeCriticalSection(&threadCounterLock); - InitializeCriticalSection(&incoming_cs); - running = true; quitting = false; disconnected = false; @@ -54,10 +50,6 @@ Connection::~Connection() { readThread->WaitForCompletion(INFINITE); writeThread->WaitForCompletion(INFINITE); - DeleteCriticalSection(&writeLock); - DeleteCriticalSection(&threadCounterLock); - DeleteCriticalSection(&incoming_cs); - delete m_hWakeReadThread; delete m_hWakeWriteThread; @@ -150,29 +142,31 @@ void Connection::send(std::shared_ptr packet) { MemSect(15); // 4J Jev, synchronized (&writeLock) - EnterCriticalSection(&writeLock); + { + std::lock_guard lock(writeLock); - estimatedRemaining += packet->getEstimatedSize() + 1; - if (packet->shouldDelay) { - // 4J We have delayed it enough by putting it in the slow queue, so - // don't delay when we actually send it - packet->shouldDelay = false; - outgoing_slow.push(packet); - } else { - outgoing.push(packet); + estimatedRemaining += packet->getEstimatedSize() + 1; + if (packet->shouldDelay) { + // 4J We have delayed it enough by putting it in the slow queue, so + // don't delay when we actually send it + packet->shouldDelay = false; + outgoing_slow.push(packet); + } else { + outgoing.push(packet); + } } // 4J Jev, end synchronized. - LeaveCriticalSection(&writeLock); MemSect(0); } void Connection::queueSend(std::shared_ptr packet) { if (quitting) return; - EnterCriticalSection(&writeLock); - estimatedRemaining += packet->getEstimatedSize() + 1; - outgoing_slow.push(packet); - LeaveCriticalSection(&writeLock); + { + std::lock_guard lock(writeLock); + estimatedRemaining += packet->getEstimatedSize() + 1; + outgoing_slow.push(packet); + } } bool Connection::writeTick() { @@ -189,13 +183,13 @@ bool Connection::writeTick() { fakeLag)) { std::shared_ptr packet; - EnterCriticalSection(&writeLock); + { + std::lock_guard lock(writeLock); - packet = outgoing.front(); - outgoing.pop(); - estimatedRemaining -= packet->getEstimatedSize() + 1; - - LeaveCriticalSection(&writeLock); + packet = outgoing.front(); + outgoing.pop(); + estimatedRemaining -= packet->getEstimatedSize() + 1; + } Packet::writePacket(packet, bufferedDos); #if defined(__linux__) @@ -238,13 +232,13 @@ bool Connection::writeTick() { // synchronized (writeLock) { - EnterCriticalSection(&writeLock); + { + std::lock_guard lock(writeLock); - packet = outgoing_slow.front(); - outgoing_slow.pop(); - estimatedRemaining -= packet->getEstimatedSize() + 1; - - LeaveCriticalSection(&writeLock); + packet = outgoing_slow.front(); + outgoing_slow.pop(); + estimatedRemaining -= packet->getEstimatedSize() + 1; + } // If the shouldDelay flag is still set at this point then we want to // write it to QNet as a single packet with priority flags Otherwise @@ -329,11 +323,12 @@ bool Connection::readTick() { if (packet != nullptr) { readSizes[packet->getId()] += packet->getEstimatedSize() + 1; - EnterCriticalSection(&incoming_cs); - if (!quitting) { - incoming.push(packet); + { + std::lock_guard lock(incoming_cs); + if (!quitting) { + incoming.push(packet); + } } - LeaveCriticalSection(&incoming_cs); didSomething = true; } else { // printf("Con:0x%x readTick close EOS\n",this); @@ -420,9 +415,11 @@ void Connection::tick() { if (estimatedRemaining > 1 * 1024 * 1024) { close(DisconnectPacket::eDisconnect_Overflow); } - EnterCriticalSection(&incoming_cs); - bool empty = incoming.empty(); - LeaveCriticalSection(&incoming_cs); + bool empty; + { + std::lock_guard lock(incoming_cs); + empty = incoming.empty(); + } if (empty) { #if CONNECTION_ENABLE_TIMEOUT_DISCONNECT if (noInputTicks++ == MAX_TICKS_WITHOUT_INPUT) { @@ -461,16 +458,17 @@ void Connection::tick() { // changed to use a eAppAction_ExitPlayerPreLogin which will run in the main // loop, so the connection will not be ticked at that point - EnterCriticalSection(&incoming_cs); // 4J Stu - If disconnected, then we shouldn't process incoming packets std::vector > packetsToHandle; - while (!disconnected && !g_NetworkManager.IsLeavingGame() && - g_NetworkManager.IsInSession() && !incoming.empty() && max-- >= 0) { - std::shared_ptr packet = incoming.front(); - packetsToHandle.push_back(packet); - incoming.pop(); + { + std::lock_guard lock(incoming_cs); + while (!disconnected && !g_NetworkManager.IsLeavingGame() && + g_NetworkManager.IsInSession() && !incoming.empty() && max-- >= 0) { + std::shared_ptr packet = incoming.front(); + packetsToHandle.push_back(packet); + incoming.pop(); + } } - LeaveCriticalSection(&incoming_cs); // MGH - moved the packet handling outside of the incoming_cs block, as it // was locking up sometimes when disconnecting @@ -492,9 +490,11 @@ void Connection::tick() { // 4J - split the following condition (used to be disconnect && // iscoming.empty()) so we can wrap the access in a critical section if (disconnected) { - EnterCriticalSection(&incoming_cs); - bool empty = incoming.empty(); - LeaveCriticalSection(&incoming_cs); + bool empty; + { + std::lock_guard lock(incoming_cs); + empty = incoming.empty(); + } if (empty) { packetListener->onDisconnect(disconnectReason, disconnectReasonObjects); @@ -540,11 +540,12 @@ int Connection::runRead(void* lpParam) { Compression::UseDefaultThreadStorage(); - CRITICAL_SECTION* cs = &con->threadCounterLock; + std::mutex* cs = &con->threadCounterLock; - EnterCriticalSection(cs); - con->readThreads++; - LeaveCriticalSection(cs); + { + std::lock_guard lock(*cs); + con->readThreads++; + } // try { @@ -587,11 +588,12 @@ int Connection::runWrite(void* lpParam) { Compression::UseDefaultThreadStorage(); - CRITICAL_SECTION* cs = &con->threadCounterLock; + std::mutex* cs = &con->threadCounterLock; - EnterCriticalSection(cs); - con->writeThreads++; - LeaveCriticalSection(cs); + { + std::lock_guard lock(*cs); + con->writeThreads++; + } // 4J Stu - Adding this to force us to run through the writeTick at least // once after the event is fired Otherwise there is a race between the @@ -614,9 +616,10 @@ int Connection::runWrite(void* lpParam) { } // 4J was in a finally block. - EnterCriticalSection(cs); - con->writeThreads--; - LeaveCriticalSection(cs); + { + std::lock_guard lock(*cs); + con->writeThreads--; + } ShutdownManager::HasFinished(ShutdownManager::eConnectionWriteThreads); return 0; diff --git a/Minecraft.World/Network/Connection.h b/Minecraft.World/Network/Connection.h index 2c7cec21e..c9b776b9c 100644 --- a/Minecraft.World/Network/Connection.h +++ b/Minecraft.World/Network/Connection.h @@ -8,6 +8,8 @@ #include "../Headers/net.minecraft.network.packet.h" #include "../Util/C4JThread.h" +#include + #include "Socket.h" // 4J JEV, size of the threads (bytes). @@ -54,7 +56,7 @@ private: std::queue > incoming; // 4J - was using synchronizedList... - CRITICAL_SECTION incoming_cs; // ... now has this critical section + std::mutex incoming_cs; // ... now has this critical section std::queue > outgoing; // 4J - was using synchronizedList - but don't think it is // required as usage is wrapped in writeLock critical section @@ -93,8 +95,8 @@ private: void _init(); // 4J Jev, these might be better of as private - CRITICAL_SECTION threadCounterLock; - CRITICAL_SECTION writeLock; + std::mutex threadCounterLock; + std::mutex writeLock; public: // 4J Jev, need to delete the critical section. diff --git a/Minecraft.World/Network/Socket.cpp b/Minecraft.World/Network/Socket.cpp index 3f8afba37..f0538ca1c 100644 --- a/Minecraft.World/Network/Socket.cpp +++ b/Minecraft.World/Network/Socket.cpp @@ -14,7 +14,7 @@ // link. 2 sockets can be created, one for either end of this local link, the // end (0 or 1) is passed as a parameter to the ctor. -CRITICAL_SECTION Socket::s_hostQueueLock[2]; +std::mutex Socket::s_hostQueueLock[2]; std::queue Socket::s_hostQueue[2]; Socket::SocketOutputStreamLocal* Socket::s_hostOutStream[2]; Socket::SocketInputStreamLocal* Socket::s_hostInStream[2]; @@ -26,7 +26,6 @@ void Socket::EnsureStreamsInitialised() { // concurrently. static bool initialized = []() -> bool { for (int i = 0; i < 2; i++) { - InitializeCriticalSection(&Socket::s_hostQueueLock[i]); s_hostOutStream[i] = new SocketOutputStreamLocal(i); s_hostInStream[i] = new SocketInputStreamLocal(i); } @@ -47,11 +46,13 @@ void Socket::Initialise(ServerConnection* serverConnection) { if (init) { // Streams already exist – just reset queue state and re-open streams. for (int i = 0; i < 2; i++) { - if (TryEnterCriticalSection(&s_hostQueueLock[i])) { - // Clear the queue - std::queue empty; - std::swap(s_hostQueue[i], empty); - LeaveCriticalSection(&s_hostQueueLock[i]); + { + std::unique_lock lock(s_hostQueueLock[i], std::try_to_lock); + if (lock.owns_lock()) { + // Clear the queue + std::queue empty; + std::swap(s_hostQueue[i], empty); + } } s_hostOutStream[i]->m_streamOpen = true; s_hostInStream[i]->m_streamOpen = true; @@ -94,7 +95,6 @@ Socket::Socket(INetworkPlayer* player, bool response /* = false*/, m_hostLocal = hostLocal; for (int i = 0; i < 2; i++) { - InitializeCriticalSection(&m_queueLockNetwork[i]); m_inputStream[i] = nullptr; m_outputStream[i] = nullptr; m_endClosed[i] = false; @@ -143,11 +143,12 @@ void Socket::pushDataToQueue(const std::uint8_t* pbData, std::size_t dataSize, return; } - EnterCriticalSection(&m_queueLockNetwork[queueIdx]); - for (std::size_t i = 0; i < dataSize; ++i) { - m_queueNetwork[queueIdx].push(*pbData++); + { + std::lock_guard lock(m_queueLockNetwork[queueIdx]); + for (std::size_t i = 0; i < dataSize; ++i) { + m_queueNetwork[queueIdx].push(*pbData++); + } } - LeaveCriticalSection(&m_queueLockNetwork[queueIdx]); } void Socket::addIncomingSocket(Socket* socket) { @@ -244,14 +245,15 @@ Socket::SocketInputStreamLocal::SocketInputStreamLocal(int queueIdx) { int Socket::SocketInputStreamLocal::read() { while (m_streamOpen && ShutdownManager::ShouldRun( ShutdownManager::eConnectionReadThreads)) { - if (TryEnterCriticalSection(&s_hostQueueLock[m_queueIdx])) { - if (s_hostQueue[m_queueIdx].size()) { - std::uint8_t retval = s_hostQueue[m_queueIdx].front(); - s_hostQueue[m_queueIdx].pop(); - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); - return retval; + { + std::unique_lock lock(s_hostQueueLock[m_queueIdx], std::try_to_lock); + if (lock.owns_lock()) { + if (s_hostQueue[m_queueIdx].size()) { + std::uint8_t retval = s_hostQueue[m_queueIdx].front(); + s_hostQueue[m_queueIdx].pop(); + return retval; + } } - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -269,16 +271,17 @@ int Socket::SocketInputStreamLocal::read(byteArray b) { int Socket::SocketInputStreamLocal::read(byteArray b, unsigned int offset, unsigned int length) { while (m_streamOpen) { - if (TryEnterCriticalSection(&s_hostQueueLock[m_queueIdx])) { - if (s_hostQueue[m_queueIdx].size() >= length) { - for (unsigned int i = 0; i < length; i++) { - b[i + offset] = s_hostQueue[m_queueIdx].front(); - s_hostQueue[m_queueIdx].pop(); + { + std::unique_lock lock(s_hostQueueLock[m_queueIdx], std::try_to_lock); + if (lock.owns_lock()) { + if (s_hostQueue[m_queueIdx].size() >= length) { + for (unsigned int i = 0; i < length; i++) { + b[i + offset] = s_hostQueue[m_queueIdx].front(); + s_hostQueue[m_queueIdx].pop(); + } + return length; } - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); - return length; } - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -287,9 +290,10 @@ int Socket::SocketInputStreamLocal::read(byteArray b, unsigned int offset, void Socket::SocketInputStreamLocal::close() { m_streamOpen = false; - EnterCriticalSection(&s_hostQueueLock[m_queueIdx]); - std::queue().swap(s_hostQueue[m_queueIdx]); - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); + { + std::lock_guard lock(s_hostQueueLock[m_queueIdx]); + std::queue().swap(s_hostQueue[m_queueIdx]); + } } /////////////////////////////////// Socket for output, on local connection @@ -304,9 +308,10 @@ void Socket::SocketOutputStreamLocal::write(unsigned int b) { if (m_streamOpen != true) { return; } - EnterCriticalSection(&s_hostQueueLock[m_queueIdx]); - s_hostQueue[m_queueIdx].push((std::uint8_t)b); - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); + { + std::lock_guard lock(s_hostQueueLock[m_queueIdx]); + s_hostQueue[m_queueIdx].push((std::uint8_t)b); + } } void Socket::SocketOutputStreamLocal::write(byteArray b) { @@ -319,19 +324,21 @@ void Socket::SocketOutputStreamLocal::write(byteArray b, unsigned int offset, return; } MemSect(12); - EnterCriticalSection(&s_hostQueueLock[m_queueIdx]); - for (unsigned int i = 0; i < length; i++) { - s_hostQueue[m_queueIdx].push(b[offset + i]); + { + std::lock_guard lock(s_hostQueueLock[m_queueIdx]); + for (unsigned int i = 0; i < length; i++) { + s_hostQueue[m_queueIdx].push(b[offset + i]); + } } - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); MemSect(0); } void Socket::SocketOutputStreamLocal::close() { m_streamOpen = false; - EnterCriticalSection(&s_hostQueueLock[m_queueIdx]); - std::queue().swap(s_hostQueue[m_queueIdx]); - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); + { + std::lock_guard lock(s_hostQueueLock[m_queueIdx]); + std::queue().swap(s_hostQueue[m_queueIdx]); + } } /////////////////////////////////// Socket for input, on network connection @@ -348,16 +355,16 @@ Socket::SocketInputStreamNetwork::SocketInputStreamNetwork(Socket* socket, int Socket::SocketInputStreamNetwork::read() { while (m_streamOpen && ShutdownManager::ShouldRun( ShutdownManager::eConnectionReadThreads)) { - if (TryEnterCriticalSection( - &m_socket->m_queueLockNetwork[m_queueIdx])) { - if (m_socket->m_queueNetwork[m_queueIdx].size()) { - std::uint8_t retval = - m_socket->m_queueNetwork[m_queueIdx].front(); - m_socket->m_queueNetwork[m_queueIdx].pop(); - LeaveCriticalSection(&m_socket->m_queueLockNetwork[m_queueIdx]); - return retval; + { + std::unique_lock lock(m_socket->m_queueLockNetwork[m_queueIdx], std::try_to_lock); + if (lock.owns_lock()) { + if (m_socket->m_queueNetwork[m_queueIdx].size()) { + std::uint8_t retval = + m_socket->m_queueNetwork[m_queueIdx].front(); + m_socket->m_queueNetwork[m_queueIdx].pop(); + return retval; + } } - LeaveCriticalSection(&m_socket->m_queueLockNetwork[m_queueIdx]); } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -375,18 +382,18 @@ int Socket::SocketInputStreamNetwork::read(byteArray b) { int Socket::SocketInputStreamNetwork::read(byteArray b, unsigned int offset, unsigned int length) { while (m_streamOpen) { - if (TryEnterCriticalSection( - &m_socket->m_queueLockNetwork[m_queueIdx])) { - if (m_socket->m_queueNetwork[m_queueIdx].size() >= length) { - for (unsigned int i = 0; i < length; i++) { - b[i + offset] = - m_socket->m_queueNetwork[m_queueIdx].front(); - m_socket->m_queueNetwork[m_queueIdx].pop(); + { + std::unique_lock lock(m_socket->m_queueLockNetwork[m_queueIdx], std::try_to_lock); + if (lock.owns_lock()) { + if (m_socket->m_queueNetwork[m_queueIdx].size() >= length) { + for (unsigned int i = 0; i < length; i++) { + b[i + offset] = + m_socket->m_queueNetwork[m_queueIdx].front(); + m_socket->m_queueNetwork[m_queueIdx].pop(); + } + return length; } - LeaveCriticalSection(&m_socket->m_queueLockNetwork[m_queueIdx]); - return length; } - LeaveCriticalSection(&m_socket->m_queueLockNetwork[m_queueIdx]); } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -441,11 +448,12 @@ void Socket::SocketOutputStreamNetwork::writeWithFlags(byteArray b, else queueIdx = SOCKET_CLIENT_END; - EnterCriticalSection(&m_socket->m_queueLockNetwork[queueIdx]); - for (unsigned int i = 0; i < length; i++) { - m_socket->m_queueNetwork[queueIdx].push(b[offset + i]); + { + std::lock_guard lock(m_socket->m_queueLockNetwork[queueIdx]); + for (unsigned int i = 0; i < length; i++) { + m_socket->m_queueNetwork[queueIdx].push(b[offset + i]); + } } - LeaveCriticalSection(&m_socket->m_queueLockNetwork[queueIdx]); } else { XRNM_SEND_BUFFER buffer; buffer.pbyData = &b[offset]; diff --git a/Minecraft.World/Network/Socket.h b/Minecraft.World/Network/Socket.h index dd811d940..18719598a 100644 --- a/Minecraft.World/Network/Socket.h +++ b/Minecraft.World/Network/Socket.h @@ -5,6 +5,7 @@ #include #include #endif +#include #include #include "../IO/Streams/InputStream.h" #include "../IO/Streams/OutputStream.h" @@ -107,14 +108,14 @@ private: int m_end; // 0 for client side or 1 for host side // For local connections between the host player and the server - static CRITICAL_SECTION s_hostQueueLock[2]; + static std::mutex s_hostQueueLock[2]; static std::queue s_hostQueue[2]; static SocketOutputStreamLocal* s_hostOutStream[2]; static SocketInputStreamLocal* s_hostInStream[2]; // For network connections std::queue m_queueNetwork[2]; // For input data - CRITICAL_SECTION m_queueLockNetwork[2]; // For input data + std::mutex m_queueLockNetwork[2]; // For input data SocketInputStreamNetwork* m_inputStream[2]; SocketOutputStreamNetwork* m_outputStream[2]; bool m_endClosed[2]; diff --git a/Minecraft.World/WorldGen/Biomes/BiomeCache.cpp b/Minecraft.World/WorldGen/Biomes/BiomeCache.cpp index 44f797141..75fc85b82 100644 --- a/Minecraft.World/WorldGen/Biomes/BiomeCache.cpp +++ b/Minecraft.World/WorldGen/Biomes/BiomeCache.cpp @@ -67,8 +67,6 @@ BiomeCache::BiomeCache(BiomeSource* source) { lastUpdateTime = 0; this->source = source; - - InitializeCriticalSection(&m_CS); } BiomeCache::~BiomeCache() { @@ -78,11 +76,10 @@ BiomeCache::~BiomeCache() { for (auto it = all.begin(); it != all.end(); ++it) { delete (*it); } - DeleteCriticalSection(&m_CS); } BiomeCache::Block* BiomeCache::getBlockAt(int x, int z) { - EnterCriticalSection(&m_CS); + std::lock_guard lock(m_CS); x >>= ZONE_SIZE_BITS; z >>= ZONE_SIZE_BITS; int64_t slot = @@ -99,7 +96,6 @@ BiomeCache::Block* BiomeCache::getBlockAt(int x, int z) { block = it->second; } block->lastUse = app.getAppTime(); - LeaveCriticalSection(&m_CS); return block; } @@ -116,7 +112,7 @@ float BiomeCache::getDownfall(int x, int z) { } void BiomeCache::update() { - EnterCriticalSection(&m_CS); + std::lock_guard lock(m_CS); int64_t now = app.getAppTime(); int64_t utime = now - lastUpdateTime; if (utime > DECAY_TIME / 4 || utime < 0) { @@ -136,7 +132,6 @@ void BiomeCache::update() { } } } - LeaveCriticalSection(&m_CS); } BiomeArray BiomeCache::getBiomeBlockAt(int x, int z) { diff --git a/Minecraft.World/WorldGen/Biomes/BiomeCache.h b/Minecraft.World/WorldGen/Biomes/BiomeCache.h index a5ab51bac..529461404 100644 --- a/Minecraft.World/WorldGen/Biomes/BiomeCache.h +++ b/Minecraft.World/WorldGen/Biomes/BiomeCache.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../Minecraft.World/Util/JavaIntHash.h" class BiomeCache { @@ -48,5 +49,5 @@ public: byteArray getBiomeIndexBlockAt(int x, int z); private: - CRITICAL_SECTION m_CS; + std::mutex m_CS; }; \ No newline at end of file From 57e4bdd973030cf5d7d4120ee4ac6fb5f340a4d4 Mon Sep 17 00:00:00 2001 From: MatthewBeshay <92357869+MatthewBeshay@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:12:22 +1100 Subject: [PATCH 2/7] Fix dirtyChunksLock scope in updateDirtyChunks Move unique_lock declaration before the FRAME_PROFILE_SCOPE block so it remains in scope for the unlock() calls in the #if/#else branches below. --- Minecraft.Client/Rendering/LevelRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Minecraft.Client/Rendering/LevelRenderer.cpp b/Minecraft.Client/Rendering/LevelRenderer.cpp index bd5fb6d0f..201b2f174 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.cpp +++ b/Minecraft.Client/Rendering/LevelRenderer.cpp @@ -1698,6 +1698,7 @@ bool LevelRenderer::updateDirtyChunks() { ClipChunk* nearChunk = nullptr; // Nearest chunk that is dirty int veryNearCount = 0; int minDistSq = 0x7fffffff; // Distances to this chunk + std::unique_lock dirtyChunksLock(m_csDirtyChunks); // Set a flag if we should only rebuild existing chunks, not create anything // new @@ -1716,7 +1717,6 @@ bool LevelRenderer::updateDirtyChunks() { PIXAddNamedCounter(((float)memAlloc) / (1024.0f * 1024.0f), "Command buffer allocations"); bool onlyRebuild = (memAlloc >= MAX_COMMANDBUFFER_ALLOCATIONS); - std::unique_lock dirtyChunksLock(m_csDirtyChunks); // Move any dirty chunks stored in the lock free stack into global flags int index = 0; From e4520df31f942047fcf70cd718c95f7aff33303d Mon Sep 17 00:00:00 2001 From: MatthewBeshay <92357869+MatthewBeshay@users.noreply.github.com> Date: Mon, 30 Mar 2026 22:14:14 +1100 Subject: [PATCH 3/7] Restore recursive locking for mutexes converted from CRITICAL_SECTION CRITICAL_SECTION is reentrant; std::mutex is not. This caused deadlocks during world generation, post-processing, and saving. --- Minecraft.Client/Level/ServerLevel.cpp | 70 +++++++++---------- Minecraft.Client/Level/ServerLevel.h | 8 +-- Minecraft.Client/Minecraft.cpp | 4 +- Minecraft.Client/Minecraft.h | 2 +- Minecraft.Client/Network/ServerChunkCache.cpp | 8 +-- Minecraft.Client/Network/ServerChunkCache.h | 2 +- .../Common/UI/UIComponent_Panorama.cpp | 2 +- Minecraft.Client/Rendering/Chunk.cpp | 4 +- .../EntityRenderers/ProgressRenderer.cpp | 22 +++--- .../EntityRenderers/ProgressRenderer.h | 2 +- Minecraft.Client/Rendering/LevelRenderer.cpp | 4 +- Minecraft.Client/Rendering/LevelRenderer.h | 2 +- .../IO/Files/ConsoleSaveFileOriginal.h | 2 +- .../IO/Files/ConsoleSaveFileSplit.h | 2 +- Minecraft.World/Level/LevelChunk.cpp | 52 +++++++------- Minecraft.World/Level/LevelChunk.h | 6 +- .../Level/Storage/CompressedTileStorage.cpp | 12 ++-- .../Level/Storage/CompressedTileStorage.h | 2 +- .../Level/Storage/OldChunkStorage.cpp | 2 +- 19 files changed, 104 insertions(+), 104 deletions(-) diff --git a/Minecraft.Client/Level/ServerLevel.cpp b/Minecraft.Client/Level/ServerLevel.cpp index 34b8ccd5c..2686f7a5a 100644 --- a/Minecraft.Client/Level/ServerLevel.cpp +++ b/Minecraft.Client/Level/ServerLevel.cpp @@ -46,7 +46,7 @@ WeighedTreasureArray ServerLevel::RANDOM_BONUS_ITEMS; C4JThread* ServerLevel::m_updateThread = nullptr; C4JThread::EventArray* ServerLevel::m_updateTrigger; -std::mutex ServerLevel::m_updateCS[3]; +std::recursive_mutex ServerLevel::m_updateCS[3]; Level* ServerLevel::m_level[3]; int ServerLevel::m_updateChunkX[3][LEVEL_CHUNKS_TO_UPDATE_MAX]; @@ -184,7 +184,7 @@ ServerLevel::~ServerLevel() { delete mobSpawner; { - std::lock_guard lock(m_csQueueSendTileUpdates); + std::lock_guard lock(m_csQueueSendTileUpdates); for (auto it = m_queuedSendTileUpdates.begin(); it != m_queuedSendTileUpdates.end(); ++it) { Pos* p = *it; @@ -198,9 +198,9 @@ ServerLevel::~ServerLevel() { } // Make sure that the update thread isn't actually doing any updating - { std::lock_guard lock(m_updateCS[0]); } - { std::lock_guard lock(m_updateCS[1]); } - { std::lock_guard lock(m_updateCS[2]); } + { std::lock_guard lock(m_updateCS[0]); } + { std::lock_guard lock(m_updateCS[1]); } + { std::lock_guard lock(m_updateCS[2]); } m_updateTrigger->ClearAll(); } @@ -440,7 +440,7 @@ void ServerLevel::tickTiles() { unsigned int tickCount = 0; { - std::lock_guard lock(m_updateCS[iLev]); + std::lock_guard lock(m_updateCS[iLev]); // This section processes the tiles that need to be ticked, which we worked // out in the previous tick (or haven't yet, if this is the first frame) /*int grassTicks = 0; @@ -594,7 +594,7 @@ void ServerLevel::addToTickNextTick(int x, int y, int z, int tileId, td.setPriorityTilt(priorityTilt); } { - std::lock_guard lock(m_tickNextTickCS); + std::lock_guard lock(m_tickNextTickCS); if (tickNextTickSet.find(td) == tickNextTickSet.end()) { tickNextTickSet.insert(td); tickNextTickList.insert(td); @@ -613,7 +613,7 @@ void ServerLevel::forceAddTileTick(int x, int y, int z, int tileId, td.delay(tickDelay + levelData->getGameTime()); } { - std::lock_guard lock(m_tickNextTickCS); + std::lock_guard lock(m_tickNextTickCS); if (tickNextTickSet.find(td) == tickNextTickSet.end()) { tickNextTickSet.insert(td); tickNextTickList.insert(td); @@ -636,7 +636,7 @@ void ServerLevel::tickEntities() { void ServerLevel::resetEmptyTime() { emptyTime = 0; } bool ServerLevel::tickPendingTicks(bool force) { - std::lock_guard lock(m_tickNextTickCS); + std::lock_guard lock(m_tickNextTickCS); int count = (int)tickNextTickList.size(); int count2 = (int)tickNextTickSet.size(); if (count != tickNextTickSet.size()) { @@ -685,7 +685,7 @@ bool ServerLevel::tickPendingTicks(bool force) { std::vector* ServerLevel::fetchTicksInChunk(LevelChunk* chunk, bool remove) { - std::lock_guard lock(m_tickNextTickCS); + std::lock_guard lock(m_tickNextTickCS); std::vector* results = new std::vector; ChunkPos* pos = chunk->getPos(); @@ -1215,12 +1215,12 @@ void ServerLevel::sendParticles(const std::wstring& name, double x, double y, // 4J Stu - Sometimes we want to update tiles on the server from the main thread // (eg SignTileEntity when string verify returns) void ServerLevel::queueSendTileUpdate(int x, int y, int z) { - std::lock_guard lock(m_csQueueSendTileUpdates); + std::lock_guard lock(m_csQueueSendTileUpdates); m_queuedSendTileUpdates.push_back(new Pos(x, y, z)); } void ServerLevel::runQueuedSendTileUpdates() { - std::lock_guard lock(m_csQueueSendTileUpdates); + std::lock_guard lock(m_csQueueSendTileUpdates); for (auto it = m_queuedSendTileUpdates.begin(); it != m_queuedSendTileUpdates.end(); ++it) { Pos* p = *it; @@ -1237,7 +1237,7 @@ bool ServerLevel::addEntity(std::shared_ptr e) { if (e->instanceof(eTYPE_ITEMENTITY)) { // printf("Adding item entity count //%d\n",m_itemEntities.size()); - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_itemEntities.size() >= MAX_ITEM_ENTITIES) { // printf("Adding - doing remove\n"); removeEntityImmediately(m_itemEntities.front()); @@ -1248,7 +1248,7 @@ bool ServerLevel::addEntity(std::shared_ptr e) { else if (e->instanceof(eTYPE_HANGING_ENTITY)) { // printf("Adding item entity count //%d\n",m_itemEntities.size()); - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_hangingEntities.size() >= MAX_HANGING_ENTITIES) { // printf("Adding - doing remove\n"); @@ -1263,7 +1263,7 @@ bool ServerLevel::addEntity(std::shared_ptr e) { else if (e->instanceof(eTYPE_ARROW)) { // printf("Adding arrow entity count //%d\n",m_arrowEntities.size()); - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_arrowEntities.size() >= MAX_ARROW_ENTITIES) { // printf("Adding - doing remove\n"); removeEntityImmediately(m_arrowEntities.front()); @@ -1274,7 +1274,7 @@ bool ServerLevel::addEntity(std::shared_ptr e) { else if (e->instanceof(eTYPE_EXPERIENCEORB)) { // printf("Adding arrow entity count //%d\n",m_arrowEntities.size()); - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_experienceOrbEntities.size() >= MAX_EXPERIENCEORB_ENTITIES) { // printf("Adding - doing remove\n"); removeEntityImmediately(m_experienceOrbEntities.front()); @@ -1291,16 +1291,16 @@ bool ServerLevel::atEntityLimit(std::shared_ptr e) { bool atLimit = false; if (e->instanceof(eTYPE_ITEMENTITY)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_itemEntities.size() >= MAX_ITEM_ENTITIES; } else if (e->instanceof(eTYPE_HANGING_ENTITY)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_hangingEntities.size() >= MAX_HANGING_ENTITIES; } else if (e->instanceof(eTYPE_ARROW)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_arrowEntities.size() >= MAX_ARROW_ENTITIES; } else if (e->instanceof(eTYPE_EXPERIENCEORB)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_experienceOrbEntities.size() >= MAX_EXPERIENCEORB_ENTITIES; } @@ -1310,30 +1310,30 @@ bool ServerLevel::atEntityLimit(std::shared_ptr e) { // Maintain a cound of primed tnt & falling tiles in this level void ServerLevel::entityAddedExtra(std::shared_ptr e) { if (e->instanceof(eTYPE_ITEMENTITY)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); m_itemEntities.push_back(e); // printf("entity added: item entity count now //%d\n",m_itemEntities.size()); } else if (e->instanceof(eTYPE_HANGING_ENTITY)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); m_hangingEntities.push_back(e); // printf("entity added: item entity count now //%d\n",m_itemEntities.size()); } else if (e->instanceof(eTYPE_ARROW)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); m_arrowEntities.push_back(e); // printf("entity added: arrow entity count now //%d\n",m_arrowEntities.size()); } else if (e->instanceof(eTYPE_EXPERIENCEORB)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); m_experienceOrbEntities.push_back(e); // printf("entity added: experience orb entity count now //%d\n",m_arrowEntities.size()); } else if (e->instanceof(eTYPE_PRIMEDTNT)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); m_primedTntCount++; } else if (e->instanceof(eTYPE_FALLINGTILE)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); m_fallingTileCount++; } } @@ -1342,7 +1342,7 @@ void ServerLevel::entityAddedExtra(std::shared_ptr e) { // item entities from our list void ServerLevel::entityRemovedExtra(std::shared_ptr e) { if (e->instanceof(eTYPE_ITEMENTITY)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: item entity count //%d\n",m_itemEntities.size()); auto it = find(m_itemEntities.begin(), m_itemEntities.end(), e); @@ -1353,7 +1353,7 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { // printf("entity removed: item entity count now //%d\n",m_itemEntities.size()); } else if (e->instanceof(eTYPE_HANGING_ENTITY)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: item entity count //%d\n",m_itemEntities.size()); auto it = find(m_hangingEntities.begin(), m_hangingEntities.end(), e); @@ -1364,7 +1364,7 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { // printf("entity removed: item entity count now //%d\n",m_itemEntities.size()); } else if (e->instanceof(eTYPE_ARROW)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: arrow entity count //%d\n",m_arrowEntities.size()); auto it = find(m_arrowEntities.begin(), m_arrowEntities.end(), e); @@ -1375,7 +1375,7 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { // printf("entity removed: arrow entity count now //%d\n",m_arrowEntities.size()); } else if (e->instanceof(eTYPE_EXPERIENCEORB)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: experience orb entity count //%d\n",m_arrowEntities.size()); auto it = find(m_experienceOrbEntities.begin(), @@ -1387,22 +1387,22 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { // printf("entity removed: experience orb entity count now //%d\n",m_arrowEntities.size()); } else if (e->instanceof(eTYPE_PRIMEDTNT)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); m_primedTntCount--; } else if (e->instanceof(eTYPE_FALLINGTILE)) { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); m_fallingTileCount--; } } bool ServerLevel::newPrimedTntAllowed() { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); bool retval = m_primedTntCount < MAX_PRIMED_TNT; return retval; } bool ServerLevel::newFallingTileAllowed() { - std::lock_guard lock(m_limiterCS); + std::lock_guard lock(m_limiterCS); bool retval = m_fallingTileCount < MAX_FALLING_TILE; return retval; } @@ -1422,7 +1422,7 @@ int ServerLevel::runUpdate(void* lpParam) { int grassTicks = 0; int lavaTicks = 0; for (unsigned int iLev = 0; iLev < 3; ++iLev) { - std::lock_guard lock(m_updateCS[iLev]); + std::lock_guard lock(m_updateCS[iLev]); for (int i = 0; i < m_updateChunkCount[iLev]; i++) { // 4J - some of these tile ticks will check things in // neighbouring tiles, causing chunks to load/create that aren't diff --git a/Minecraft.Client/Level/ServerLevel.h b/Minecraft.Client/Level/ServerLevel.h index 74b5e87dd..852b391a3 100644 --- a/Minecraft.Client/Level/ServerLevel.h +++ b/Minecraft.Client/Level/ServerLevel.h @@ -17,7 +17,7 @@ private: EntityTracker* tracker; PlayerChunkMap* chunkMap; - std::mutex m_tickNextTickCS; // 4J added + std::recursive_mutex m_tickNextTickCS; // 4J added std::set tickNextTickList; // 4J Was TreeSet std::unordered_set m_queuedSendTileUpdates; // 4J added - std::mutex m_csQueueSendTileUpdates; + std::recursive_mutex m_csQueueSendTileUpdates; protected: int saveInterval; @@ -178,7 +178,7 @@ public: int m_primedTntCount; int m_fallingTileCount; - std::mutex m_limiterCS; + std::recursive_mutex m_limiterCS; std::list > m_itemEntities; std::list > m_hangingEntities; std::list > m_arrowEntities; @@ -212,7 +212,7 @@ public: static int m_randValue[3]; static C4JThread::EventArray* m_updateTrigger; - static std::mutex m_updateCS[3]; + static std::recursive_mutex m_updateCS[3]; static C4JThread* m_updateThread; static int runUpdate(void* lpParam); diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 1ebd7660b..faf44a939 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -987,7 +987,7 @@ void Minecraft::run_middle() { } #endif - { std::lock_guard lock(m_setLevelCS); + { std::lock_guard lock(m_setLevelCS); if (running) { if (reloadTextures) { @@ -3669,7 +3669,7 @@ void Minecraft::setLevel(MultiPlayerLevel* level, int message /*=-1*/, std::shared_ptr forceInsertPlayer /*=nullptr*/, bool doForceStatsSave /*=true*/, bool bPrimaryPlayerSignedOut /*=false*/) { - std::lock_guard lock(m_setLevelCS); + std::lock_guard lock(m_setLevelCS); bool playerAdded = false; this->cameraTargetPlayer = nullptr; diff --git a/Minecraft.Client/Minecraft.h b/Minecraft.Client/Minecraft.h index b2fd0c8eb..751fec019 100644 --- a/Minecraft.Client/Minecraft.h +++ b/Minecraft.Client/Minecraft.h @@ -348,7 +348,7 @@ public: // 4J Stu void forceStatsSave(int idx); - std::mutex m_setLevelCS; + std::recursive_mutex m_setLevelCS; private: // A bit field that store whether a particular quadrant is in the full diff --git a/Minecraft.Client/Network/ServerChunkCache.cpp b/Minecraft.Client/Network/ServerChunkCache.cpp index 0b14d68d9..566fea724 100644 --- a/Minecraft.Client/Network/ServerChunkCache.cpp +++ b/Minecraft.Client/Network/ServerChunkCache.cpp @@ -144,7 +144,7 @@ LevelChunk* ServerChunkCache::create( LevelChunk* lastChunk = chunk; if ((chunk == nullptr) || (chunk->x != x) || (chunk->z != z)) { - { std::lock_guard lock(m_csLoadCreate); + { std::lock_guard lock(m_csLoadCreate); chunk = load(x, z); if (chunk == nullptr) { if (source == nullptr) { @@ -169,7 +169,7 @@ LevelChunk* ServerChunkCache::create( #endif { // Successfully updated the cache - std::lock_guard lock(m_csLoadCreate); + std::lock_guard lock(m_csLoadCreate); // 4J - added - this will run a recalcHeightmap if source is a // randomlevelsource, which has been split out from source::getChunk // so that we are doing it after the chunk has been added to the @@ -649,7 +649,7 @@ bool ServerChunkCache::saveAllEntities() { PIXBeginNamedEvent(0, "Save all entities"); PIXBeginNamedEvent(0, "saving to NBT"); - { std::lock_guard lock(m_csLoadCreate); + { std::lock_guard lock(m_csLoadCreate); for (auto it = m_loadedChunkList.begin(); it != m_loadedChunkList.end(); ++it) { storage->saveEntities(level, *it); @@ -666,7 +666,7 @@ bool ServerChunkCache::saveAllEntities() { } bool ServerChunkCache::save(bool force, ProgressListener* progressListener) { - std::lock_guard lock(m_csLoadCreate); + std::lock_guard lock(m_csLoadCreate); int saves = 0; // 4J - added this to support progressListner diff --git a/Minecraft.Client/Network/ServerChunkCache.h b/Minecraft.Client/Network/ServerChunkCache.h index d39049ac6..ee9d30caa 100644 --- a/Minecraft.Client/Network/ServerChunkCache.h +++ b/Minecraft.Client/Network/ServerChunkCache.h @@ -31,7 +31,7 @@ private: #endif // 4J - added for multithreaded support - std::mutex m_csLoadCreate; + std::recursive_mutex m_csLoadCreate; // 4J - size of cache is defined by size of one side - must be even int XZSIZE; int XZOFFSET; diff --git a/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp b/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp index e54781483..2e096319d 100644 --- a/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp @@ -44,7 +44,7 @@ void UIComponent_Panorama::tick() { Minecraft* pMinecraft = Minecraft::GetInstance(); { - std::lock_guard lock(pMinecraft->m_setLevelCS); + std::lock_guard lock(pMinecraft->m_setLevelCS); if (pMinecraft->level != nullptr) { int64_t i64TimeOfDay = 0; // are we in the Nether? - Leave the time as 0 if we are, so we show diff --git a/Minecraft.Client/Rendering/Chunk.cpp b/Minecraft.Client/Rendering/Chunk.cpp index 9caf9c73d..9b3681b46 100644 --- a/Minecraft.Client/Rendering/Chunk.cpp +++ b/Minecraft.Client/Rendering/Chunk.cpp @@ -151,7 +151,7 @@ void Chunk::setPos(int x, int y, int z) { assigned = true; { - std::lock_guard lock(levelRenderer->m_csDirtyChunks); + std::lock_guard lock(levelRenderer->m_csDirtyChunks); unsigned char refCount = levelRenderer->incGlobalChunkRefCount(x, y, z, level); // printf("\t\t [inc] refcount %d at %d, %d, %d\n",refCount,x,y,z); @@ -722,7 +722,7 @@ void Chunk::reset() { bool retireRenderableTileEntities = false; { - std::lock_guard lock(levelRenderer->m_csDirtyChunks); + std::lock_guard lock(levelRenderer->m_csDirtyChunks); oldKey = levelRenderer->getGlobalIndexForChunk(x, y, z, level); unsigned char refCount = levelRenderer->decGlobalChunkRefCount(x, y, z, level); diff --git a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp index 3851c94a9..795daf8fb 100644 --- a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp +++ b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp @@ -4,7 +4,7 @@ #include "ProgressRenderer.h" #include "../../../Minecraft.World/Platform/System.h" -std::mutex ProgressRenderer::s_progress; +std::recursive_mutex ProgressRenderer::s_progress; ProgressRenderer::ProgressRenderer(Minecraft* minecraft) { status = -1; @@ -34,7 +34,7 @@ void ProgressRenderer::_progressStart(int title) { } { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); lastPercent = 0; this->title = title; } @@ -48,7 +48,7 @@ void ProgressRenderer::progressStage(int status) { lastTime = 0; { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); m_eType = eProgressStringType_ID; this->status = status; } @@ -60,7 +60,7 @@ void ProgressRenderer::progressStagePercentage(int i) { // 4J Stu - Removing all progressRenderer rendering. This will be replaced // on the xbox { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); lastPercent = i; } } @@ -68,7 +68,7 @@ void ProgressRenderer::progressStagePercentage(int i) { int ProgressRenderer::getCurrentPercent() { int returnValue = 0; { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); returnValue = lastPercent; } return returnValue; @@ -77,7 +77,7 @@ int ProgressRenderer::getCurrentPercent() { int ProgressRenderer::getCurrentTitle() { int returnValue; { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); returnValue = title; } return returnValue; @@ -86,7 +86,7 @@ int ProgressRenderer::getCurrentTitle() { int ProgressRenderer::getCurrentStatus() { int returnValue; { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); returnValue = status; } return returnValue; @@ -95,25 +95,25 @@ int ProgressRenderer::getCurrentStatus() { ProgressRenderer::eProgressStringType ProgressRenderer::getType() { eProgressStringType returnValue; { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); returnValue = m_eType; } return returnValue; } void ProgressRenderer::setType(eProgressStringType eType) { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); m_eType = eType; } void ProgressRenderer::progressStage(std::wstring& wstrText) { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); m_wstrText = wstrText; m_eType = eProgressStringType_String; } std::wstring& ProgressRenderer::getProgressString(void) { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); std::wstring& temp = m_wstrText; return temp; } diff --git a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h index 97d35f0ef..5de0a6c95 100644 --- a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h +++ b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h @@ -10,7 +10,7 @@ public: // on a save transfer }; - static std::mutex s_progress; + static std::recursive_mutex s_progress; int getCurrentPercent(); int getCurrentTitle(); diff --git a/Minecraft.Client/Rendering/LevelRenderer.cpp b/Minecraft.Client/Rendering/LevelRenderer.cpp index 201b2f174..540c5cb29 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.cpp +++ b/Minecraft.Client/Rendering/LevelRenderer.cpp @@ -648,7 +648,7 @@ std::wstring LevelRenderer::gatherStats2() { } void LevelRenderer::resortChunks(int xc, int yc, int zc) { - std::lock_guard lock(m_csDirtyChunks); + std::lock_guard lock(m_csDirtyChunks); xc -= CHUNK_XZSIZE / 2; yc -= CHUNK_SIZE / 2; zc -= CHUNK_XZSIZE / 2; @@ -1698,7 +1698,7 @@ bool LevelRenderer::updateDirtyChunks() { ClipChunk* nearChunk = nullptr; // Nearest chunk that is dirty int veryNearCount = 0; int minDistSq = 0x7fffffff; // Distances to this chunk - std::unique_lock dirtyChunksLock(m_csDirtyChunks); + std::unique_lock dirtyChunksLock(m_csDirtyChunks); // Set a flag if we should only rebuild existing chunks, not create anything // new diff --git a/Minecraft.Client/Rendering/LevelRenderer.h b/Minecraft.Client/Rendering/LevelRenderer.h index 7e187e998..f237ebe5c 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.h +++ b/Minecraft.Client/Rendering/LevelRenderer.h @@ -216,7 +216,7 @@ private: public: void fullyFlagRenderableTileEntitiesToBeRemoved(); // 4J added - std::mutex m_csDirtyChunks; + std::recursive_mutex m_csDirtyChunks; bool m_nearDirtyChunk; // 4J - Destroyed Tile Management - these things added so we can track tiles diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h index 05ac4981b..3109a4e58 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h +++ b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h @@ -24,7 +24,7 @@ private: #endif void* pvSaveMem; - std::mutex m_lock; + std::recursive_mutex m_lock; void PrepareForWrite(FileEntry* file, unsigned int nNumberOfBytesToWrite); void MoveDataBeyond(FileEntry* file, unsigned int nNumberOfBytesToWrite); diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h index 4bbd0a6f8..dc42f5564 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h +++ b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h @@ -80,7 +80,7 @@ private: #endif void* pvSaveMem; - std::mutex m_lock; + std::recursive_mutex m_lock; void PrepareForWrite(FileEntry* file, unsigned int nNumberOfBytesToWrite); void MoveDataBeyond(FileEntry* file, unsigned int nNumberOfBytesToWrite); diff --git a/Minecraft.World/Level/LevelChunk.cpp b/Minecraft.World/Level/LevelChunk.cpp index 7c7235714..751a466fb 100644 --- a/Minecraft.World/Level/LevelChunk.cpp +++ b/Minecraft.World/Level/LevelChunk.cpp @@ -22,16 +22,16 @@ #include #if defined(SHARING_ENABLED) -std::mutex LevelChunk::m_csSharing; +std::recursive_mutex LevelChunk::m_csSharing; #endif #if defined(_ENTITIES_RW_SECTION) // AP - use a RW critical section so we can have multiple threads reading the // same data to avoid a clash CRITICAL_RW_SECTION LevelChunk::m_csEntities; #else -std::mutex LevelChunk::m_csEntities; +std::recursive_mutex LevelChunk::m_csEntities; #endif -std::mutex LevelChunk::m_csTileEntities; +std::recursive_mutex LevelChunk::m_csTileEntities; bool LevelChunk::touchedSky = false; void LevelChunk::staticCtor() { @@ -48,7 +48,7 @@ void LevelChunk::init(Level* level, int x, int z) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); #endif entityBlocks = new std::vector >*[ENTITY_BLOCKS_LENGTH]; @@ -79,7 +79,7 @@ void LevelChunk::init(Level* level, int x, int z) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { entityBlocks[i] = new std::vector >(); @@ -249,7 +249,7 @@ void LevelChunk::setUnsaved(bool unsaved) { void LevelChunk::stopSharingTilesAndData() { #if defined(SHARING_ENABLED) - { std::lock_guard lock(m_csSharing); + { std::lock_guard lock(m_csSharing); lastUnsharedTime = System::currentTimeMillis(); if (!sharingTilesAndData) { return; @@ -315,7 +315,7 @@ void LevelChunk::stopSharingTilesAndData() { // not sharing void LevelChunk::reSyncLighting() { #if defined(SHARING_ENABLED) - { std::lock_guard lock(m_csSharing); + { std::lock_guard lock(m_csSharing); if (isEmpty()) { return; @@ -352,7 +352,7 @@ void LevelChunk::reSyncLighting() { void LevelChunk::startSharingTilesAndData(int forceMs) { #if defined(SHARING_ENABLED) - { std::lock_guard lock(m_csSharing); + { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { return; } @@ -1178,7 +1178,7 @@ void LevelChunk::addEntity(std::shared_ptr e) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); #endif entityBlocks[yc]->push_back(e); #if defined(_ENTITIES_RW_SECTION) @@ -1199,7 +1199,7 @@ void LevelChunk::removeEntity(std::shared_ptr e, int yc) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); #endif // 4J - was entityBlocks[yc]->remove(e); @@ -1242,7 +1242,7 @@ std::shared_ptr LevelChunk::getTileEntity(int x, int y, int z) { // insert when we don't want one) // shared_ptr tileEntity = tileEntities[pos]; std::shared_ptr tileEntity = nullptr; - { std::unique_lock lock(m_csTileEntities); + { std::unique_lock lock(m_csTileEntities); auto it = tileEntities.find(pos); if (it == tileEntities.end()) { @@ -1273,7 +1273,7 @@ std::shared_ptr LevelChunk::getTileEntity(int x, int y, int z) { // doesn't seem right - assignment wrong way? Check // 4J Stu - It should have been inserted by now, but check to be sure - { std::lock_guard lock2(m_csTileEntities); + { std::lock_guard lock2(m_csTileEntities); auto newIt = tileEntities.find(pos); if (newIt != tileEntities.end()) { tileEntity = newIt->second; @@ -1284,7 +1284,7 @@ std::shared_ptr LevelChunk::getTileEntity(int x, int y, int z) { } } if (tileEntity != nullptr && tileEntity->isRemoved()) { - { std::lock_guard lock(m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); tileEntities.erase(pos); } return nullptr; @@ -1330,7 +1330,7 @@ void LevelChunk::setTileEntity(int x, int y, int z, tileEntity->clearRemoved(); - { std::lock_guard lock(m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); tileEntities[pos] = tileEntity; } } @@ -1344,7 +1344,7 @@ void LevelChunk::removeTileEntity(int x, int y, int z) { // if (removeThis != null) { // removeThis.setRemoved(); // } - { std::lock_guard lock(m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); auto it = tileEntities.find(pos); if (it != tileEntities.end()) { std::shared_ptr te = tileEntities[pos]; @@ -1402,7 +1402,7 @@ void LevelChunk::load() { #endif std::vector > values; - { std::lock_guard lock(m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); for (auto it = tileEntities.begin(); it != tileEntities.end(); it++) { values.push_back(it->second); } @@ -1412,7 +1412,7 @@ void LevelChunk::load() { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { level->addEntities(entityBlocks[i]); @@ -1434,7 +1434,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter loaded = false; if (unloadTileEntities) { std::vector > tileEntitiesToRemove; - { std::lock_guard lock(m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); for (auto it = tileEntities.begin(); it != tileEntities.end(); it++) { tileEntitiesToRemove.push_back(it->second); } @@ -1450,7 +1450,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { level->removeEntities(entityBlocks[i]); @@ -1475,7 +1475,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter PIXBeginNamedEvent(0, "Saving entities"); ListTag* entityTags = new ListTag(); - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { auto itEnd = entityBlocks[i]->end(); for (std::vector >::iterator it = @@ -1523,7 +1523,7 @@ bool LevelChunk::containsPlayer() { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { std::vector >* vecEntity = entityBlocks[i]; @@ -1561,7 +1561,7 @@ void LevelChunk::getEntities(std::shared_ptr except, AABB* bb, // AP - RW critical sections are expensive so enter once in // Level::getEntities - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); for (int yc = yc0; yc <= yc1; yc++) { std::vector >* entities = entityBlocks[yc]; @@ -1607,7 +1607,7 @@ void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, // AP - RW critical sections are expensive so enter once in // Level::getEntitiesOfClass - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); for (int yc = yc0; yc <= yc1; yc++) { std::vector >* entities = entityBlocks[yc]; @@ -1655,7 +1655,7 @@ int LevelChunk::countEntities() { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, false); #else - { std::lock_guard lock(m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int yc = 0; yc < ENTITY_BLOCKS_LENGTH; yc++) { entityCount += (int)entityBlocks[yc]->size(); @@ -2208,7 +2208,7 @@ void LevelChunk::compressBlocks() { // Note - only the extraction of the pointers needs to be done in the // critical section, since even if the data is unshared whilst we are // processing this data is still valid (for the server) - { std::lock_guard lock(m_csSharing); + { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { blocksToCompressLower = lowerBlocks; blocksToCompressUpper = upperBlocks; @@ -2307,7 +2307,7 @@ void LevelChunk::compressData() { // Note - only the extraction of the pointers needs to be done in the // critical section, since even if the data is unshared whilst we are // processing this data is still valid (for the server) - { std::lock_guard lock(m_csSharing); + { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { dataToCompressLower = lowerData; dataToCompressUpper = upperData; diff --git a/Minecraft.World/Level/LevelChunk.h b/Minecraft.World/Level/LevelChunk.h index 56356c3e8..0dd5df669 100644 --- a/Minecraft.World/Level/LevelChunk.h +++ b/Minecraft.World/Level/LevelChunk.h @@ -270,7 +270,7 @@ public: virtual void attemptCompression(); #if defined(SHARING_ENABLED) - static std::mutex m_csSharing; // 4J added + static std::recursive_mutex m_csSharing; // 4J added #endif // 4J added #if defined(_ENTITIES_RW_SECTION) @@ -278,9 +278,9 @@ public: m_csEntities; // AP - we're using a RW critical so we can do multiple // reads without contention #else - static std::mutex m_csEntities; + static std::recursive_mutex m_csEntities; #endif - static std::mutex m_csTileEntities; // 4J added + static std::recursive_mutex m_csTileEntities; // 4J added static void staticCtor(); void checkPostProcess(ChunkSource* source, ChunkSource* parent, int x, int z); diff --git a/Minecraft.World/Level/Storage/CompressedTileStorage.cpp b/Minecraft.World/Level/Storage/CompressedTileStorage.cpp index 2c668933c..46c1da9eb 100644 --- a/Minecraft.World/Level/Storage/CompressedTileStorage.cpp +++ b/Minecraft.World/Level/Storage/CompressedTileStorage.cpp @@ -6,7 +6,7 @@ int CompressedTileStorage::deleteQueueIndex; XLockFreeStack CompressedTileStorage::deleteQueue[3]; -std::mutex CompressedTileStorage::cs_write; +std::recursive_mutex CompressedTileStorage::cs_write; #if defined(PSVITA_PRECOMPUTED_TABLE) // AP - this will create a precomputed table to speed up getData @@ -33,7 +33,7 @@ CompressedTileStorage::CompressedTileStorage() { } CompressedTileStorage::CompressedTileStorage(CompressedTileStorage* copyFrom) { - { std::lock_guard lock(cs_write); + { std::lock_guard lock(cs_write); allocatedSize = copyFrom->allocatedSize; if (allocatedSize > 0) { indicesAndData = (unsigned char*)XPhysicalAlloc( @@ -139,7 +139,7 @@ bool CompressedTileStorage::isRenderChunkEmpty( } bool CompressedTileStorage::isSameAs(CompressedTileStorage* other) { - std::lock_guard lock(cs_write); + std::lock_guard lock(cs_write); if (allocatedSize != other->allocatedSize) { return false; } @@ -238,7 +238,7 @@ inline void CompressedTileStorage::getBlock(int* block, int x, int y, int z) { void CompressedTileStorage::setData(byteArray dataIn, unsigned int inOffset) { unsigned short _blockIndices[512]; - std::lock_guard lock(cs_write); + std::lock_guard lock(cs_write); unsigned char* data = dataIn.data + inOffset; // Is the destination fully uncompressed? If so just write our data in - @@ -590,7 +590,7 @@ int CompressedTileStorage::get(int x, int y, int z) { // Set an individual tile value void CompressedTileStorage::set(int x, int y, int z, int val) { - std::lock_guard lock(cs_write); + std::lock_guard lock(cs_write); assert(val != 255); int block, tile; getBlockAndTile(&block, &tile, x, y, z); @@ -778,7 +778,7 @@ void CompressedTileStorage::compress(int upgradeBlock /*=-1*/) { (upgradeBlock > -1); // If an upgrade block is specified, we'll always // need to recompress - otherwise default to false - std::lock_guard lock(cs_write); + std::lock_guard lock(cs_write); unsigned short* blockIndices = (unsigned short*)indicesAndData; unsigned char* data = indicesAndData + 1024; diff --git a/Minecraft.World/Level/Storage/CompressedTileStorage.h b/Minecraft.World/Level/Storage/CompressedTileStorage.h index 5ff5b5b13..42e91e455 100644 --- a/Minecraft.World/Level/Storage/CompressedTileStorage.h +++ b/Minecraft.World/Level/Storage/CompressedTileStorage.h @@ -158,7 +158,7 @@ public: static unsigned char compressBuffer[32768 + 256]; - static std::mutex cs_write; + static std::recursive_mutex cs_write; int getAllocatedSize(int* count0, int* count1, int* count2, int* count4, int* count8); diff --git a/Minecraft.World/Level/Storage/OldChunkStorage.cpp b/Minecraft.World/Level/Storage/OldChunkStorage.cpp index 911d5e670..70ace0f3a 100644 --- a/Minecraft.World/Level/Storage/OldChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/OldChunkStorage.cpp @@ -198,7 +198,7 @@ bool OldChunkStorage::saveEntities(LevelChunk* lc, Level* level, ListTag* entityTags = new ListTag(); { - std::lock_guard lock(lc->m_csEntities); + std::lock_guard lock(lc->m_csEntities); for (int i = 0; i < lc->ENTITY_BLOCKS_LENGTH; i++) { auto itEnd = lc->entityBlocks[i]->end(); for (std::vector >::iterator it = From a513fa7597a00a251c174a5050f60bce492ec689 Mon Sep 17 00:00:00 2001 From: MatthewBeshay <92357869+MatthewBeshay@users.noreply.github.com> Date: Tue, 31 Mar 2026 00:16:16 +1100 Subject: [PATCH 4/7] Rename CriticalSection wrapper functions to match std::mutex usage EnterCallbackIdCriticalSection/LeaveCallbackIdCriticalSection -> lockCallbackScenes/unlockCallbackScenes, EnterSaveNotificationSection/LeaveSaveNotificationSection -> lockSaveNotification/unlockSaveNotification, m_saveNotificationCriticalSection -> m_saveNotificationMutex. --- Minecraft.Client/MinecraftServer.cpp | 8 ++++---- Minecraft.Client/Platform/Common/Consoles_App.cpp | 8 ++++---- Minecraft.Client/Platform/Common/Consoles_App.h | 6 +++--- Minecraft.Client/Platform/Common/UI/UIController.cpp | 4 ++-- Minecraft.Client/Platform/Common/UI/UIController.h | 4 ++-- .../Common/UI/UIScene_InGameSaveManagementMenu.cpp | 2 +- .../Platform/Common/UI/UIScene_LoadOrJoinMenu.cpp | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index 0c4d1b2db..c914a5d80 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -1176,7 +1176,7 @@ void MinecraftServer::run(int64_t seed, void* lpParameter) { switch (eAction) { case eXuiServerAction_AutoSaveGame: case eXuiServerAction_SaveGame: - app.EnterSaveNotificationSection(); + app.lockSaveNotification(); if (players != nullptr) { players->saveAll( Minecraft::GetInstance()->progressRenderer); @@ -1211,7 +1211,7 @@ void MinecraftServer::run(int64_t seed, void* lpParameter) { Minecraft::GetInstance()->progressRenderer, (eAction == eXuiServerAction_AutoSaveGame)); } - app.LeaveSaveNotificationSection(); + app.unlockSaveNotification(); break; case eXuiServerAction_DropItem: // Find the player, and drop the id at their feet @@ -1292,7 +1292,7 @@ void MinecraftServer::run(int64_t seed, void* lpParameter) { break; case eXuiServerAction_ExportSchematic: #if !defined(_CONTENT_PACKAGE) - app.EnterSaveNotificationSection(); + app.lockSaveNotification(); // players->broadcastAll( // shared_ptr( new @@ -1326,7 +1326,7 @@ void MinecraftServer::run(int64_t seed, void* lpParameter) { delete initData; } - app.LeaveSaveNotificationSection(); + app.unlockSaveNotification(); #endif break; case eXuiServerAction_SetCameraLocation: diff --git a/Minecraft.Client/Platform/Common/Consoles_App.cpp b/Minecraft.Client/Platform/Common/Consoles_App.cpp index 5eff1864f..edc049903 100644 --- a/Minecraft.Client/Platform/Common/Consoles_App.cpp +++ b/Minecraft.Client/Platform/Common/Consoles_App.cpp @@ -5641,8 +5641,8 @@ DLC_INFO* CMinecraftApp::GetDLCInfoForFullOfferID(uint64_t ullOfferID_Full) { return nullptr; } -void CMinecraftApp::EnterSaveNotificationSection() { - std::lock_guard lock(m_saveNotificationCriticalSection); +void CMinecraftApp::lockSaveNotification() { + std::lock_guard lock(m_saveNotificationMutex); if (m_saveNotificationDepth++ == 0) { if (g_NetworkManager .IsInSession()) // this can be triggered from the front end if @@ -5660,8 +5660,8 @@ void CMinecraftApp::EnterSaveNotificationSection() { } } -void CMinecraftApp::LeaveSaveNotificationSection() { - std::lock_guard lock(m_saveNotificationCriticalSection); +void CMinecraftApp::unlockSaveNotification() { + std::lock_guard lock(m_saveNotificationMutex); if (--m_saveNotificationDepth == 0) { if (g_NetworkManager .IsInSession()) // this can be triggered from the front end if diff --git a/Minecraft.Client/Platform/Common/Consoles_App.h b/Minecraft.Client/Platform/Common/Consoles_App.h index 36c47839d..9263ac5b2 100644 --- a/Minecraft.Client/Platform/Common/Consoles_App.h +++ b/Minecraft.Client/Platform/Common/Consoles_App.h @@ -880,11 +880,11 @@ public: void SetCorruptSaveDeleted(bool bVal) { m_bCorruptSaveDeleted = bVal; } bool GetCorruptSaveDeleted(void) { return m_bCorruptSaveDeleted; } - void EnterSaveNotificationSection(); - void LeaveSaveNotificationSection(); + void lockSaveNotification(); + void unlockSaveNotification(); private: - std::mutex m_saveNotificationCriticalSection; + std::mutex m_saveNotificationMutex; int m_saveNotificationDepth; // Download Status diff --git a/Minecraft.Client/Platform/Common/UI/UIController.cpp b/Minecraft.Client/Platform/Common/UI/UIController.cpp index bb3f23978..f5a80b595 100644 --- a/Minecraft.Client/Platform/Common/UI/UIController.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIController.cpp @@ -1400,11 +1400,11 @@ UIScene* UIController::GetSceneFromCallbackId(size_t id) { return scene; } -void UIController::EnterCallbackIdCriticalSection() { +void UIController::lockCallbackScenes() { m_registeredCallbackScenesCS.lock(); } -void UIController::LeaveCallbackIdCriticalSection() { +void UIController::unlockCallbackScenes() { m_registeredCallbackScenesCS.unlock(); } diff --git a/Minecraft.Client/Platform/Common/UI/UIController.h b/Minecraft.Client/Platform/Common/UI/UIController.h index 26acadedb..09223ba6d 100644 --- a/Minecraft.Client/Platform/Common/UI/UIController.h +++ b/Minecraft.Client/Platform/Common/UI/UIController.h @@ -312,8 +312,8 @@ public: size_t RegisterForCallbackId(UIScene* scene); void UnregisterCallbackId(size_t id); UIScene* GetSceneFromCallbackId(size_t id); - void EnterCallbackIdCriticalSection(); - void LeaveCallbackIdCriticalSection(); + void lockCallbackScenes(); + void unlockCallbackScenes(); private: void setFullscreenMenuDisplayed(bool displayed); diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_InGameSaveManagementMenu.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_InGameSaveManagementMenu.cpp index 5aceeb6c1..ed88edf2a 100644 --- a/Minecraft.Client/Platform/Common/UI/UIScene_InGameSaveManagementMenu.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIScene_InGameSaveManagementMenu.cpp @@ -95,7 +95,7 @@ UIScene_InGameSaveManagementMenu::~UIScene_InGameSaveManagementMenu() { } delete[] m_saveDetails; } - app.LeaveSaveNotificationSection(); + app.unlockSaveNotification(); StorageManager.SetSaveDisabled(false); StorageManager.ContinueIncompleteOperation(); } diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_LoadOrJoinMenu.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_LoadOrJoinMenu.cpp index e8ddcbce4..5228a5787 100644 --- a/Minecraft.Client/Platform/Common/UI/UIScene_LoadOrJoinMenu.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIScene_LoadOrJoinMenu.cpp @@ -1442,7 +1442,7 @@ int UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned( } int UIScene_LoadOrJoinMenu::DeleteSaveDataReturned(void* lpParam, bool bRes) { - ui.EnterCallbackIdCriticalSection(); + ui.lockCallbackScenes(); UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)ui.GetSceneFromCallbackId((size_t)lpParam); @@ -1455,7 +1455,7 @@ int UIScene_LoadOrJoinMenu::DeleteSaveDataReturned(void* lpParam, bool bRes) { pClass->updateTooltips(); } - ui.LeaveCallbackIdCriticalSection(); + ui.unlockCallbackScenes(); return 0; } From 156a23d744e938c801c4975a7af41b0e0849224a Mon Sep 17 00:00:00 2001 From: MatthewBeshay <92357869+MatthewBeshay@users.noreply.github.com> Date: Tue, 31 Mar 2026 00:22:33 +1100 Subject: [PATCH 5/7] Remove dead _ENTITIES_RW_SECTION code and update stale critical section comments The RW section code path was never compiled. Updated remaining comments to reflect mutex/lock terminology. --- Minecraft.Client/Rendering/LevelRenderer.cpp | 10 +-- Minecraft.World/Level/LevelChunk.cpp | 85 +------------------ Minecraft.World/Level/LevelChunk.h | 6 -- .../Level/Storage/McRegionChunkStorage.cpp | 7 +- Minecraft.World/Network/Connection.cpp | 3 +- Minecraft.World/Network/Connection.h | 8 +- 6 files changed, 16 insertions(+), 103 deletions(-) diff --git a/Minecraft.Client/Rendering/LevelRenderer.cpp b/Minecraft.Client/Rendering/LevelRenderer.cpp index 540c5cb29..bc52e1de6 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.cpp +++ b/Minecraft.Client/Rendering/LevelRenderer.cpp @@ -1930,11 +1930,11 @@ bool LevelRenderer::updateDirtyChunks() { chunk->clearDirty(); // Take a copy of the details that are required for chunk // rebuilding, and rebuild That instead of the original chunk - // data. This is done within the m_csDirtyChunks critical - // section, which means that any chunks can't be repositioned + // data. This is done within the m_csDirtyChunks lock, + // which means that any chunks can't be repositioned // whilst we are doing this copy. The copy will then be // guaranteed to be consistent whilst rebuilding takes place - // outside of that critical section. + // outside of that lock. permaChunk[index].makeCopyForRebuild(chunk); ++index; } @@ -2024,10 +2024,10 @@ bool LevelRenderer::updateDirtyChunks() { chunk->clearDirty(); // Take a copy of the details that are required for chunk // rebuilding, and rebuild That instead of the original chunk data. - // This is done within the m_csDirtyChunks critical section, which + // This is done within the m_csDirtyChunks lock, which // means that any chunks can't be repositioned whilst we are doing // this copy. The copy will then be guaranteed to be consistent - // whilst rebuilding takes place outside of that critical section. + // whilst rebuilding takes place outside of that lock. permaChunk.makeCopyForRebuild(chunk); dirtyChunksLock.unlock(); } diff --git a/Minecraft.World/Level/LevelChunk.cpp b/Minecraft.World/Level/LevelChunk.cpp index 751a466fb..97fe9d7bb 100644 --- a/Minecraft.World/Level/LevelChunk.cpp +++ b/Minecraft.World/Level/LevelChunk.cpp @@ -24,20 +24,11 @@ #if defined(SHARING_ENABLED) std::recursive_mutex LevelChunk::m_csSharing; #endif -#if defined(_ENTITIES_RW_SECTION) -// AP - use a RW critical section so we can have multiple threads reading the -// same data to avoid a clash -CRITICAL_RW_SECTION LevelChunk::m_csEntities; -#else std::recursive_mutex LevelChunk::m_csEntities; -#endif std::recursive_mutex LevelChunk::m_csTileEntities; bool LevelChunk::touchedSky = false; void LevelChunk::staticCtor() { -#if defined(_ENTITIES_RW_SECTION) - InitializeCriticalRWSection(&m_csEntities); -#endif } void LevelChunk::init(Level* level, int x, int z) { @@ -45,18 +36,10 @@ void LevelChunk::init(Level* level, int x, int z) { for (int i = 0; i < 16 * 16; i++) { biomes[i] = 0xff; } -#if defined(_ENTITIES_RW_SECTION) - EnterCriticalRWSection(&m_csEntities, true); -#else { std::lock_guard lock(m_csEntities); -#endif entityBlocks = new std::vector >*[ENTITY_BLOCKS_LENGTH]; -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&m_csEntities, true); -#else } -#endif terrainPopulated = 0; m_unsaved = false; @@ -76,19 +59,11 @@ void LevelChunk::init(Level* level, int x, int z) { this->z = z; MemSect(1); heightmap = byteArray(16 * 16); -#if defined(_ENTITIES_RW_SECTION) - EnterCriticalRWSection(&m_csEntities, true); -#else { std::lock_guard lock(m_csEntities); -#endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { entityBlocks[i] = new std::vector >(); } -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&m_csEntities, true); -#else } -#endif MemSect(0); @@ -1175,17 +1150,9 @@ void LevelChunk::addEntity(std::shared_ptr e) { e->yChunk = yc; e->zChunk = z; -#if defined(_ENTITIES_RW_SECTION) - EnterCriticalRWSection(&m_csEntities, true); -#else { std::lock_guard lock(m_csEntities); -#endif entityBlocks[yc]->push_back(e); -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&m_csEntities, true); -#else } -#endif } void LevelChunk::removeEntity(std::shared_ptr e) { @@ -1196,11 +1163,7 @@ void LevelChunk::removeEntity(std::shared_ptr e, int yc) { if (yc < 0) yc = 0; if (yc >= ENTITY_BLOCKS_LENGTH) yc = ENTITY_BLOCKS_LENGTH - 1; -#if defined(_ENTITIES_RW_SECTION) - EnterCriticalRWSection(&m_csEntities, true); -#else { std::lock_guard lock(m_csEntities); -#endif // 4J - was entityBlocks[yc]->remove(e); auto it = find(entityBlocks[yc]->begin(), entityBlocks[yc]->end(), e); @@ -1213,11 +1176,7 @@ void LevelChunk::removeEntity(std::shared_ptr e, int yc) { MemSect(0); } -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&m_csEntities, true); -#else } -#endif } bool LevelChunk::isSkyLit(int x, int y, int z) { @@ -1409,19 +1368,11 @@ void LevelChunk::load() { } level->addAllPendingTileEntities(values); -#if defined(_ENTITIES_RW_SECTION) - EnterCriticalRWSection(&m_csEntities, true); -#else { std::lock_guard lock(m_csEntities); -#endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { level->addEntities(entityBlocks[i]); } -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&m_csEntities, true); -#else } -#endif } else { #if defined(_LARGE_WORLDS) m_bUnloaded = false; @@ -1447,19 +1398,11 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter } } -#if defined(_ENTITIES_RW_SECTION) - EnterCriticalRWSection(&m_csEntities, true); -#else { std::lock_guard lock(m_csEntities); -#endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { level->removeEntities(entityBlocks[i]); } -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&m_csEntities, true); -#else } -#endif // app.DebugPrintf("Unloaded chunk %d, %d\n", x, z); #if defined(_LARGE_WORLDS) @@ -1520,28 +1463,16 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter } bool LevelChunk::containsPlayer() { -#if defined(_ENTITIES_RW_SECTION) - EnterCriticalRWSection(&m_csEntities, true); -#else { std::lock_guard lock(m_csEntities); -#endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { std::vector >* vecEntity = entityBlocks[i]; for (int j = 0; j < vecEntity->size(); j++) { if (vecEntity->at(j)->GetType() == eTYPE_SERVERPLAYER) { -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&m_csEntities, true); -#else -#endif return true; } } } -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&m_csEntities, true); -#else } -#endif return false; } @@ -1559,7 +1490,7 @@ void LevelChunk::getEntities(std::shared_ptr except, AABB* bb, if (yc0 < 0) yc0 = 0; if (yc1 >= ENTITY_BLOCKS_LENGTH) yc1 = ENTITY_BLOCKS_LENGTH - 1; - // AP - RW critical sections are expensive so enter once in + // AP - locking is expensive so enter once in // Level::getEntities { std::lock_guard lock(m_csEntities); for (int yc = yc0; yc <= yc1; yc++) { @@ -1605,7 +1536,7 @@ void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, yc1 = 0; } - // AP - RW critical sections are expensive so enter once in + // AP - locking is expensive so enter once in // Level::getEntitiesOfClass { std::lock_guard lock(m_csEntities); for (int yc = yc0; yc <= yc1; yc++) { @@ -1652,19 +1583,11 @@ void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, int LevelChunk::countEntities() { int entityCount = 0; -#if defined(_ENTITIES_RW_SECTION) - EnterCriticalRWSection(&m_csEntities, false); -#else { std::lock_guard lock(m_csEntities); -#endif for (int yc = 0; yc < ENTITY_BLOCKS_LENGTH; yc++) { entityCount += (int)entityBlocks[yc]->size(); } -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&m_csEntities, false); -#else } -#endif return entityCount; } @@ -2206,7 +2129,7 @@ void LevelChunk::compressBlocks() { // server again. if (level->isClientSide && g_NetworkManager.IsHost()) { // Note - only the extraction of the pointers needs to be done in the - // critical section, since even if the data is unshared whilst we are + // lock, since even if the data is unshared whilst we are // processing this data is still valid (for the server) { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { @@ -2305,7 +2228,7 @@ void LevelChunk::compressData() { // server again. if (level->isClientSide && g_NetworkManager.IsHost()) { // Note - only the extraction of the pointers needs to be done in the - // critical section, since even if the data is unshared whilst we are + // lock, since even if the data is unshared whilst we are // processing this data is still valid (for the server) { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { diff --git a/Minecraft.World/Level/LevelChunk.h b/Minecraft.World/Level/LevelChunk.h index 0dd5df669..7796cb7a3 100644 --- a/Minecraft.World/Level/LevelChunk.h +++ b/Minecraft.World/Level/LevelChunk.h @@ -273,13 +273,7 @@ public: static std::recursive_mutex m_csSharing; // 4J added #endif // 4J added -#if defined(_ENTITIES_RW_SECTION) - static CRITICAL_RW_SECTION - m_csEntities; // AP - we're using a RW critical so we can do multiple - // reads without contention -#else static std::recursive_mutex m_csEntities; -#endif static std::recursive_mutex m_csTileEntities; // 4J added static void staticCtor(); void checkPostProcess(ChunkSource* source, ChunkSource* parent, int x, diff --git a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp index c85237704..d880d410a 100644 --- a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp @@ -182,11 +182,10 @@ void McRegionChunkStorage::save(Level* level, LevelChunk* levelChunk) { // 4J - removed try/catch // try { - // Note - have added use of a critical section round sections of code that + // Note - have added use of a mutex round sections of code that // do a lot of memory alloc/free operations. This is because when we are - // running saves on multiple threads these sections have a lot of contention - // and thrash the memory system's critical sections Better to let each - // thread have its turn at a higher level of granularity. + // running saves on multiple threads these sections have a lot of contention. + // Better to let each thread have its turn at a higher level of granularity. MemSect(30); PIXBeginNamedEvent(0, "Getting output stream\n"); DataOutputStream* output = RegionFileCache::getChunkDataOutputStream( diff --git a/Minecraft.World/Network/Connection.cpp b/Minecraft.World/Network/Connection.cpp index e90443f25..83651a18e 100644 --- a/Minecraft.World/Network/Connection.cpp +++ b/Minecraft.World/Network/Connection.cpp @@ -38,7 +38,6 @@ void Connection::_init() { tickCount = 0; } -// 4J Jev, need to delete the critical section. Connection::~Connection() { // 4J Stu - Just to be sure, make sure the read and write threads terminate // themselves before the connection object is destroyed @@ -488,7 +487,7 @@ void Connection::tick() { } // 4J - split the following condition (used to be disconnect && - // iscoming.empty()) so we can wrap the access in a critical section + // iscoming.empty()) so we can wrap the access in a mutex if (disconnected) { bool empty; { diff --git a/Minecraft.World/Network/Connection.h b/Minecraft.World/Network/Connection.h index c9b776b9c..4cf68a8b1 100644 --- a/Minecraft.World/Network/Connection.h +++ b/Minecraft.World/Network/Connection.h @@ -56,14 +56,13 @@ private: std::queue > incoming; // 4J - was using synchronizedList... - std::mutex incoming_cs; // ... now has this critical section + std::mutex incoming_cs; // ... now has this mutex std::queue > outgoing; // 4J - was using synchronizedList - but don't think it is - // required as usage is wrapped in writeLock critical section + // required as usage is wrapped in writeLock std::queue > outgoing_slow; // 4J - was using synchronizedList - but don't think it - // is required as usage is wrapped in writeLock critical - // section + // is required as usage is wrapped in writeLock PacketListener* packetListener; bool quitting; @@ -99,7 +98,6 @@ private: std::mutex writeLock; public: - // 4J Jev, need to delete the critical section. ~Connection(); Connection(Socket* socket, const std::wstring& id, PacketListener* packetListener); // throws IOException From e911e07a588618a94ce446d2271c3b63c95bea23 Mon Sep 17 00:00:00 2001 From: MatthewBeshay <92357869+MatthewBeshay@users.noreply.github.com> Date: Tue, 31 Mar 2026 01:01:25 +1100 Subject: [PATCH 6/7] Refactor C4JThread: modernise API naming and replace Windows constants Rename all PascalCase methods to camelCase, replace Windows macro constants with C++ constexpr members, convert ThreadPriority to enum class, remove unused Sleep(), fix memory ordering on inline accessors, extract platform code into helpers. --- Minecraft.Client/Level/ServerLevel.cpp | 10 +- Minecraft.Client/Minecraft.cpp | 2 +- Minecraft.Client/MinecraftServer.cpp | 14 +- Minecraft.Client/Network/ServerChunkCache.cpp | 10 +- .../Platform/Common/Audio/SoundEngine.cpp | 4 +- .../Leaderboards/SonyLeaderboardManager.cpp | 6 +- .../Common/Network/GameNetworkManager.cpp | 20 +- .../Network/PlatformNetworkManagerStub.cpp | 2 +- .../Platform/Common/UI/UIController.cpp | 6 +- .../Common/UI/UIScene_FullscreenProgress.cpp | 12 +- Minecraft.Client/Platform/Linux/Linux_App.cpp | 2 +- .../Platform/Windows64/Windows64_App.cpp | 2 +- Minecraft.Client/Rendering/GameRenderer.cpp | 26 +- Minecraft.Client/Rendering/LevelRenderer.cpp | 20 +- .../Level/Storage/McRegionChunkStorage.cpp | 8 +- Minecraft.World/Network/Connection.cpp | 28 +- Minecraft.World/Network/Socket.cpp | 2 +- Minecraft.World/Util/C4JThread.cpp | 836 +++++++----------- Minecraft.World/Util/C4JThread.h | 89 +- 19 files changed, 458 insertions(+), 641 deletions(-) diff --git a/Minecraft.Client/Level/ServerLevel.cpp b/Minecraft.Client/Level/ServerLevel.cpp index 2686f7a5a..afd3315ad 100644 --- a/Minecraft.Client/Level/ServerLevel.cpp +++ b/Minecraft.Client/Level/ServerLevel.cpp @@ -62,8 +62,8 @@ void ServerLevel::staticCtor() { m_updateTrigger = new C4JThread::EventArray(3); m_updateThread = new C4JThread(runUpdate, nullptr, "Tile update"); - m_updateThread->SetProcessor(CPU_CORE_TILE_UPDATE); - m_updateThread->Run(); + m_updateThread->setProcessor(CPU_CORE_TILE_UPDATE); + m_updateThread->run(); RANDOM_BONUS_ITEMS = WeighedTreasureArray(20); @@ -201,7 +201,7 @@ ServerLevel::~ServerLevel() { { std::lock_guard lock(m_updateCS[0]); } { std::lock_guard lock(m_updateCS[1]); } { std::lock_guard lock(m_updateCS[2]); } - m_updateTrigger->ClearAll(); + m_updateTrigger->clearAll(); } void ServerLevel::tick() { @@ -553,7 +553,7 @@ void ServerLevel::tickTiles() { m_level[iLev] = this; m_randValue[iLev] = randValue; // We've set up everything that the udpate thread needs, so kick it off - m_updateTrigger->Set(iLev); + m_updateTrigger->set(iLev); } bool ServerLevel::isTileToBeTickedAt(int x, int y, int z, int tileId) { @@ -1411,7 +1411,7 @@ int ServerLevel::runUpdate(void* lpParam) { ShutdownManager::HasStarted(ShutdownManager::eRunUpdateThread, m_updateTrigger); while (ShutdownManager::ShouldRun(ShutdownManager::eRunUpdateThread)) { - m_updateTrigger->WaitForAll(INFINITE); + m_updateTrigger->waitForAll(C4JThread::kInfiniteTimeout); if (!ShutdownManager::ShouldRun(ShutdownManager::eRunUpdateThread)) break; diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index faf44a939..de9428a74 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -212,7 +212,7 @@ Minecraft::Minecraft(Component* mouseComponent, Canvas* parent, new C4JThread::EventQueue(levelTickUpdateFunc, levelTickThreadInitFunc, "LevelTick_EventQueuePoll"); levelTickEventQueue->setProcessor(3); - levelTickEventQueue->setPriority(THREAD_PRIORITY_NORMAL); + levelTickEventQueue->setPriority(C4JThread::ThreadPriority::Normal); #endif } diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index c914a5d80..c5fb9936a 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -303,8 +303,8 @@ void MinecraftServer::postProcessTerminate(ProgressRenderer* mcprogress) { } do { - status = m_postUpdateThread->WaitForCompletion(50); - if (status == WAIT_TIMEOUT) { + status = m_postUpdateThread->waitForCompletion(50); + if (status == C4JThread::WaitResult::Timeout) { { std::lock_guard lock(server->m_postProcessCS); postProcessItemRemaining = server->m_postProcessRequests.size(); @@ -319,7 +319,7 @@ void MinecraftServer::postProcessTerminate(ProgressRenderer* mcprogress) { SparseLightStorage::tick(); SparseDataStorage::tick(); } - } while (status == WAIT_TIMEOUT); + } while (status == C4JThread::WaitResult::Timeout); delete m_postUpdateThread; m_postUpdateThread = nullptr; } @@ -493,9 +493,9 @@ bool MinecraftServer::loadLevel(LevelStorageSource* storageSource, new C4JThread(runPostUpdate, this, "Post processing", 256 * 1024); m_postUpdateTerminate = false; - m_postUpdateThread->SetProcessor(CPU_CORE_POST_PROCESSING); - m_postUpdateThread->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); - m_postUpdateThread->Run(); + m_postUpdateThread->setProcessor(CPU_CORE_POST_PROCESSING); + m_postUpdateThread->setPriority(C4JThread::ThreadPriority::AboveNormal); + m_postUpdateThread->run(); int64_t startTime = System::currentTimeMillis(); @@ -1244,7 +1244,7 @@ void MinecraftServer::run(int64_t seed, void* lpParameter) { case eXuiServerAction_PauseServer: m_isServerPaused = ((size_t)param == true); if (m_isServerPaused) { - m_serverPausedEvent->Set(); + m_serverPausedEvent->set(); } break; case eXuiServerAction_ToggleRain: { diff --git a/Minecraft.Client/Network/ServerChunkCache.cpp b/Minecraft.Client/Network/ServerChunkCache.cpp index 566fea724..40628a484 100644 --- a/Minecraft.Client/Network/ServerChunkCache.cpp +++ b/Minecraft.Client/Network/ServerChunkCache.cpp @@ -859,8 +859,8 @@ int ServerChunkCache::runSaveThreadProc(void* lpParam) { } // Wait for the producer thread to tell us to start - params->wakeEvent->WaitForSignal( - INFINITE); // WaitForSingleObject(params->wakeEvent,INFINITE); + params->wakeEvent->waitForSignal( + C4JThread::kInfiniteTimeout); // WaitForSingleObject(params->wakeEvent,INFINITE); // app.DebugPrintf("Save thread has started\n"); @@ -880,14 +880,14 @@ int ServerChunkCache::runSaveThreadProc(void* lpParam) { // Inform the producer thread that we are done with this chunk params->notificationEvent - ->Set(); // SetEvent(params->notificationEvent); + ->set(); // SetEvent(params->notificationEvent); // app.DebugPrintf("Save thread has alerted producer that it is // complete\n"); // Wait for the producer thread to tell us to go again - params->wakeEvent->WaitForSignal( - INFINITE); // WaitForSingleObject(params->wakeEvent,INFINITE); + params->wakeEvent->waitForSignal( + C4JThread::kInfiniteTimeout); // WaitForSingleObject(params->wakeEvent,INFINITE); PIXEndNamedEvent(); } diff --git a/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp b/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp index 12376e5c1..29e246508 100644 --- a/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp +++ b/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp @@ -462,7 +462,7 @@ void SoundEngine::playMusicTick() { SetIsPlayingStreamingCDMusic(isCD); m_openStreamThread = new C4JThread( OpenStreamThreadProc, this, "OpenStreamThreadProc"); - m_openStreamThread->Run(); + m_openStreamThread->run(); m_StreamState = eMusicStreamState_Opening; } else { app.DebugPrintf( @@ -1493,7 +1493,7 @@ void SoundEngine::playMusicUpdate() { // ~300ms. m_openStreamThread = new C4JThread(OpenStreamThreadProc, this, "OpenStreamThreadProc"); - m_openStreamThread->Run(); + m_openStreamThread->run(); m_StreamState = eMusicStreamState_Opening; } break; diff --git a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp index 5d9411d51..600a3e3f3 100644 --- a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp +++ b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp @@ -640,9 +640,9 @@ bool SonyLeaderboardManager::OpenSession() { if (m_threadScoreboard == nullptr) { m_threadScoreboard = new C4JThread(&scoreboardThreadEntry, this, "4JScoreboard"); - m_threadScoreboard->SetProcessor(CPU_CORE_LEADERBOARDS); - m_threadScoreboard->SetPriority(THREAD_PRIORITY_BELOW_NORMAL); - m_threadScoreboard->Run(); + m_threadScoreboard->setProcessor(CPU_CORE_LEADERBOARDS); + m_threadScoreboard->setPriority(C4JThread::ThreadPriority::BelowNormal); + m_threadScoreboard->run(); } app.DebugPrintf( diff --git a/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp b/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp index feb99fb17..ab700d242 100644 --- a/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp +++ b/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp @@ -213,8 +213,8 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft* minecraft, new C4JThread(&CGameNetworkManager::ServerThreadProc, lpParameter, "Server", 256 * 1024); - thread->SetProcessor(CPU_CORE_SERVER); - thread->Run(); + thread->setProcessor(CPU_CORE_SERVER); + thread->run(); app.DebugPrintf("[NET] Waiting for server ready...\n"); ServerReadyWait(); @@ -916,7 +916,7 @@ int CGameNetworkManager::ChangeSessionTypeThreadProc(void* lpParam) { eXuiServerAction_PauseServer, (void*)true); // wait for the server to be in a non-ticking state - pServer->m_serverPausedEvent->WaitForSignal(INFINITE); + pServer->m_serverPausedEvent->waitForSignal(C4JThread::kInfiniteTimeout); pMinecraft->progressRenderer->progressStartNoAbort( g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT)); @@ -1495,7 +1495,7 @@ void CGameNetworkManager::ServerReadyCreate(bool create) { void CGameNetworkManager::ServerReady() { if (m_hServerReadyEvent != nullptr) { - m_hServerReadyEvent->Set(); + m_hServerReadyEvent->set(); } else { app.DebugPrintf( "[NET] Warning: ServerReady() called but m_hServerReadyEvent is " @@ -1505,7 +1505,7 @@ void CGameNetworkManager::ServerReady() { void CGameNetworkManager::ServerReadyWait() { if (m_hServerReadyEvent != nullptr) { - m_hServerReadyEvent->WaitForSignal(INFINITE); + m_hServerReadyEvent->waitForSignal(C4JThread::kInfiniteTimeout); } else { app.DebugPrintf( "[NET] Warning: ServerReadyWait() called but m_hServerReadyEvent " @@ -1528,7 +1528,7 @@ void CGameNetworkManager::ServerStoppedCreate(bool create) { void CGameNetworkManager::ServerStopped() { if (m_hServerStoppedEvent != nullptr) { - m_hServerStoppedEvent->Set(); + m_hServerStoppedEvent->set(); } else { app.DebugPrintf( "[NET] Warning: ServerStopped() called but m_hServerStoppedEvent " @@ -1543,10 +1543,10 @@ void CGameNetworkManager::ServerStoppedWait() { // it might be locked waiting for this to complete itself. Do some ticking // here then if this is the case. if (C4JThread::isMainThread()) { - int result = WAIT_TIMEOUT; + int result = C4JThread::WaitResult::Timeout; do { RenderManager.StartFrame(); - result = m_hServerStoppedEvent->WaitForSignal(20); + result = m_hServerStoppedEvent->waitForSignal(20); // Tick some simple things ProfileManager.Tick(); StorageManager.Tick(); @@ -1555,10 +1555,10 @@ void CGameNetworkManager::ServerStoppedWait() { ui.tick(); ui.render(); RenderManager.Present(); - } while (result == WAIT_TIMEOUT); + } while (result == C4JThread::WaitResult::Timeout); } else { if (m_hServerStoppedEvent != nullptr) { - m_hServerStoppedEvent->WaitForSignal(INFINITE); + m_hServerStoppedEvent->waitForSignal(C4JThread::kInfiniteTimeout); } else { app.DebugPrintf( "[NET] Warning: ServerStoppedWait() called but " diff --git a/Minecraft.Client/Platform/Common/Network/PlatformNetworkManagerStub.cpp b/Minecraft.Client/Platform/Common/Network/PlatformNetworkManagerStub.cpp index 446d7a81e..9bc82654a 100644 --- a/Minecraft.Client/Platform/Common/Network/PlatformNetworkManagerStub.cpp +++ b/Minecraft.Client/Platform/Common/Network/PlatformNetworkManagerStub.cpp @@ -330,7 +330,7 @@ int CPlatformNetworkManagerStub::RemovePlayerOnSocketClosedThreadProc( if (socket != nullptr) { // printf("Waiting for socket closed event\n"); - socket->m_socketClosedEvent->WaitForSignal(INFINITE); + socket->m_socketClosedEvent->waitForSignal(C4JThread::kInfiniteTimeout); // printf("Socket closed event has fired\n"); // 4J Stu - Clear our reference to this socket diff --git a/Minecraft.Client/Platform/Common/UI/UIController.cpp b/Minecraft.Client/Platform/Common/UI/UIController.cpp index f5a80b595..dcff5c66f 100644 --- a/Minecraft.Client/Platform/Common/UI/UIController.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIController.cpp @@ -588,13 +588,13 @@ void UIController::ReloadSkin() { m_reloadSkinThread = new C4JThread(reloadSkinThreadProc, (void*)this, "Reload skin thread"); - m_reloadSkinThread->SetProcessor(CPU_CORE_UI_SCENE); + m_reloadSkinThread->setProcessor(CPU_CORE_UI_SCENE); // Navigate to the timer scene so that we can display something while the // loading is happening ui.NavigateToScene(0, eUIScene_Timer, (void*)1, eUILayer_Tooltips, eUIGroup_Fullscreen); - // m_reloadSkinThread->Run(); + // m_reloadSkinThread->run(); //// Load new skin // loadSkins(); @@ -611,7 +611,7 @@ void UIController::ReloadSkin() { } void UIController::StartReloadSkinThread() { - if (m_reloadSkinThread) m_reloadSkinThread->Run(); + if (m_reloadSkinThread) m_reloadSkinThread->run(); } int UIController::reloadSkinThreadProc(void* lpParam) { diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_FullscreenProgress.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_FullscreenProgress.cpp index edb108e6c..b03c1b7d5 100644 --- a/Minecraft.Client/Platform/Common/UI/UIScene_FullscreenProgress.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIScene_FullscreenProgress.cpp @@ -63,11 +63,11 @@ UIScene_FullscreenProgress::UIScene_FullscreenProgress(int iPad, void* initData, m_labelTip.setVisible(m_CompletionData->bShowTips); thread = new C4JThread(params->func, params->lpParam, "FullscreenProgress"); - thread->SetProcessor(CPU_CORE_UI_SCENE); // TODO 4J Stu - Make sure this is + thread->setProcessor(CPU_CORE_UI_SCENE); // TODO 4J Stu - Make sure this is // a good thread/core to use m_threadCompleted = false; - thread->Run(); + thread->run(); threadStarted = true; } @@ -92,12 +92,12 @@ void UIScene_FullscreenProgress::updateTooltips() { } void UIScene_FullscreenProgress::handleDestroy() { - int code = thread->GetExitCode(); + int code = thread->getExitCode(); const unsigned int exitcode = static_cast(code); // If we're active, have a cancel func, and haven't already cancelled, call // cancel func - if (exitcode == STILL_ACTIVE && m_cancelFunc != nullptr && + if (exitcode == C4JThread::kStillActive && m_cancelFunc != nullptr && !m_bWasCancelled) { m_bWasCancelled = true; m_cancelFunc(m_cancelFuncParam); @@ -140,12 +140,12 @@ void UIScene_FullscreenProgress::tick() { m_progressBar.setLabel(wstrText.c_str()); } - int code = thread->GetExitCode(); + int code = thread->getExitCode(); uint32_t exitcode = *((uint32_t*)&code); // app.DebugPrintf("CScene_FullscreenProgress Timer %d\n",pTimer->nId); - if (exitcode != STILL_ACTIVE) { + if (exitcode != C4JThread::kStillActive) { // If we failed (currently used by network connection thread), navigate // back if (exitcode != S_OK) { diff --git a/Minecraft.Client/Platform/Linux/Linux_App.cpp b/Minecraft.Client/Platform/Linux/Linux_App.cpp index 6e519a20a..e7d5d629a 100644 --- a/Minecraft.Client/Platform/Linux/Linux_App.cpp +++ b/Minecraft.Client/Platform/Linux/Linux_App.cpp @@ -115,7 +115,7 @@ void CConsoleMinecraftApp::TemporaryCreateGameStart() { C4JThread* thread = new C4JThread(loadingParams->func, loadingParams->lpParam, "RunNetworkGame"); - thread->Run(); + thread->run(); } int CConsoleMinecraftApp::GetLocalTMSFileIndex(wchar_t* wchTMSFile, diff --git a/Minecraft.Client/Platform/Windows64/Windows64_App.cpp b/Minecraft.Client/Platform/Windows64/Windows64_App.cpp index 8bccd39a6..c9371b695 100644 --- a/Minecraft.Client/Platform/Windows64/Windows64_App.cpp +++ b/Minecraft.Client/Platform/Windows64/Windows64_App.cpp @@ -108,7 +108,7 @@ void CConsoleMinecraftApp::TemporaryCreateGameStart() { C4JThread* thread = new C4JThread(loadingParams->func, loadingParams->lpParam, "RunNetworkGame"); - thread->Run(); + thread->run(); } int CConsoleMinecraftApp::GetLocalTMSFileIndex(wchar_t* wchTMSFile, diff --git a/Minecraft.Client/Rendering/GameRenderer.cpp b/Minecraft.Client/Rendering/GameRenderer.cpp index e590c9167..b74a05259 100644 --- a/Minecraft.Client/Rendering/GameRenderer.cpp +++ b/Minecraft.Client/Rendering/GameRenderer.cpp @@ -167,12 +167,12 @@ GameRenderer::GameRenderer(Minecraft* mc) { #if defined(MULTITHREAD_ENABLE) m_updateEvents = new C4JThread::EventArray( - eUpdateEventCount, C4JThread::EventArray::e_modeAutoClear); - m_updateEvents->Set(eUpdateEventIsFinished); + eUpdateEventCount, C4JThread::EventArray::Mode::AutoClear); + m_updateEvents->set(eUpdateEventIsFinished); m_updateThread = new C4JThread(runUpdate, nullptr, "Chunk update"); - m_updateThread->SetProcessor(CPU_CORE_CHUNK_UPDATE); - m_updateThread->Run(); + m_updateThread->setProcessor(CPU_CORE_CHUNK_UPDATE); + m_updateThread->run(); #endif } @@ -1080,17 +1080,17 @@ int GameRenderer::runUpdate(void* lpParam) { m_updateEvents); while ( ShutdownManager::ShouldRun(ShutdownManager::eRenderChunkUpdateThread)) { - // m_updateEvents->Clear(eUpdateEventIsFinished); - // m_updateEvents->WaitForSingle(eUpdateCanRun,INFINITE); + // m_updateEvents->clear(eUpdateEventIsFinished); + // m_updateEvents->waitForSingle(eUpdateCanRun,C4JThread::kInfiniteTimeout); // 4J Stu - We Need to have this happen atomically to avoid deadlocks - m_updateEvents->WaitForAll(INFINITE); + m_updateEvents->waitForAll(C4JThread::kInfiniteTimeout); if (!ShutdownManager::ShouldRun( ShutdownManager::eRenderChunkUpdateThread)) { break; } - m_updateEvents->Set(eUpdateCanRun); + m_updateEvents->set(eUpdateCanRun); // PIXBeginNamedEvent(0,"Updating dirty chunks //%d",(count++)&7); @@ -1143,7 +1143,7 @@ int GameRenderer::runUpdate(void* lpParam) { // PIXEndNamedEvent(); - m_updateEvents->Set(eUpdateEventIsFinished); + m_updateEvents->set(eUpdateEventIsFinished); } ShutdownManager::HasFinished(ShutdownManager::eRenderChunkUpdateThread); @@ -1160,8 +1160,8 @@ void GameRenderer::EnableUpdateThread() { app.DebugPrintf( "------------------EnableUpdateThread--------------------\n"); updateRunning = true; - m_updateEvents->Set(eUpdateCanRun); - m_updateEvents->Set(eUpdateEventIsFinished); + m_updateEvents->set(eUpdateCanRun); + m_updateEvents->set(eUpdateEventIsFinished); #endif } @@ -1174,8 +1174,8 @@ void GameRenderer::DisableUpdateThread() { app.DebugPrintf( "------------------DisableUpdateThread--------------------\n"); updateRunning = false; - m_updateEvents->Clear(eUpdateCanRun); - m_updateEvents->WaitForSingle(eUpdateEventIsFinished, INFINITE); + m_updateEvents->clear(eUpdateCanRun); + m_updateEvents->waitForSingle(eUpdateEventIsFinished, C4JThread::kInfiniteTimeout); #endif } diff --git a/Minecraft.Client/Rendering/LevelRenderer.cpp b/Minecraft.Client/Rendering/LevelRenderer.cpp index bc52e1de6..434f1134e 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.cpp +++ b/Minecraft.Client/Rendering/LevelRenderer.cpp @@ -1945,7 +1945,7 @@ bool LevelRenderer::updateDirtyChunks() { for (int i = MAX_CHUNK_REBUILD_THREADS - 1; i >= 0; --i) { // Set the events that won't run if ((i + 1) > index) - s_rebuildCompleteEvents->Set(i); + s_rebuildCompleteEvents->set(i); else break; } @@ -1974,7 +1974,7 @@ bool LevelRenderer::updateDirtyChunks() { if (index != 0) { FRAME_PROFILE_SCOPE(ChunkRebuildSchedule); - s_rebuildCompleteEvents->Set( + s_rebuildCompleteEvents->set( index - 1); // MGH - this rebuild happening on the main // thread instead, mark the thread it // should have been running on as complete @@ -1990,14 +1990,14 @@ bool LevelRenderer::updateDirtyChunks() { else { // Activate thread to rebuild this chunk FRAME_PROFILE_SCOPE(ChunkRebuildSchedule); - s_activationEventA[index - 1]->Set(); + s_activationEventA[index - 1]->set(); } } // Wait for the other threads to be done as well { FRAME_PROFILE_SCOPE(ChunkRebuildSchedule); - s_rebuildCompleteEvents->WaitForAll(INFINITE); + s_rebuildCompleteEvents->waitForAll(C4JThread::kInfiniteTimeout); } } #else @@ -4005,14 +4005,14 @@ void LevelRenderer::staticCtor() { // Threads 1,3 and 5 are generally idle so use them if ((i % 3) == 0) - rebuildThreads[i]->SetProcessor(CPU_CORE_CHUNK_REBUILD_A); + rebuildThreads[i]->setProcessor(CPU_CORE_CHUNK_REBUILD_A); else if ((i % 3) == 1) { - rebuildThreads[i]->SetProcessor(CPU_CORE_CHUNK_REBUILD_B); + rebuildThreads[i]->setProcessor(CPU_CORE_CHUNK_REBUILD_B); } else if ((i % 3) == 2) - rebuildThreads[i]->SetProcessor(CPU_CORE_CHUNK_REBUILD_C); + rebuildThreads[i]->setProcessor(CPU_CORE_CHUNK_REBUILD_C); // ResumeThread( saveThreads[j] ); - rebuildThreads[i]->Run(); + rebuildThreads[i]->run(); } } @@ -4025,7 +4025,7 @@ int LevelRenderer::rebuildChunkThreadProc(void* lpParam) { int index = (int)(uintptr_t)lpParam; while (true) { - s_activationEventA[index]->WaitForSignal(INFINITE); + s_activationEventA[index]->waitForSignal(C4JThread::kInfiniteTimeout); // app.DebugPrintf("Rebuilding permaChunk %d\n", index + 1); { @@ -4034,7 +4034,7 @@ int LevelRenderer::rebuildChunkThreadProc(void* lpParam) { } // Inform the producer thread that we are done with this chunk - s_rebuildCompleteEvents->Set(index); + s_rebuildCompleteEvents->set(index); } return 0; diff --git a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp index d880d410a..bba7b774a 100644 --- a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp @@ -336,14 +336,14 @@ void McRegionChunkStorage::staticCtor() { // Threads 1,3 and 5 are generally idle so use them if (i == 0) - s_saveThreads[i]->SetProcessor(CPU_CORE_SAVE_THREAD_A); + s_saveThreads[i]->setProcessor(CPU_CORE_SAVE_THREAD_A); else if (i == 1) { - s_saveThreads[i]->SetProcessor(CPU_CORE_SAVE_THREAD_B); + s_saveThreads[i]->setProcessor(CPU_CORE_SAVE_THREAD_B); } else if (i == 2) - s_saveThreads[i]->SetProcessor(CPU_CORE_SAVE_THREAD_C); + s_saveThreads[i]->setProcessor(CPU_CORE_SAVE_THREAD_C); // ResumeThread( saveThreads[j] ); - s_saveThreads[i]->Run(); + s_saveThreads[i]->run(); } } diff --git a/Minecraft.World/Network/Connection.cpp b/Minecraft.World/Network/Connection.cpp index 83651a18e..6b5849d20 100644 --- a/Minecraft.World/Network/Connection.cpp +++ b/Minecraft.World/Network/Connection.cpp @@ -46,8 +46,8 @@ Connection::~Connection() { dis->close(); // The input stream needs closed before the readThread, // or the readThread may get stuck whilst blocking // waiting on a read - readThread->WaitForCompletion(INFINITE); - writeThread->WaitForCompletion(INFINITE); + readThread->waitForCompletion(C4JThread::kInfiniteTimeout); + writeThread->waitForCompletion(C4JThread::kInfiniteTimeout); delete m_hWakeReadThread; delete m_hWakeWriteThread; @@ -111,11 +111,11 @@ Connection::Connection(Socket* socket, const std::wstring& id, new C4JThread(runRead, (void*)this, readThreadName, READ_STACK_SIZE); writeThread = new C4JThread(runWrite, this, writeThreadName, WRITE_STACK_SIZE); - readThread->SetProcessor(CPU_CORE_CONNECTIONS); - writeThread->SetProcessor(CPU_CORE_CONNECTIONS); + readThread->setProcessor(CPU_CORE_CONNECTIONS); + writeThread->setProcessor(CPU_CORE_CONNECTIONS); - readThread->Run(); - writeThread->Run(); + readThread->run(); + writeThread->run(); /* 4J JEV, java: new Thread(wstring(id).append(L" read thread")) { @@ -304,8 +304,8 @@ void Connection::flush() { // multithreaded functions a bit more // readThread.interrupt(); // writeThread.interrupt(); - m_hWakeReadThread->Set(); - m_hWakeWriteThread->Set(); + m_hWakeReadThread->set(); + m_hWakeWriteThread->set(); } bool Connection::readTick() { @@ -388,8 +388,8 @@ void Connection::close(DisconnectPacket::eDisconnectReason reason) { // Make sure that the read & write threads are dead before we go and kill // the streams that they depend on - readThread->WaitForCompletion(INFINITE); - writeThread->WaitForCompletion(INFINITE); + readThread->waitForCompletion(C4JThread::kInfiniteTimeout); + writeThread->waitForCompletion(C4JThread::kInfiniteTimeout); delete dis; dis = nullptr; @@ -558,7 +558,7 @@ int Connection::runRead(void* lpParam) { // std::this_thread::sleep_for(std::chrono::milliseconds(100L)); // TODO - 4J Stu - 1.8.2 changes these sleeps to 2L, but not sure // whether we should do that as well - con->m_hWakeReadThread->WaitForSignal(100L); + con->m_hWakeReadThread->waitForSignal(100L); } MemSect(0); @@ -598,17 +598,17 @@ int Connection::runWrite(void* lpParam) { // once after the event is fired Otherwise there is a race between the // calling thread setting the running flag and this loop checking the // condition - unsigned int waitResult = WAIT_TIMEOUT; + unsigned int waitResult = C4JThread::WaitResult::Timeout; while ( - (con->running || waitResult == WAIT_OBJECT_0) && + (con->running || waitResult == C4JThread::WaitResult::Signaled) && ShutdownManager::ShouldRun(ShutdownManager::eConnectionWriteThreads)) { while (con->writeTick()); // std::this_thread::sleep_for(std::chrono::milliseconds(100L)); // TODO - 4J Stu - 1.8.2 changes these sleeps to 2L, but not sure // whether we should do that as well - waitResult = con->m_hWakeWriteThread->WaitForSignal(100L); + waitResult = con->m_hWakeWriteThread->waitForSignal(100L); if (con->bufferedDos != nullptr) con->bufferedDos->flush(); // if (con->byteArrayDos != nullptr) con->byteArrayDos->flush(); diff --git a/Minecraft.World/Network/Socket.cpp b/Minecraft.World/Network/Socket.cpp index 1ce1df879..c0d16bd82 100644 --- a/Minecraft.World/Network/Socket.cpp +++ b/Minecraft.World/Network/Socket.cpp @@ -227,7 +227,7 @@ bool Socket::close(bool isServerConnection) { m_endClosed[m_end] = true; } if (allClosed && m_socketClosedEvent != nullptr) { - m_socketClosedEvent->Set(); + m_socketClosedEvent->set(); } if (allClosed) createdOk = false; return allClosed; diff --git a/Minecraft.World/Util/C4JThread.cpp b/Minecraft.World/Util/C4JThread.cpp index 209eb7e29..f3ba46fc8 100644 --- a/Minecraft.World/Util/C4JThread.cpp +++ b/Minecraft.World/Util/C4JThread.cpp @@ -2,17 +2,15 @@ #include "C4JThread.h" -#include #include #include #include #include #include #include -#include -#include #include #include +#include #include #if defined(_WIN32) @@ -30,145 +28,109 @@ #include "../../Minecraft.Client/Platform/Common/ShutdownManager.h" -#if !defined(INFINITE) -#define INFINITE 0xFFFFFFFFu -#endif - -#if !defined(WAIT_OBJECT_0) -#define WAIT_OBJECT_0 0u -#endif - -#if !defined(WAIT_TIMEOUT) -#define WAIT_TIMEOUT 258u -#endif - -#if !defined(STILL_ACTIVE) -#define STILL_ACTIVE 259 -#endif - -#if !defined(THREAD_PRIORITY_IDLE) -#define THREAD_PRIORITY_IDLE (-15) -#endif - -#if !defined(THREAD_PRIORITY_LOWEST) -#define THREAD_PRIORITY_LOWEST (-2) -#endif - -#if !defined(THREAD_PRIORITY_BELOW_NORMAL) -#define THREAD_PRIORITY_BELOW_NORMAL (-1) -#endif - -#if !defined(THREAD_PRIORITY_NORMAL) -#define THREAD_PRIORITY_NORMAL 0 -#endif - -#if !defined(THREAD_PRIORITY_ABOVE_NORMAL) -#define THREAD_PRIORITY_ABOVE_NORMAL 1 -#endif - -#if !defined(THREAD_PRIORITY_HIGHEST) -#define THREAD_PRIORITY_HIGHEST 2 -#endif - -#if !defined(THREAD_PRIORITY_TIME_CRITICAL) -#define THREAD_PRIORITY_TIME_CRITICAL 15 -#endif - thread_local C4JThread* C4JThread::ms_currentThread = nullptr; namespace { constexpr int kDefaultStackSize = 65536 * 2; constexpr int kMinimumStackSize = 16384; -constexpr int kUnsetPriority = std::numeric_limits::min(); +constexpr auto kUnsetPriority = + static_cast(std::numeric_limits::min()); constexpr int kEventQueueShutdownPollMs = 100; const std::thread::id g_processMainThreadId = std::this_thread::get_id(); template -bool WaitForCondition(std::condition_variable& condition, +bool waitForCondition(std::condition_variable& condition, std::unique_lock& lock, int timeoutMs, Predicate predicate) { - if (timeoutMs < 0 || static_cast(timeoutMs) == - static_cast(INFINITE)) { + if (timeoutMs < 0) { condition.wait(lock, predicate); return true; } - return condition.wait_for(lock, std::chrono::milliseconds(timeoutMs), predicate); } -std::uint32_t FirstSetBitIndex(std::uint32_t bitMask) { +std::uint32_t firstSetBitIndex(std::uint32_t bitMask) { return static_cast(std::countr_zero(bitMask)); } -std::uint32_t BuildMaskForSize(int size) { - assert(size > 0); - assert(size <= 32); - - if (size == 32) { - return 0xFFFFFFFFU; - } - +std::uint32_t buildMaskForSize(int size) { + assert(size > 0 && size <= 32); + if (size == 32) return 0xFFFFFFFFU; return (1U << static_cast(size)) - 1U; } -void FormatThreadName(std::string& outThreadName, const char* threadName) { - const char* safeName = (threadName != nullptr && threadName[0] != '\0') - ? threadName - : "Unnamed"; - - char buffer[64]; - std::snprintf(buffer, sizeof(buffer), "(4J) %s", safeName); - buffer[sizeof(buffer) - 1] = '\0'; - outThreadName = buffer; +void formatThreadName(std::string& out, const char* name) { + const char* safe = (name && name[0] != '\0') ? name : "Unnamed"; + char buf[64]; + std::snprintf(buf, sizeof(buf), "(4J) %s", safe); + out = buf; } -const char* GetSafeThreadName(const char* threadName) { - return (threadName != nullptr && threadName[0] != '\0') ? threadName - : "(4J) Unnamed"; -} - -bool IsProcessorIndexPlausible(int proc) { - if (proc < 0) { - return true; - } - - const unsigned int hardwareThreads = std::thread::hardware_concurrency(); - if (hardwareThreads == 0U) { - return true; - } - - return static_cast(proc) < hardwareThreads; +bool isProcessorIndexPlausible(int proc) { + if (proc < 0) return true; + const unsigned hw = std::thread::hardware_concurrency(); + return hw == 0U || static_cast(proc) < hw; } +std::int64_t getNativeThreadId() { #if defined(__linux__) -std::int64_t GetLinuxThreadId() { return static_cast(::syscall(SYS_gettid)); +#else + return 0; +#endif } -int MapPriorityToNice(int priority) { - switch (priority) { - case THREAD_PRIORITY_TIME_CRITICAL: - return -15; - case THREAD_PRIORITY_HIGHEST: - return -10; - case THREAD_PRIORITY_ABOVE_NORMAL: - return -5; - case THREAD_PRIORITY_NORMAL: - return 0; - case THREAD_PRIORITY_BELOW_NORMAL: - return 5; - case THREAD_PRIORITY_LOWEST: - return 10; - case THREAD_PRIORITY_IDLE: - return 19; - default: - return 0; +void setThreadNamePlatform([[maybe_unused]] std::uint32_t threadId, + [[maybe_unused]] const char* name) { +#if defined(_WIN32) + // Try modern API first (Windows 10 1607+). + if (threadId == static_cast(-1) || + threadId == ::GetCurrentThreadId()) { + using SetThreadDescriptionFn = int32_t(WINAPI*)(void*, PCWSTR); + const HMODULE kernel = ::GetModuleHandleW(L"Kernel32.dll"); + if (kernel) { + const auto fn = reinterpret_cast( + ::GetProcAddress(kernel, "SetThreadDescription")); + if (fn) { + wchar_t wide[64]; + const auto n = std::mbstowcs( + wide, name, (sizeof(wide) / sizeof(wide[0])) - 1); + if (n != static_cast(-1)) { + wide[n] = L'\0'; + (void)fn(::GetCurrentThread(), wide); + return; + } + } + } } -} + + // Legacy fallback: raise exception 0x406D1388 for older MSVC debuggers. +#pragma pack(push, 8) + struct THREADNAME_INFO { + std::uint32_t dwType; + const char* szName; + std::uint32_t dwThreadID; + std::uint32_t dwFlags; + }; +#pragma pack(pop) + + THREADNAME_INFO info{0x1000, name, threadId, 0}; + __try { + ::RaiseException(0x406D1388, 0, sizeof(info) / sizeof(uintptr_t), + reinterpret_cast(&info)); + } __except (EXCEPTION_EXECUTE_HANDLER) { + } + +#elif defined(__linux__) + // pthread_setname_np limit: 16 chars including null terminator. + char truncated[16]; + std::snprintf(truncated, sizeof(truncated), "%s", name); + (void)::pthread_setname_np(::pthread_self(), truncated); #endif +} #if defined(_WIN32) thread_local std::vector g_affinityMaskStack; @@ -176,28 +138,126 @@ thread_local std::vector g_affinityMaskStack; thread_local std::vector g_affinityMaskStack; #endif +void setAffinityPlatform(std::thread& threadHandle, bool isSelf, int proc) { +#if defined(_WIN32) + void* handle = nullptr; + if (threadHandle.joinable()) + handle = threadHandle.native_handle(); + else if (isSelf) + handle = ::GetCurrentThread(); + else + return; + + DWORD_PTR mask = 0; + if (proc < 0) { + DWORD_PTR processMask = 0, systemMask = 0; + if (!::GetProcessAffinityMask(::GetCurrentProcess(), &processMask, + &systemMask) || + processMask == 0) + return; + mask = processMask; + } else { + constexpr auto bitCount = + static_cast(sizeof(DWORD_PTR) * CHAR_BIT); + if (static_cast(proc) >= bitCount) return; + mask = static_cast(1) << static_cast(proc); + } + (void)::SetThreadAffinityMask(handle, mask); + +#elif defined(__linux__) + pthread_t handle; + if (threadHandle.joinable()) + handle = threadHandle.native_handle(); + else if (isSelf) + handle = ::pthread_self(); + else + return; + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + if (proc < 0) { + if (::sched_getaffinity(0, sizeof(cpuset), &cpuset) != 0) return; + } else { + if (proc >= CPU_SETSIZE) return; + CPU_SET(proc, &cpuset); + } + (void)::pthread_setaffinity_np(handle, sizeof(cpuset), &cpuset); +#else + (void)threadHandle; + (void)isSelf; + (void)proc; +#endif +} + +void setPriorityPlatform(std::thread& threadHandle, bool isSelf, + C4JThread::ThreadPriority priority, + std::atomic& nativeTid) { +#if defined(_WIN32) + void* handle = nullptr; + if (threadHandle.joinable()) + handle = threadHandle.native_handle(); + else if (isSelf) + handle = ::GetCurrentThread(); + else + return; + (void)::SetThreadPriority(handle, std::to_underlying(priority)); + +#elif defined(__linux__) + std::int64_t tid = 0; + if (isSelf) { + tid = getNativeThreadId(); + nativeTid.store(tid, std::memory_order_release); + } else { + tid = nativeTid.load(std::memory_order_acquire); + } + if (tid <= 0) return; + + using enum C4JThread::ThreadPriority; + int niceValue = 0; + switch (priority) { + case TimeCritical: niceValue = -15; break; + case Highest: niceValue = -10; break; + case AboveNormal: niceValue = -5; break; + case Normal: niceValue = 0; break; + case BelowNormal: niceValue = 5; break; + case Lowest: niceValue = 10; break; + case Idle: niceValue = 19; break; + default: niceValue = 0; break; + } + + errno = 0; + if (::setpriority(PRIO_PROCESS, static_cast(tid), niceValue) != 0) { + if ((errno == EACCES || errno == EPERM) && niceValue < 0) { + (void)::setpriority(PRIO_PROCESS, static_cast(tid), 0); + } + } +#else + (void)threadHandle; + (void)isSelf; + (void)priority; + (void)nativeTid; +#endif +} + } // namespace C4JThread::C4JThread(C4JThreadStartFunc* startFunc, void* param, const char* threadName, int stackSize) : m_threadParam(param), m_startFunc(startFunc), - m_stackSize(stackSize == 0 ? kDefaultStackSize : stackSize), + m_stackSize(std::max(stackSize == 0 ? kDefaultStackSize : stackSize, + kMinimumStackSize)), m_threadName(), m_isRunning(false), m_hasStarted(false), - m_exitCode(STILL_ACTIVE), + m_exitCode(kStillActive), m_threadID(), m_threadHandle(), - m_completionFlag(std::make_unique(Event::e_modeManualClear)), + m_completionFlag(std::make_unique(Event::Mode::ManualClear)), m_requestedProcessor(-1), m_requestedPriority(kUnsetPriority), m_nativeTid(0) { - if (m_stackSize < kMinimumStackSize) { - m_stackSize = kMinimumStackSize; - } - - FormatThreadName(m_threadName, threadName); + formatThreadName(m_threadName, threadName); } C4JThread::C4JThread(const char* mainThreadName) @@ -207,21 +267,16 @@ C4JThread::C4JThread(const char* mainThreadName) m_threadName(), m_isRunning(true), m_hasStarted(true), - m_exitCode(STILL_ACTIVE), + m_exitCode(kStillActive), m_threadID(std::this_thread::get_id()), m_threadHandle(), - m_completionFlag(std::make_unique(Event::e_modeManualClear)), + m_completionFlag(std::make_unique(Event::Mode::ManualClear)), m_requestedProcessor(-1), m_requestedPriority(kUnsetPriority), -#if defined(__linux__) - m_nativeTid(GetLinuxThreadId()) -#else - m_nativeTid(0) -#endif -{ - FormatThreadName(m_threadName, mainThreadName); + m_nativeTid(getNativeThreadId()) { + formatThreadName(m_threadName, mainThreadName); ms_currentThread = this; - SetCurrentThreadName(m_threadName.c_str()); + setCurrentThreadName(m_threadName.c_str()); } C4JThread::~C4JThread() { @@ -246,28 +301,25 @@ C4JThread& C4JThread::getMainThreadInstance() noexcept { void C4JThread::entryPoint(C4JThread* pThread) { ms_currentThread = pThread; pThread->m_threadID = std::this_thread::get_id(); + pThread->m_nativeTid.store(getNativeThreadId(), std::memory_order_release); -#if defined(__linux__) - pThread->m_nativeTid.store(GetLinuxThreadId(), std::memory_order_release); -#endif - - SetCurrentThreadName(pThread->m_threadName.c_str()); + setCurrentThreadName(pThread->m_threadName.c_str()); const int requestedProcessor = pThread->m_requestedProcessor.load(std::memory_order_acquire); if (requestedProcessor >= 0) { - pThread->SetProcessor(requestedProcessor); + pThread->setProcessor(requestedProcessor); } - const int requestedPriority = + const auto requestedPriority = pThread->m_requestedPriority.load(std::memory_order_acquire); if (requestedPriority != kUnsetPriority) { - pThread->SetPriority(requestedPriority); + pThread->setPriority(requestedPriority); } int exitCode = 0; try { - exitCode = (pThread->m_startFunc != nullptr) + exitCode = pThread->m_startFunc ? (*pThread->m_startFunc)(pThread->m_threadParam) : 0; } catch (...) { @@ -276,10 +328,10 @@ void C4JThread::entryPoint(C4JThread* pThread) { pThread->m_exitCode.store(exitCode, std::memory_order_release); pThread->m_isRunning.store(false, std::memory_order_release); - pThread->m_completionFlag->Set(); + pThread->m_completionFlag->set(); } -void C4JThread::Run() { +void C4JThread::run() { bool expected = false; if (!m_hasStarted.compare_exchange_strong(expected, true, std::memory_order_acq_rel)) { @@ -287,8 +339,8 @@ void C4JThread::Run() { } m_isRunning.store(true, std::memory_order_release); - m_exitCode.store(STILL_ACTIVE, std::memory_order_release); - m_completionFlag->Clear(); + m_exitCode.store(kStillActive, std::memory_order_release); + m_completionFlag->clear(); m_nativeTid.store(0, std::memory_order_release); m_threadHandle = std::thread(&C4JThread::entryPoint, this); @@ -297,169 +349,50 @@ void C4JThread::Run() { const int requestedProcessor = m_requestedProcessor.load(std::memory_order_acquire); if (requestedProcessor >= 0) { - SetProcessor(requestedProcessor); + setProcessor(requestedProcessor); } - const int requestedPriority = + const auto requestedPriority = m_requestedPriority.load(std::memory_order_acquire); if (requestedPriority != kUnsetPriority) { - SetPriority(requestedPriority); + setPriority(requestedPriority); } } -void C4JThread::SetProcessor(int proc) { +void C4JThread::setProcessor(int proc) { m_requestedProcessor.store(proc, std::memory_order_release); - - if (!IsProcessorIndexPlausible(proc)) { - return; - } - -#if defined(_WIN32) - void* threadHandle = nullptr; - - if (m_threadHandle.joinable()) { - threadHandle = m_threadHandle.native_handle(); - } else if (ms_currentThread == this) { - threadHandle = ::GetCurrentThread(); - } else { - return; - } - - DWORD_PTR affinityMask = 0; - if (proc < 0) { - DWORD_PTR processAffinityMask = 0; - DWORD_PTR systemAffinityMask = 0; - if (!::GetProcessAffinityMask(::GetCurrentProcess(), - &processAffinityMask, - &systemAffinityMask) || - processAffinityMask == 0) { - return; - } - affinityMask = processAffinityMask; - } else { - const unsigned int bitCount = - static_cast(sizeof(DWORD_PTR) * CHAR_BIT); - if (static_cast(proc) >= bitCount) { - return; - } - - affinityMask = - (static_cast(1) << static_cast(proc)); - } - - (void)::SetThreadAffinityMask(threadHandle, affinityMask); - -#elif defined(__linux__) - pthread_t threadHandle; - - if (m_threadHandle.joinable()) { - threadHandle = m_threadHandle.native_handle(); - } else if (ms_currentThread == this) { - threadHandle = ::pthread_self(); - } else { - return; - } - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - - if (proc < 0) { - if (::sched_getaffinity(0, sizeof(cpuset), &cpuset) != 0) { - return; - } - } else { - if (proc >= CPU_SETSIZE) { - return; - } - CPU_SET(proc, &cpuset); - } - - (void)::pthread_setaffinity_np(threadHandle, sizeof(cpuset), &cpuset); -#else - (void)proc; -#endif + if (!isProcessorIndexPlausible(proc)) return; + setAffinityPlatform(m_threadHandle, ms_currentThread == this, proc); } -void C4JThread::SetPriority(int priority) { +void C4JThread::setPriority(ThreadPriority priority) { m_requestedPriority.store(priority, std::memory_order_release); - -#if defined(_WIN32) - void* threadHandle = nullptr; - - if (m_threadHandle.joinable()) { - threadHandle = m_threadHandle.native_handle(); - } else if (ms_currentThread == this) { - threadHandle = ::GetCurrentThread(); - } else { - return; - } - - (void)::SetThreadPriority(threadHandle, priority); - -#elif defined(__linux__) - std::int64_t nativeTid = 0; - - if (ms_currentThread == this) { - nativeTid = GetLinuxThreadId(); - m_nativeTid.store(nativeTid, std::memory_order_release); - } else { - nativeTid = m_nativeTid.load(std::memory_order_acquire); - } - - if (nativeTid <= 0) { - return; - } - - const int niceValue = MapPriorityToNice(priority); - - errno = 0; - if (::setpriority(PRIO_PROCESS, static_cast(nativeTid), niceValue) != - 0) { - if ((errno == EACCES || errno == EPERM) && niceValue < 0) { - (void)::setpriority(PRIO_PROCESS, static_cast(nativeTid), 0); - } - } -#else - (void)priority; -#endif + setPriorityPlatform(m_threadHandle, ms_currentThread == this, priority, + m_nativeTid); } -std::uint32_t C4JThread::WaitForCompletion(int timeoutMs) { - const std::uint32_t waitResult = m_completionFlag->WaitForSignal(timeoutMs); - if (waitResult == WAIT_OBJECT_0 && m_threadHandle.joinable()) { +std::uint32_t C4JThread::waitForCompletion(int timeoutMs) { + const std::uint32_t result = m_completionFlag->waitForSignal(timeoutMs); + if (result == WaitResult::Signaled && m_threadHandle.joinable()) { if (m_threadHandle.get_id() == std::this_thread::get_id()) { m_threadHandle.detach(); } else { m_threadHandle.join(); } } - return waitResult; + return result; } -int C4JThread::GetExitCode() const noexcept { +int C4JThread::getExitCode() const noexcept { return m_isRunning.load(std::memory_order_acquire) - ? STILL_ACTIVE + ? kStillActive : m_exitCode.load(std::memory_order_acquire); } -void C4JThread::Sleep(int millisecs) { - if (millisecs <= 0) { - std::this_thread::yield(); - return; - } - - std::this_thread::sleep_for(std::chrono::milliseconds(millisecs)); -} - C4JThread* C4JThread::getCurrentThread() noexcept { - if (ms_currentThread != nullptr) { - return ms_currentThread; - } - - if (std::this_thread::get_id() == g_processMainThreadId) { + if (ms_currentThread) return ms_currentThread; + if (std::this_thread::get_id() == g_processMainThreadId) return &getMainThreadInstance(); - } - return nullptr; } @@ -467,213 +400,122 @@ bool C4JThread::isMainThread() noexcept { return std::this_thread::get_id() == g_processMainThreadId; } -void C4JThread::SetThreadName(std::uint32_t threadId, const char* threadName) { - const char* safeThreadName = GetSafeThreadName(threadName); - -#if defined(_WIN32) - if (threadId == static_cast(-1) || - threadId == ::GetCurrentThreadId()) { - using SetThreadDescriptionFn = int32_t(WINAPI*)(void*, PCWSTR); - - const HMODULE kernelModule = ::GetModuleHandleW(L"Kernel32.dll"); - if (kernelModule != nullptr) { - const auto setThreadDescription = - reinterpret_cast( - ::GetProcAddress(kernelModule, "SetThreadDescription")); - - if (setThreadDescription != nullptr) { - wchar_t wideName[64]; - const std::size_t converted = - std::mbstowcs(wideName, safeThreadName, - (sizeof(wideName) / sizeof(wideName[0])) - 1); - - if (converted != static_cast(-1)) { - wideName[converted] = L'\0'; - (void)setThreadDescription(::GetCurrentThread(), wideName); - return; - } - } - } - } - -#pragma pack(push, 8) - struct THREADNAME_INFO { - std::uint32_t dwType; - const char* szName; - std::uint32_t dwThreadID; - std::uint32_t dwFlags; - }; -#pragma pack(pop) - - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = safeThreadName; - info.dwThreadID = threadId; - info.dwFlags = 0; - - __try { - ::RaiseException(0x406D1388, 0, sizeof(info) / sizeof(uintptr_t), - reinterpret_cast(&info)); - } __except (EXCEPTION_EXECUTE_HANDLER) { - } - -#elif defined(__linux__) - (void)threadId; - - char truncatedName[16]; - std::snprintf(truncatedName, sizeof(truncatedName), "%s", safeThreadName); - truncatedName[sizeof(truncatedName) - 1] = '\0'; - - (void)::pthread_setname_np(::pthread_self(), truncatedName); - -#else - (void)threadId; - (void)safeThreadName; -#endif +void C4JThread::setThreadName(std::uint32_t threadId, const char* threadName) { + const char* safe = (threadName && threadName[0] != '\0') ? threadName + : "(4J) Unnamed"; + setThreadNamePlatform(threadId, safe); } -void C4JThread::SetCurrentThreadName(const char* threadName) { - SetThreadName(static_cast(-1), threadName); +void C4JThread::setCurrentThreadName(const char* threadName) { + setThreadName(static_cast(-1), threadName); } -C4JThread::Event::Event(EMode mode) +C4JThread::Event::Event(Mode mode) : m_mode(mode), m_mutex(), m_condition(), m_signaled(false) {} -void C4JThread::Event::Set() { +void C4JThread::Event::set() { { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); m_signaled = true; } - - if (m_mode == e_modeAutoClear) { + if (m_mode == Mode::AutoClear) m_condition.notify_one(); - } else { + else m_condition.notify_all(); - } } -void C4JThread::Event::Clear() { - std::lock_guard lock(m_mutex); +void C4JThread::Event::clear() { + std::lock_guard lock(m_mutex); m_signaled = false; } -std::uint32_t C4JThread::Event::WaitForSignal(int timeoutMs) { - std::unique_lock lock(m_mutex); - const bool signaled = WaitForCondition(m_condition, lock, timeoutMs, - [this] { return m_signaled; }); - - if (!signaled) { - return WAIT_TIMEOUT; +std::uint32_t C4JThread::Event::waitForSignal(int timeoutMs) { + std::unique_lock lock(m_mutex); + if (!waitForCondition(m_condition, lock, timeoutMs, + [this] { return m_signaled; })) { + return WaitResult::Timeout; } - - if (m_mode == e_modeAutoClear) { - m_signaled = false; - } - - return WAIT_OBJECT_0; + if (m_mode == Mode::AutoClear) m_signaled = false; + return WaitResult::Signaled; } -C4JThread::EventArray::EventArray(int size, EMode mode) +C4JThread::EventArray::EventArray(int size, Mode mode) : m_size(size), m_mode(mode), m_mutex(), m_condition(), m_signaledMask(0U) { - assert(m_size > 0); - assert(m_size <= 32); + assert(m_size > 0 && m_size <= 32); } -void C4JThread::EventArray::Set(int index) { - assert(index >= 0); - assert(index < m_size); - +void C4JThread::EventArray::set(int index) { + assert(index >= 0 && index < m_size); { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); m_signaledMask |= (1U << static_cast(index)); } - m_condition.notify_all(); } -void C4JThread::EventArray::Clear(int index) { - assert(index >= 0); - assert(index < m_size); - - std::lock_guard lock(m_mutex); +void C4JThread::EventArray::clear(int index) { + assert(index >= 0 && index < m_size); + std::lock_guard lock(m_mutex); m_signaledMask &= ~(1U << static_cast(index)); } -void C4JThread::EventArray::SetAll() { +void C4JThread::EventArray::setAll() { { - std::lock_guard lock(m_mutex); - m_signaledMask |= BuildMaskForSize(m_size); + std::lock_guard lock(m_mutex); + m_signaledMask |= buildMaskForSize(m_size); } - m_condition.notify_all(); } -void C4JThread::EventArray::ClearAll() { - std::lock_guard lock(m_mutex); +void C4JThread::EventArray::clearAll() { + std::lock_guard lock(m_mutex); m_signaledMask = 0U; } -std::uint32_t C4JThread::EventArray::WaitForSingle(int index, int timeoutMs) { - assert(index >= 0); - assert(index < m_size); - +std::uint32_t C4JThread::EventArray::waitForSingle(int index, int timeoutMs) { + assert(index >= 0 && index < m_size); const std::uint32_t bitMask = 1U << static_cast(index); - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); - const bool signaled = WaitForCondition( - m_condition, lock, timeoutMs, - [this, bitMask] { return (m_signaledMask & bitMask) != 0U; }); - - if (!signaled) { - return WAIT_TIMEOUT; + if (!waitForCondition(m_condition, lock, timeoutMs, + [this, bitMask] { + return (m_signaledMask & bitMask) != 0U; + })) { + return WaitResult::Timeout; } - - if (m_mode == e_modeAutoClear) { - m_signaledMask &= ~bitMask; - } - - return WAIT_OBJECT_0; + if (m_mode == Mode::AutoClear) m_signaledMask &= ~bitMask; + return WaitResult::Signaled; } -std::uint32_t C4JThread::EventArray::WaitForAll(int timeoutMs) { - const std::uint32_t bitMask = BuildMaskForSize(m_size); - std::unique_lock lock(m_mutex); +std::uint32_t C4JThread::EventArray::waitForAll(int timeoutMs) { + const std::uint32_t bitMask = buildMaskForSize(m_size); + std::unique_lock lock(m_mutex); - const bool signaled = WaitForCondition( - m_condition, lock, timeoutMs, - [this, bitMask] { return (m_signaledMask & bitMask) == bitMask; }); - - if (!signaled) { - return WAIT_TIMEOUT; + if (!waitForCondition(m_condition, lock, timeoutMs, + [this, bitMask] { + return (m_signaledMask & bitMask) == bitMask; + })) { + return WaitResult::Timeout; } - - if (m_mode == e_modeAutoClear) { - m_signaledMask &= ~bitMask; - } - - return WAIT_OBJECT_0; + if (m_mode == Mode::AutoClear) m_signaledMask &= ~bitMask; + return WaitResult::Signaled; } -std::uint32_t C4JThread::EventArray::WaitForAny(int timeoutMs) { - const std::uint32_t bitMask = BuildMaskForSize(m_size); - std::unique_lock lock(m_mutex); +std::uint32_t C4JThread::EventArray::waitForAny(int timeoutMs) { + const std::uint32_t bitMask = buildMaskForSize(m_size); + std::unique_lock lock(m_mutex); - const bool signaled = WaitForCondition( - m_condition, lock, timeoutMs, - [this, bitMask] { return (m_signaledMask & bitMask) != 0U; }); - - if (!signaled) { - return WAIT_TIMEOUT; + if (!waitForCondition(m_condition, lock, timeoutMs, + [this, bitMask] { + return (m_signaledMask & bitMask) != 0U; + })) { + return WaitResult::Timeout; } - const std::uint32_t readyMask = m_signaledMask & bitMask; - const std::uint32_t readyIndex = FirstSetBitIndex(readyMask); - - if (m_mode == e_modeAutoClear) { - m_signaledMask &= ~(1U << readyIndex); - } - - return WAIT_OBJECT_0 + readyIndex; + const std::uint32_t readyIndex = + firstSetBitIndex(m_signaledMask & bitMask); + if (m_mode == Mode::AutoClear) m_signaledMask &= ~(1U << readyIndex); + return WaitResult::Signaled + readyIndex; } C4JThread::EventQueue::EventQueue(UpdateFunc* updateFunc, @@ -686,88 +528,67 @@ C4JThread::EventQueue::EventQueue(UpdateFunc* updateFunc, m_drainedCondition(), m_updateFunc(updateFunc), m_threadInitFunc(threadInitFunc), - m_threadName(threadName != nullptr ? threadName : "Unnamed"), + m_threadName(threadName ? threadName : "Unnamed"), m_processor(-1), m_priority(kUnsetPriority), m_busy(false), m_initOnce(), m_stopRequested(false) { - assert(m_updateFunc != nullptr); + assert(m_updateFunc); } C4JThread::EventQueue::~EventQueue() { m_stopRequested.store(true, std::memory_order_release); m_queueCondition.notify_all(); - - if (m_thread) { - (void)m_thread->WaitForCompletion(INFINITE); - } + if (m_thread) (void)m_thread->waitForCompletion(kInfiniteTimeout); } void C4JThread::EventQueue::setProcessor(int proc) { m_processor = proc; - if (m_thread) { - m_thread->SetProcessor(proc); - } + if (m_thread) m_thread->setProcessor(proc); } -void C4JThread::EventQueue::setPriority(int priority) { +void C4JThread::EventQueue::setPriority(ThreadPriority priority) { m_priority = priority; - if (m_thread) { - m_thread->SetPriority(priority); - } + if (m_thread) m_thread->setPriority(priority); } void C4JThread::EventQueue::init() { std::call_once(m_initOnce, [this]() { m_thread = std::make_unique(threadFunc, this, m_threadName.c_str()); - - if (m_processor >= 0) { - m_thread->SetProcessor(m_processor); - } - - if (m_priority != kUnsetPriority) { - m_thread->SetPriority(m_priority); - } - - m_thread->Run(); + if (m_processor >= 0) m_thread->setProcessor(m_processor); + if (m_priority != kUnsetPriority) m_thread->setPriority(m_priority); + m_thread->run(); }); } void C4JThread::EventQueue::sendEvent(Level* pLevel) { init(); - - if (m_stopRequested.load(std::memory_order_acquire)) { - return; - } - + if (m_stopRequested.load(std::memory_order_acquire)) return; { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); m_queue.push(pLevel); } - m_queueCondition.notify_one(); } void C4JThread::EventQueue::waitForFinish() { init(); - - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); m_drainedCondition.wait(lock, [this] { return m_queue.empty() && !m_busy; }); } int C4JThread::EventQueue::threadFunc(void* lpParam) { - EventQueue* pQueue = static_cast(lpParam); - pQueue->threadPoll(); + static_cast(lpParam)->threadPoll(); return 0; } void C4JThread::EventQueue::threadPoll() { ShutdownManager::HasStarted(ShutdownManager::eEventQueueThreads); - if (m_threadInitFunc != nullptr) { + if (m_threadInitFunc) { try { m_threadInitFunc(); } catch (...) { @@ -779,7 +600,7 @@ void C4JThread::EventQueue::threadPoll() { void* updateParam = nullptr; { - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); m_queueCondition.wait_for( lock, std::chrono::milliseconds(kEventQueueShutdownPollMs), [this] { @@ -787,13 +608,8 @@ void C4JThread::EventQueue::threadPoll() { !m_queue.empty(); }); - if (m_stopRequested.load(std::memory_order_acquire)) { - break; - } - - if (m_queue.empty()) { - continue; - } + if (m_stopRequested.load(std::memory_order_acquire)) break; + if (m_queue.empty()) continue; m_busy = true; updateParam = m_queue.front(); @@ -806,82 +622,60 @@ void C4JThread::EventQueue::threadPoll() { } { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); m_busy = false; - if (m_queue.empty()) { - m_drainedCondition.notify_all(); - } + if (m_queue.empty()) m_drainedCondition.notify_all(); } } { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); m_busy = false; - std::queue emptyQueue; - m_queue.swap(emptyQueue); + std::queue empty; + m_queue.swap(empty); } m_drainedCondition.notify_all(); ShutdownManager::HasFinished(ShutdownManager::eEventQueueThreads); } -void C4JThread::PushAffinityAllCores() { +void C4JThread::pushAffinityAllCores() { #if defined(_WIN32) - const void* currentThread = ::GetCurrentThread(); - DWORD_PTR processAffinityMask = 0; - DWORD_PTR systemAffinityMask = 0; - - if (!::GetProcessAffinityMask(::GetCurrentProcess(), &processAffinityMask, - &systemAffinityMask) || - processAffinityMask == 0) { + DWORD_PTR processMask = 0, systemMask = 0; + if (!::GetProcessAffinityMask(::GetCurrentProcess(), &processMask, + &systemMask) || + processMask == 0) return; - } - - const DWORD_PTR previousMask = - ::SetThreadAffinityMask(currentThread, processAffinityMask); - - if (previousMask != 0) { - g_affinityMaskStack.push_back(previousMask); - } + const DWORD_PTR prev = + ::SetThreadAffinityMask(::GetCurrentThread(), processMask); + if (prev != 0) g_affinityMaskStack.push_back(prev); #elif defined(__linux__) - cpu_set_t previousMask; - if (::pthread_getaffinity_np(::pthread_self(), sizeof(previousMask), - &previousMask) != 0) { + cpu_set_t prev; + if (::pthread_getaffinity_np(::pthread_self(), sizeof(prev), &prev) != 0) return; - } + g_affinityMaskStack.push_back(prev); - g_affinityMaskStack.push_back(previousMask); - - cpu_set_t allowedMask; - if (::sched_getaffinity(0, sizeof(allowedMask), &allowedMask) != 0) { + cpu_set_t all; + if (::sched_getaffinity(0, sizeof(all), &all) != 0) { g_affinityMaskStack.pop_back(); return; } - - (void)::pthread_setaffinity_np(::pthread_self(), sizeof(allowedMask), - &allowedMask); + (void)::pthread_setaffinity_np(::pthread_self(), sizeof(all), &all); #endif } -void C4JThread::PopAffinity() { +void C4JThread::popAffinity() { #if defined(_WIN32) - if (g_affinityMaskStack.empty()) { - return; - } - - const DWORD_PTR previousMask = g_affinityMaskStack.back(); + if (g_affinityMaskStack.empty()) return; + const DWORD_PTR prev = g_affinityMaskStack.back(); g_affinityMaskStack.pop_back(); - (void)::SetThreadAffinityMask(::GetCurrentThread(), previousMask); + (void)::SetThreadAffinityMask(::GetCurrentThread(), prev); #elif defined(__linux__) - if (g_affinityMaskStack.empty()) { - return; - } - - const cpu_set_t previousMask = g_affinityMaskStack.back(); + if (g_affinityMaskStack.empty()) return; + const cpu_set_t prev = g_affinityMaskStack.back(); g_affinityMaskStack.pop_back(); - (void)::pthread_setaffinity_np(::pthread_self(), sizeof(previousMask), - &previousMask); + (void)::pthread_setaffinity_np(::pthread_self(), sizeof(prev), &prev); #endif -} \ No newline at end of file +} diff --git a/Minecraft.World/Util/C4JThread.h b/Minecraft.World/Util/C4JThread.h index 8fea963f1..3d0ea9688 100644 --- a/Minecraft.World/Util/C4JThread.h +++ b/Minecraft.World/Util/C4JThread.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -37,19 +36,37 @@ inline constexpr int CPU_CORE_LEADERBOARDS = 5; class C4JThread { public: + struct WaitResult { + static constexpr std::uint32_t Signaled = 0; + static constexpr std::uint32_t Timeout = 258; + }; + + enum class ThreadPriority : int { + Idle = -15, + Lowest = -2, + BelowNormal = -1, + Normal = 0, + AboveNormal = 1, + Highest = 2, + TimeCritical = 15 + }; + + static constexpr int kInfiniteTimeout = -1; + static constexpr int kStillActive = 259; + class Event { public: - enum EMode { e_modeAutoClear, e_modeManualClear }; + enum class Mode { AutoClear, ManualClear }; - explicit Event(EMode mode = e_modeAutoClear); + explicit Event(Mode mode = Mode::AutoClear); ~Event() = default; - void Set(); - void Clear(); - std::uint32_t WaitForSignal(int timeoutMs); + void set(); + void clear(); + std::uint32_t waitForSignal(int timeoutMs); private: - EMode m_mode; + Mode m_mode; std::mutex m_mutex; std::condition_variable m_condition; bool m_signaled; @@ -57,21 +74,21 @@ public: class EventArray { public: - enum EMode { e_modeAutoClear, e_modeManualClear }; + enum class Mode { AutoClear, ManualClear }; - explicit EventArray(int size, EMode mode = e_modeAutoClear); + explicit EventArray(int size, Mode mode = Mode::AutoClear); - void Set(int index); - void Clear(int index); - void SetAll(); - void ClearAll(); - std::uint32_t WaitForAll(int timeoutMs); - std::uint32_t WaitForAny(int timeoutMs); - std::uint32_t WaitForSingle(int index, int timeoutMs); + void set(int index); + void clear(int index); + void setAll(); + void clearAll(); + std::uint32_t waitForAll(int timeoutMs); + std::uint32_t waitForAny(int timeoutMs); + std::uint32_t waitForSingle(int index, int timeoutMs); private: int m_size; - EMode m_mode; + Mode m_mode; std::mutex m_mutex; std::condition_variable m_condition; std::uint32_t m_signaledMask; @@ -90,7 +107,7 @@ public: EventQueue& operator=(const EventQueue&) = delete; void setProcessor(int proc); - void setPriority(int priority); + void setPriority(ThreadPriority priority); void sendEvent(Level* pLevel); void waitForFinish(); @@ -108,7 +125,7 @@ public: ThreadInitFunc* m_threadInitFunc; std::string m_threadName; int m_processor; - int m_priority; + ThreadPriority m_priority; bool m_busy; std::once_flag m_initOnce; std::atomic m_stopRequested; @@ -122,24 +139,25 @@ public: C4JThread(const C4JThread&) = delete; C4JThread& operator=(const C4JThread&) = delete; - void Run(); + void run(); - [[nodiscard]] bool isRunning() const noexcept { return m_isRunning.load(); } + [[nodiscard]] bool isRunning() const noexcept { + return m_isRunning.load(std::memory_order_acquire); + } [[nodiscard]] bool hasStarted() const noexcept { - return m_hasStarted.load(); + return m_hasStarted.load(std::memory_order_acquire); } - void SetProcessor(int proc); - void SetPriority(int priority); + void setProcessor(int proc); + void setPriority(ThreadPriority priority); - std::uint32_t WaitForCompletion(int timeoutMs); - [[nodiscard]] int GetExitCode() const noexcept; + std::uint32_t waitForCompletion(int timeoutMs); + [[nodiscard]] int getExitCode() const noexcept; [[nodiscard]] const char* getName() const noexcept { return m_threadName.c_str(); } - static void Sleep(int millisecs); static C4JThread* getCurrentThread() noexcept; static bool isMainThread() noexcept; @@ -148,11 +166,16 @@ public: return pThread ? pThread->getName() : "(4J) Unknown thread"; } - static void SetThreadName(std::uint32_t threadId, const char* threadName); - static void SetCurrentThreadName(const char* threadName); + static void setThreadName(std::uint32_t threadId, const char* threadName); + static void setCurrentThreadName(const char* threadName); - static void PushAffinityAllCores(); - static void PopAffinity(); + static void pushAffinityAllCores(); + static void popAffinity(); + + // TODO(C++26): When we switch to C++26, replace EventQueue with + // std::execution (senders/receivers) for structured concurrency. + // TODO(C++26): When we switch to C++26, use std::hazard_pointer / std::rcu + // for lock-free data structure reclamation. private: static void entryPoint(C4JThread* pThread); @@ -171,8 +194,8 @@ private: std::unique_ptr m_completionFlag; std::atomic m_requestedProcessor; - std::atomic m_requestedPriority; + std::atomic m_requestedPriority; std::atomic m_nativeTid; static thread_local C4JThread* ms_currentThread; -}; \ No newline at end of file +}; From 1767c3f6e968b8ab18a57ba6d71d76c75f282152 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+tropicaaal@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:37:24 -0500 Subject: [PATCH 7/7] chore: fmt --- Minecraft.Client/Level/MultiPlayerLevel.cpp | 4 +- Minecraft.Client/Level/ServerLevel.cpp | 27 +- Minecraft.Client/Minecraft.cpp | 1312 +++++++++-------- Minecraft.Client/MinecraftServer.cpp | 23 +- .../Network/MultiPlayerChunkCache.cpp | 80 +- Minecraft.Client/Network/PlayerConnection.cpp | 4 +- Minecraft.Client/Network/PlayerList.cpp | 123 +- Minecraft.Client/Network/ServerChunkCache.cpp | 41 +- Minecraft.Client/Network/ServerConnection.cpp | 34 +- .../Platform/Common/Consoles_App.cpp | 340 +++-- .../Leaderboards/SonyLeaderboardManager.cpp | 42 +- .../Platform/Common/UI/UIController.cpp | 9 +- .../Platform/Common/UI/UIScene.cpp | 4 +- Minecraft.Client/Rendering/Chunk.cpp | 35 +- Minecraft.Client/Rendering/Chunk.h | 4 +- .../EntityRenderers/ProgressRenderer.cpp | 21 +- Minecraft.Client/Rendering/GameRenderer.cpp | 11 +- Minecraft.Client/Rendering/LevelRenderer.cpp | 5 +- .../IO/Files/ConsoleSaveFileOriginal.cpp | 8 +- .../IO/Files/ConsoleSaveFileSplit.cpp | 5 +- Minecraft.World/IO/Streams/Compression.cpp | 64 +- Minecraft.World/Level/Level.cpp | 921 ++++++------ Minecraft.World/Level/Level.h | 4 +- Minecraft.World/Level/LevelChunk.cpp | 624 ++++---- .../Level/Storage/CompressedTileStorage.cpp | 21 +- .../Level/Storage/McRegionChunkStorage.cpp | 118 +- .../Level/Storage/ZonedChunkStorage.cpp | 3 +- Minecraft.World/Network/Connection.cpp | 3 +- Minecraft.World/Network/Connection.h | 2 +- Minecraft.World/Network/Socket.cpp | 18 +- Minecraft.World/Network/Socket.h | 2 +- Minecraft.World/Util/C4JThread.cpp | 60 +- 32 files changed, 2076 insertions(+), 1896 deletions(-) diff --git a/Minecraft.Client/Level/MultiPlayerLevel.cpp b/Minecraft.Client/Level/MultiPlayerLevel.cpp index 9c3fee74d..1bf05b98a 100644 --- a/Minecraft.Client/Level/MultiPlayerLevel.cpp +++ b/Minecraft.Client/Level/MultiPlayerLevel.cpp @@ -929,8 +929,8 @@ void MultiPlayerLevel::removeUnusedTileEntitiesInRegion(int x0, int y0, int z0, tileEntityList[i] = tileEntityList.back(); tileEntityList.pop_back(); - // 4J Stu - Chests can create new tile entities when being - // removed, so disable this + // 4J Stu - Chests can create new tile entities when + // being removed, so disable this m_bDisableAddNewTileEntities = true; lc->removeTileEntity(te->x & 15, te->y, te->z & 15); m_bDisableAddNewTileEntities = false; diff --git a/Minecraft.Client/Level/ServerLevel.cpp b/Minecraft.Client/Level/ServerLevel.cpp index afd3315ad..2822c8350 100644 --- a/Minecraft.Client/Level/ServerLevel.cpp +++ b/Minecraft.Client/Level/ServerLevel.cpp @@ -192,15 +192,21 @@ ServerLevel::~ServerLevel() { } m_queuedSendTileUpdates.clear(); - delete this->tracker; // MGH - added, we were losing about 500K going in - // and out the menus + delete this->tracker; // MGH - added, we were losing about 500K going + // in and out the menus delete this->chunkMap; } // Make sure that the update thread isn't actually doing any updating - { std::lock_guard lock(m_updateCS[0]); } - { std::lock_guard lock(m_updateCS[1]); } - { std::lock_guard lock(m_updateCS[2]); } + { + std::lock_guard lock(m_updateCS[0]); + } + { + std::lock_guard lock(m_updateCS[1]); + } + { + std::lock_guard lock(m_updateCS[2]); + } m_updateTrigger->clearAll(); } @@ -441,8 +447,9 @@ void ServerLevel::tickTiles() { { std::lock_guard lock(m_updateCS[iLev]); - // This section processes the tiles that need to be ticked, which we worked - // out in the previous tick (or haven't yet, if this is the first frame) + // This section processes the tiles that need to be ticked, which we + // worked out in the previous tick (or haven't yet, if this is the first + // frame) /*int grassTicks = 0; int lavaTicks = 0; int otherTicks = 0;*/ @@ -452,7 +459,8 @@ void ServerLevel::tickTiles() { int z = m_updateTileZ[iLev][i]; if (hasChunkAt(x, y, z)) { int id = getTile(x, y, z); - if (Tile::tiles[id] != nullptr && Tile::tiles[id]->isTicking()) { + if (Tile::tiles[id] != nullptr && + Tile::tiles[id]->isTicking()) { /*if(id == 2) ++grassTicks; else if(id == 11) ++lavaTicks; else ++otherTicks;*/ @@ -461,7 +469,8 @@ void ServerLevel::tickTiles() { } } // printf("Total ticks - Grass: %d, Lava: %d, Other: %d, Total: %d\n", - // grassTicks, lavaTicks, otherTicks, grassTicks + lavaTicks + otherTicks); + // grassTicks, lavaTicks, otherTicks, grassTicks + lavaTicks + + // otherTicks); m_updateTileCount[iLev] = 0; m_updateChunkCount[iLev] = 0; } diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index de9428a74..2305f0ed9 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -987,356 +987,447 @@ void Minecraft::run_middle() { } #endif - { std::lock_guard lock(m_setLevelCS); + { + std::lock_guard lock(m_setLevelCS); - if (running) { - if (reloadTextures) { - reloadTextures = false; - textures->reloadAll(); - } + if (running) { + if (reloadTextures) { + reloadTextures = false; + textures->reloadAll(); + } - // while (running) - { - // try { // 4J - removed try/catch - // if (minecraftApplet != null && - // !minecraftApplet.isActive()) break; // 4J - removed + // while (running) + { + // try { // 4J - removed try/catch + // if (minecraftApplet != null && + // !minecraftApplet.isActive()) break; // 4J - + // removed - // if (parent == nullptr && Display.isCloseRequested()) { - // // 4J - removed - // stop(); - // } + // if (parent == nullptr && + // Display.isCloseRequested()) { + // // 4J - removed + // stop(); + // } - // 4J-PB - AUTOSAVE TIMER - only in the full game and if the player - // is the host - if (level != nullptr && ProfileManager.IsFullVersion() && - g_NetworkManager.IsHost()) { - /*if(!bAutosaveTimerSet) - { - // set the timer - bAutosaveTimerSet=true; + // 4J-PB - AUTOSAVE TIMER - only in the full game and if the + // player is the host + if (level != nullptr && ProfileManager.IsFullVersion() && + g_NetworkManager.IsHost()) { + /*if(!bAutosaveTimerSet) + { + // set the timer + bAutosaveTimerSet=true; - app.SetAutosaveTimerTime(); - } - else*/ - { - // if the pause menu is up for the primary player, don't - // autosave If saving isn't disabled, and the main player - // has a app action running , or has any crafting or - // containers open, don't autosave - if (!StorageManager.GetSaveDisabled() && - (app.GetXuiAction(ProfileManager.GetPrimaryPad()) == - eAppAction_Idle)) { - if (!ui.IsPauseMenuDisplayed( - ProfileManager.GetPrimaryPad()) && - !ui.IsIgnoreAutosaveMenuDisplayed( - ProfileManager.GetPrimaryPad())) { - // check if the autotimer countdown has reached zero - unsigned char ucAutosaveVal = app.GetGameSettings( - ProfileManager.GetPrimaryPad(), - eGameSetting_Autosave); - bool bTrialTexturepack = false; - if (!Minecraft::GetInstance() - ->skins->isUsingDefaultSkin()) { - TexturePack* tPack = Minecraft::GetInstance() - ->skins->getSelected(); - DLCTexturePack* pDLCTexPack = - (DLCTexturePack*)tPack; - - DLCPack* pDLCPack = - pDLCTexPack->getDLCInfoParentPack(); - - if (pDLCPack) { - if (!pDLCPack->hasPurchasedFile( - DLCManager::e_DLCType_Texture, - L"")) { - bTrialTexturepack = true; - } - } - } - - // If the autosave value is not zero, and the player - // isn't using a trial texture pack, then check - // whether we need to save this tick - if ((ucAutosaveVal != 0) && !bTrialTexturepack) { - if (app.AutosaveDue()) { - // disable the autosave countdown - ui.ShowAutosaveCountdownTimer(false); - - // Need to save now - app.DebugPrintf("+++++++++++\n"); - app.DebugPrintf("+++Autosave\n"); - app.DebugPrintf("+++++++++++\n"); - app.SetAction( + app.SetAutosaveTimerTime(); + } + else*/ + { + // if the pause menu is up for the primary player, don't + // autosave If saving isn't disabled, and the main + // player has a app action running , or has any crafting + // or containers open, don't autosave + if (!StorageManager.GetSaveDisabled() && + (app.GetXuiAction(ProfileManager.GetPrimaryPad()) == + eAppAction_Idle)) { + if (!ui.IsPauseMenuDisplayed( + ProfileManager.GetPrimaryPad()) && + !ui.IsIgnoreAutosaveMenuDisplayed( + ProfileManager.GetPrimaryPad())) { + // check if the autotimer countdown has reached + // zero + unsigned char ucAutosaveVal = + app.GetGameSettings( ProfileManager.GetPrimaryPad(), - eAppAction_AutosaveSaveGame); - // app.SetAutosaveTimerTime(); + eGameSetting_Autosave); + bool bTrialTexturepack = false; + if (!Minecraft::GetInstance() + ->skins->isUsingDefaultSkin()) { + TexturePack* tPack = + Minecraft::GetInstance() + ->skins->getSelected(); + DLCTexturePack* pDLCTexPack = + (DLCTexturePack*)tPack; + + DLCPack* pDLCPack = + pDLCTexPack->getDLCInfoParentPack(); + + if (pDLCPack) { + if (!pDLCPack->hasPurchasedFile( + DLCManager::e_DLCType_Texture, + L"")) { + bTrialTexturepack = true; + } + } + } + + // If the autosave value is not zero, and the + // player isn't using a trial texture pack, then + // check whether we need to save this tick + if ((ucAutosaveVal != 0) && + !bTrialTexturepack) { + if (app.AutosaveDue()) { + // disable the autosave countdown + ui.ShowAutosaveCountdownTimer(false); + + // Need to save now + app.DebugPrintf("+++++++++++\n"); + app.DebugPrintf("+++Autosave\n"); + app.DebugPrintf("+++++++++++\n"); + app.SetAction( + ProfileManager.GetPrimaryPad(), + eAppAction_AutosaveSaveGame); + // app.SetAutosaveTimerTime(); #if !defined(_CONTENT_PACKAGE) - { - // print the time - SYSTEMTIME UTCSysTime; - GetSystemTime(&UTCSysTime); - // char szTime[15]; + { + // print the time + SYSTEMTIME UTCSysTime; + GetSystemTime(&UTCSysTime); + // char szTime[15]; - app.DebugPrintf("%02d:%02d:%02d\n", - UTCSysTime.wHour, - UTCSysTime.wMinute, - UTCSysTime.wSecond); - } + app.DebugPrintf("%02d:%02d:%02d\n", + UTCSysTime.wHour, + UTCSysTime.wMinute, + UTCSysTime.wSecond); + } #endif - } else { - unsigned int uiTimeToAutosave = - app.SecondsToAutosave(); + } else { + unsigned int uiTimeToAutosave = + app.SecondsToAutosave(); - if (uiTimeToAutosave < 6) { - ui.ShowAutosaveCountdownTimer(true); - ui.UpdateAutosaveCountdownTimer( - uiTimeToAutosave); + if (uiTimeToAutosave < 6) { + ui.ShowAutosaveCountdownTimer(true); + ui.UpdateAutosaveCountdownTimer( + uiTimeToAutosave); + } } } - } - } else { - // disable the autosave countdown - ui.ShowAutosaveCountdownTimer(false); - } - } - } - } - - // 4J-PB - Once we're in the level, check if the players have the - // level in their banned list and ask if they want to play it - for (int i = 0; i < XUSER_MAX_COUNT; i++) { - if (localplayers[i] && (app.GetBanListCheck(i) == false) && - !Minecraft::GetInstance()->isTutorial() && - ProfileManager.IsSignedInLive(i) && - !ProfileManager.IsGuest(i)) { - // If there is a sys ui displayed, we can't display the - // message box here, so ignore until we can - if (!ProfileManager.IsSystemUIDisplayed()) { - app.SetBanListCheck(i, true); - // 4J-PB - check if the level is in the banned level - // list get the unique save name and xuid from whoever - // is the host - INetworkPlayer* pHostPlayer = - g_NetworkManager.GetHostPlayer(); - PlayerUID xuid = pHostPlayer->GetUID(); - - if (app.IsInBannedLevelList(i, xuid, - app.GetUniqueMapName())) { - // put up a message box asking if the player would - // like to unban this level - app.DebugPrintf("This level is banned\n"); - // set the app action to bring up the message box to - // give them the option to remove from the ban list - // or exit the level - app.SetAction(i, eAppAction_LevelInBanLevelList, - (void*)true); - } - } - } - } - - if (!ProfileManager.IsSystemUIDisplayed() && - app.DLCInstallProcessCompleted() && !app.DLCInstallPending() && - app.m_dlcManager.NeedsCorruptCheck()) { - app.m_dlcManager.checkForCorruptDLCAndAlert(); - } - - // When we go into the first loaded level, check if the console has - // active joypads that are not in the game, and bring up the - // quadrant display to remind them to press start (if the session - // has space) - if (level != nullptr && bFirstTimeIntoGame && - g_NetworkManager.SessionHasSpace()) { - // have a short delay before the display - if (iFirstTimeCountdown == 0) { - bFirstTimeIntoGame = false; - - if (app.IsLocalMultiplayerAvailable()) { - for (int i = 0; i < XUSER_MAX_COUNT; i++) { - if ((localplayers[i] == nullptr) && - InputManager.IsPadConnected(i)) { - if (!ui.PressStartPlaying(i)) { - ui.ShowPressStart(i); - } + } else { + // disable the autosave countdown + ui.ShowAutosaveCountdownTimer(false); } } } - } else - iFirstTimeCountdown--; - } - // 4J-PB - store any button toggles for the players, since the - // minecraft::tick may not be called if we're running fast, and a - // button press and release will be missed + } - for (int i = 0; i < XUSER_MAX_COUNT; i++) { - if (localplayers[i]) { - // 4J-PB - add these to check for coming out of idle - if (InputManager.ButtonPressed(i, MINECRAFT_ACTION_JUMP)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_JUMP; - if (InputManager.ButtonPressed(i, MINECRAFT_ACTION_USE)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_USE; + // 4J-PB - Once we're in the level, check if the players have + // the level in their banned list and ask if they want to play + // it + for (int i = 0; i < XUSER_MAX_COUNT; i++) { + if (localplayers[i] && (app.GetBanListCheck(i) == false) && + !Minecraft::GetInstance()->isTutorial() && + ProfileManager.IsSignedInLive(i) && + !ProfileManager.IsGuest(i)) { + // If there is a sys ui displayed, we can't display the + // message box here, so ignore until we can + if (!ProfileManager.IsSystemUIDisplayed()) { + app.SetBanListCheck(i, true); + // 4J-PB - check if the level is in the banned level + // list get the unique save name and xuid from + // whoever is the host + INetworkPlayer* pHostPlayer = + g_NetworkManager.GetHostPlayer(); + PlayerUID xuid = pHostPlayer->GetUID(); - if (InputManager.ButtonPressed(i, - MINECRAFT_ACTION_INVENTORY)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_INVENTORY; - if (InputManager.ButtonPressed(i, MINECRAFT_ACTION_ACTION)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_ACTION; - if (InputManager.ButtonPressed(i, - MINECRAFT_ACTION_CRAFTING)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_CRAFTING; - if (InputManager.ButtonPressed( - i, MINECRAFT_ACTION_PAUSEMENU)) { - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_PAUSEMENU; - app.DebugPrintf( - "PAUSE PRESSED - ipad = %d, Storing press\n", i); -#if defined(ENABLE_JAVA_GUIS) - pauseGame(); -#endif + if (app.IsInBannedLevelList( + i, xuid, app.GetUniqueMapName())) { + // put up a message box asking if the player + // would like to unban this level + app.DebugPrintf("This level is banned\n"); + // set the app action to bring up the message + // box to give them the option to remove from + // the ban list or exit the level + app.SetAction(i, eAppAction_LevelInBanLevelList, + (void*)true); + } + } } - if (InputManager.ButtonPressed(i, MINECRAFT_ACTION_DROP)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_DROP; + } - // 4J-PB - If we're flying, the sneak needs to be held on to - // go down - if (localplayers[i]->abilities.flying) { - if (InputManager.ButtonDown( - i, MINECRAFT_ACTION_SNEAK_TOGGLE)) + if (!ProfileManager.IsSystemUIDisplayed() && + app.DLCInstallProcessCompleted() && + !app.DLCInstallPending() && + app.m_dlcManager.NeedsCorruptCheck()) { + app.m_dlcManager.checkForCorruptDLCAndAlert(); + } + + // When we go into the first loaded level, check if the console + // has active joypads that are not in the game, and bring up the + // quadrant display to remind them to press start (if the + // session has space) + if (level != nullptr && bFirstTimeIntoGame && + g_NetworkManager.SessionHasSpace()) { + // have a short delay before the display + if (iFirstTimeCountdown == 0) { + bFirstTimeIntoGame = false; + + if (app.IsLocalMultiplayerAvailable()) { + for (int i = 0; i < XUSER_MAX_COUNT; i++) { + if ((localplayers[i] == nullptr) && + InputManager.IsPadConnected(i)) { + if (!ui.PressStartPlaying(i)) { + ui.ShowPressStart(i); + } + } + } + } + } else + iFirstTimeCountdown--; + } + // 4J-PB - store any button toggles for the players, since the + // minecraft::tick may not be called if we're running fast, and + // a button press and release will be missed + + for (int i = 0; i < XUSER_MAX_COUNT; i++) { + if (localplayers[i]) { + // 4J-PB - add these to check for coming out of idle + if (InputManager.ButtonPressed(i, + MINECRAFT_ACTION_JUMP)) localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_SNEAK_TOGGLE; - } else { + 1LL << MINECRAFT_ACTION_JUMP; + if (InputManager.ButtonPressed(i, MINECRAFT_ACTION_USE)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_USE; + if (InputManager.ButtonPressed( - i, MINECRAFT_ACTION_SNEAK_TOGGLE)) + i, MINECRAFT_ACTION_INVENTORY)) localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_SNEAK_TOGGLE; - } - if (InputManager.ButtonPressed( - i, MINECRAFT_ACTION_RENDER_THIRD_PERSON)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_RENDER_THIRD_PERSON; - if (InputManager.ButtonPressed(i, - MINECRAFT_ACTION_GAME_INFO)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_GAME_INFO; + 1LL << MINECRAFT_ACTION_INVENTORY; + if (InputManager.ButtonPressed(i, + MINECRAFT_ACTION_ACTION)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_ACTION; + if (InputManager.ButtonPressed( + i, MINECRAFT_ACTION_CRAFTING)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_CRAFTING; + if (InputManager.ButtonPressed( + i, MINECRAFT_ACTION_PAUSEMENU)) { + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_PAUSEMENU; + app.DebugPrintf( + "PAUSE PRESSED - ipad = %d, Storing press\n", + i); +#if defined(ENABLE_JAVA_GUIS) + pauseGame(); +#endif + } + if (InputManager.ButtonPressed(i, + MINECRAFT_ACTION_DROP)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_DROP; + + // 4J-PB - If we're flying, the sneak needs to be held + // on to go down + if (localplayers[i]->abilities.flying) { + if (InputManager.ButtonDown( + i, MINECRAFT_ACTION_SNEAK_TOGGLE)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_SNEAK_TOGGLE; + } else { + if (InputManager.ButtonPressed( + i, MINECRAFT_ACTION_SNEAK_TOGGLE)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_SNEAK_TOGGLE; + } + if (InputManager.ButtonPressed( + i, MINECRAFT_ACTION_RENDER_THIRD_PERSON)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_RENDER_THIRD_PERSON; + if (InputManager.ButtonPressed( + i, MINECRAFT_ACTION_GAME_INFO)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_GAME_INFO; #if !defined(_FINAL_BUILD) - if (app.DebugSettingsOn() && app.GetUseDPadForDebug()) { - localplayers[i]->ullDpad_last = 0; - localplayers[i]->ullDpad_this = 0; - localplayers[i]->ullDpad_filtered = 0; - if (InputManager.ButtonPressed( - i, MINECRAFT_ACTION_DPAD_RIGHT)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_CHANGE_SKIN; - if (InputManager.ButtonPressed( - i, MINECRAFT_ACTION_DPAD_UP)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_FLY_TOGGLE; - if (InputManager.ButtonPressed( - i, MINECRAFT_ACTION_DPAD_DOWN)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_RENDER_DEBUG; - if (InputManager.ButtonPressed( - i, MINECRAFT_ACTION_DPAD_LEFT)) - localplayers[i]->ullButtonsPressed |= - 1LL << MINECRAFT_ACTION_SPAWN_CREEPER; - } else -#endif - { - // Movement on DPAD is stored ulimately into - // ullDpad_filtered - this ignores any diagonals - // pressed, instead reporting the last single direction - // - otherwise we get loads of accidental diagonal - // movements - - localplayers[i]->ullDpad_this = 0; - int dirCount = 0; - - if (InputManager.ButtonDown( - i, MINECRAFT_ACTION_DPAD_LEFT)) { - localplayers[i]->ullDpad_this |= - 1LL << MINECRAFT_ACTION_DPAD_LEFT; - dirCount++; - } - if (InputManager.ButtonDown( - i, MINECRAFT_ACTION_DPAD_RIGHT)) { - localplayers[i]->ullDpad_this |= - 1LL << MINECRAFT_ACTION_DPAD_RIGHT; - dirCount++; - } - if (InputManager.ButtonDown(i, - MINECRAFT_ACTION_DPAD_UP)) { - localplayers[i]->ullDpad_this |= - 1LL << MINECRAFT_ACTION_DPAD_UP; - dirCount++; - } - if (InputManager.ButtonDown( - i, MINECRAFT_ACTION_DPAD_DOWN)) { - localplayers[i]->ullDpad_this |= - 1LL << MINECRAFT_ACTION_DPAD_DOWN; - dirCount++; - } - - if (dirCount <= 1) { - localplayers[i]->ullDpad_last = - localplayers[i]->ullDpad_this; - localplayers[i]->ullDpad_filtered = - localplayers[i]->ullDpad_this; - } else { - localplayers[i]->ullDpad_filtered = - localplayers[i]->ullDpad_last; - } - } - - // for the opacity timer - if (InputManager.ButtonPressed( - i, MINECRAFT_ACTION_LEFT_SCROLL) || - InputManager.ButtonPressed( - i, MINECRAFT_ACTION_RIGHT_SCROLL)) - // InputManager.ButtonPressed(i, MINECRAFT_ACTION_USE) || - // InputManager.ButtonPressed(i, MINECRAFT_ACTION_ACTION)) - { - app.SetOpacityTimer(i); - } - } else { - // 4J Stu - This doesn't make any sense with the way we - // handle XboxOne users - // did we just get input from a player who doesn't exist? - // They'll be wanting to join the game then - bool tryJoin = !pause && - !ui.IsIgnorePlayerJoinMenuDisplayed( - ProfileManager.GetPrimaryPad()) && - g_NetworkManager.SessionHasSpace() && - RenderManager.IsHiDef() && - InputManager.ButtonPressed(i); - if (tryJoin) { - if (!ui.PressStartPlaying(i)) { - ui.ShowPressStart(i); - } else { - // did we just get input from a player who doesn't - // exist? They'll be wanting to join the game then + if (app.DebugSettingsOn() && app.GetUseDPadForDebug()) { + localplayers[i]->ullDpad_last = 0; + localplayers[i]->ullDpad_this = 0; + localplayers[i]->ullDpad_filtered = 0; if (InputManager.ButtonPressed( - i, MINECRAFT_ACTION_PAUSEMENU)) { - // Let them join + i, MINECRAFT_ACTION_DPAD_RIGHT)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_CHANGE_SKIN; + if (InputManager.ButtonPressed( + i, MINECRAFT_ACTION_DPAD_UP)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_FLY_TOGGLE; + if (InputManager.ButtonPressed( + i, MINECRAFT_ACTION_DPAD_DOWN)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_RENDER_DEBUG; + if (InputManager.ButtonPressed( + i, MINECRAFT_ACTION_DPAD_LEFT)) + localplayers[i]->ullButtonsPressed |= + 1LL << MINECRAFT_ACTION_SPAWN_CREEPER; + } else +#endif + { + // Movement on DPAD is stored ulimately into + // ullDpad_filtered - this ignores any diagonals + // pressed, instead reporting the last single + // direction + // - otherwise we get loads of accidental diagonal + // movements - // are they signed in? - if (ProfileManager.IsSignedIn(i)) { - // if this is a local game, then the player - // just needs to be signed in - if (g_NetworkManager.IsLocalGame() || - (ProfileManager.IsSignedInLive(i) && - ProfileManager - .AllowedToPlayMultiplayer(i))) { - if (level->isClientSide) { - bool success = addLocalPlayer(i); + localplayers[i]->ullDpad_this = 0; + int dirCount = 0; - if (!success) { + if (InputManager.ButtonDown( + i, MINECRAFT_ACTION_DPAD_LEFT)) { + localplayers[i]->ullDpad_this |= + 1LL << MINECRAFT_ACTION_DPAD_LEFT; + dirCount++; + } + if (InputManager.ButtonDown( + i, MINECRAFT_ACTION_DPAD_RIGHT)) { + localplayers[i]->ullDpad_this |= + 1LL << MINECRAFT_ACTION_DPAD_RIGHT; + dirCount++; + } + if (InputManager.ButtonDown( + i, MINECRAFT_ACTION_DPAD_UP)) { + localplayers[i]->ullDpad_this |= + 1LL << MINECRAFT_ACTION_DPAD_UP; + dirCount++; + } + if (InputManager.ButtonDown( + i, MINECRAFT_ACTION_DPAD_DOWN)) { + localplayers[i]->ullDpad_this |= + 1LL << MINECRAFT_ACTION_DPAD_DOWN; + dirCount++; + } + + if (dirCount <= 1) { + localplayers[i]->ullDpad_last = + localplayers[i]->ullDpad_this; + localplayers[i]->ullDpad_filtered = + localplayers[i]->ullDpad_this; + } else { + localplayers[i]->ullDpad_filtered = + localplayers[i]->ullDpad_last; + } + } + + // for the opacity timer + if (InputManager.ButtonPressed( + i, MINECRAFT_ACTION_LEFT_SCROLL) || + InputManager.ButtonPressed( + i, MINECRAFT_ACTION_RIGHT_SCROLL)) + // InputManager.ButtonPressed(i, MINECRAFT_ACTION_USE) + // || InputManager.ButtonPressed(i, + // MINECRAFT_ACTION_ACTION)) + { + app.SetOpacityTimer(i); + } + } else { + // 4J Stu - This doesn't make any sense with the way we + // handle XboxOne users + // did we just get input from a player who doesn't + // exist? They'll be wanting to join the game then + bool tryJoin = !pause && + !ui.IsIgnorePlayerJoinMenuDisplayed( + ProfileManager.GetPrimaryPad()) && + g_NetworkManager.SessionHasSpace() && + RenderManager.IsHiDef() && + InputManager.ButtonPressed(i); + if (tryJoin) { + if (!ui.PressStartPlaying(i)) { + ui.ShowPressStart(i); + } else { + // did we just get input from a player who + // doesn't exist? They'll be wanting to join the + // game then + if (InputManager.ButtonPressed( + i, MINECRAFT_ACTION_PAUSEMENU)) { + // Let them join + + // are they signed in? + if (ProfileManager.IsSignedIn(i)) { + // if this is a local game, then the + // player just needs to be signed in + if (g_NetworkManager.IsLocalGame() || + (ProfileManager.IsSignedInLive(i) && + ProfileManager + .AllowedToPlayMultiplayer( + i))) { + if (level->isClientSide) { + bool success = + addLocalPlayer(i); + + if (!success) { + app.DebugPrintf( + "Bringing up the sign " + "in " + "ui\n"); + ProfileManager.RequestSignInUI( + false, + g_NetworkManager + .IsLocalGame(), + true, false, true, + &Minecraft:: + InGame_SignInReturned, + this, i); + } else { + } + } else { + // create the localplayer + std::shared_ptr player = + localplayers[i]; + if (player == nullptr) { + player = + createExtraLocalPlayer( + i, + (convStringToWstring( + ProfileManager + .GetGamertag( + i))) + .c_str(), + i, + level->dimension + ->id); + } + } + } else { + if (ProfileManager.IsSignedInLive( + ProfileManager + .GetPrimaryPad()) && + !ProfileManager + .AllowedToPlayMultiplayer( + i)) { + ProfileManager + .RequestConvertOfflineToGuestUI( + &Minecraft:: + InGame_SignInReturned, + this, i); + // 4J Stu - Don't allow + // converting to guests as we + // don't allow any guest sign-in + // while in the game Fix for + // #66516 - TCR #124: MPS Guest + // Support ; #001: BAS Game + // Stability: TU8: The game + // crashes when second Guest + // signs-in on console which + // takes part in Xbox LIVE + // multiplayer session. + // ProfileManager.RequestConvertOfflineToGuestUI( + // &Minecraft::InGame_SignInReturned, + // this,i); + + ui.HidePressStart(); + { + uint32_t uiIDA[1]; + uiIDA[0] = IDS_CONFIRM_OK; + ui.RequestErrorMessage( + IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, + IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, + uiIDA, 1, i); + } + } + // else + { + // player not signed in to live + // bring up the sign in dialog app.DebugPrintf( "Bringing up the sign in " "ui\n"); @@ -1348,391 +1439,336 @@ void Minecraft::run_middle() { &Minecraft:: InGame_SignInReturned, this, i); - } else { - } - } else { - // create the localplayer - std::shared_ptr player = - localplayers[i]; - if (player == nullptr) { - player = createExtraLocalPlayer( - i, - (convStringToWstring( - ProfileManager - .GetGamertag(i))) - .c_str(), - i, level->dimension->id); } } } else { - if (ProfileManager.IsSignedInLive( - ProfileManager - .GetPrimaryPad()) && - !ProfileManager - .AllowedToPlayMultiplayer(i)) { - ProfileManager - .RequestConvertOfflineToGuestUI( - &Minecraft:: - InGame_SignInReturned, - this, i); - // 4J Stu - Don't allow converting - // to guests as we don't allow any - // guest sign-in while in the game - // Fix for #66516 - TCR #124: MPS - // Guest Support ; #001: BAS Game - // Stability: TU8: The game crashes - // when second Guest signs-in on - // console which takes part in Xbox - // LIVE multiplayer session. - // ProfileManager.RequestConvertOfflineToGuestUI( - // &Minecraft::InGame_SignInReturned, - // this,i); - - ui.HidePressStart(); - { - uint32_t uiIDA[1]; - uiIDA[0] = IDS_CONFIRM_OK; - ui.RequestErrorMessage( - IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, - IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, - uiIDA, 1, i); - } - } - // else - { - // player not signed in to live - // bring up the sign in dialog - app.DebugPrintf( - "Bringing up the sign in ui\n"); - ProfileManager.RequestSignInUI( - false, - g_NetworkManager.IsLocalGame(), - true, false, true, - &Minecraft:: - InGame_SignInReturned, - this, i); - } + // bring up the sign in dialog + app.DebugPrintf( + "Bringing up the sign in ui\n"); + ProfileManager.RequestSignInUI( + false, + g_NetworkManager.IsLocalGame(), + true, false, true, + &Minecraft::InGame_SignInReturned, + this, i); } - } else { - // bring up the sign in dialog - app.DebugPrintf( - "Bringing up the sign in ui\n"); - ProfileManager.RequestSignInUI( - false, g_NetworkManager.IsLocalGame(), - true, false, true, - &Minecraft::InGame_SignInReturned, this, - i); } } } } } - } - if (pause && level != nullptr) { - float lastA = timer->a; - timer->advanceTime(); - timer->a = lastA; - } else { - timer->advanceTime(); - } - - // int64_t beforeTickTime = System::nanoTime(); - for (int i = 0; i < timer->ticks; i++) { - bool bLastTimerTick = (i == (timer->ticks - 1)); - // 4J-PB - the tick here can run more than once, and this is a - // problem for our input, which would see the a key press twice - // with the same time - let's tick the inputmanager again - if (i != 0) { - InputManager.Tick(); - app.HandleButtonPresses(); + if (pause && level != nullptr) { + float lastA = timer->a; + timer->advanceTime(); + timer->a = lastA; + } else { + timer->advanceTime(); } - ticks++; - // try { // 4J - try/catch removed - bool bFirst = true; - for (int idx = 0; idx < XUSER_MAX_COUNT; idx++) { - // 4J - If we are waiting for this connection to do - // something, then tick it here. This replaces many of the - // original Java scenes which would tick the connection - // while showing that scene - if (m_pendingLocalConnections[idx] != nullptr) { - m_pendingLocalConnections[idx]->tick(); + // int64_t beforeTickTime = System::nanoTime(); + for (int i = 0; i < timer->ticks; i++) { + bool bLastTimerTick = (i == (timer->ticks - 1)); + // 4J-PB - the tick here can run more than once, and this is + // a problem for our input, which would see the a key press + // twice with the same time - let's tick the inputmanager + // again + if (i != 0) { + InputManager.Tick(); + app.HandleButtonPresses(); } - // reset the player inactive tick - if (localplayers[idx] != nullptr) { - // any input received? - if ((localplayers[idx]->ullButtonsPressed != 0) || - InputManager.GetJoypadStick_LX(idx, false) != - 0.0f || - InputManager.GetJoypadStick_LY(idx, false) != - 0.0f || - InputManager.GetJoypadStick_RX(idx, false) != - 0.0f || - InputManager.GetJoypadStick_RY(idx, false) != - 0.0f) { - localplayers[idx]->ResetInactiveTicks(); - } else { - localplayers[idx]->IncrementInactiveTicks(); + ticks++; + // try { // 4J - try/catch removed + bool bFirst = true; + for (int idx = 0; idx < XUSER_MAX_COUNT; idx++) { + // 4J - If we are waiting for this connection to do + // something, then tick it here. This replaces many of + // the original Java scenes which would tick the + // connection while showing that scene + if (m_pendingLocalConnections[idx] != nullptr) { + m_pendingLocalConnections[idx]->tick(); } - if (localplayers[idx]->GetInactiveTicks() > 200) { - if (!localplayers[idx]->isIdle() && - localplayers[idx]->onGround) { - localplayers[idx]->setIsIdle(true); + // reset the player inactive tick + if (localplayers[idx] != nullptr) { + // any input received? + if ((localplayers[idx]->ullButtonsPressed != 0) || + InputManager.GetJoypadStick_LX(idx, false) != + 0.0f || + InputManager.GetJoypadStick_LY(idx, false) != + 0.0f || + InputManager.GetJoypadStick_RX(idx, false) != + 0.0f || + InputManager.GetJoypadStick_RY(idx, false) != + 0.0f) { + localplayers[idx]->ResetInactiveTicks(); + } else { + localplayers[idx]->IncrementInactiveTicks(); } - } else { - if (localplayers[idx]->isIdle()) { - localplayers[idx]->setIsIdle(false); + + if (localplayers[idx]->GetInactiveTicks() > 200) { + if (!localplayers[idx]->isIdle() && + localplayers[idx]->onGround) { + localplayers[idx]->setIsIdle(true); + } + } else { + if (localplayers[idx]->isIdle()) { + localplayers[idx]->setIsIdle(false); + } + } + } + + if (setLocalPlayerIdx(idx)) { + tick(bFirst, bLastTimerTick); + bFirst = false; + // clear the stored button downs since the tick for + // this player will now have actioned them + player->ullButtonsPressed = 0LL; + } else if (screen != nullptr) { + screen->updateEvents(); + // 4jcraft: this fixes the title screen panorama + // running faster than it should + if (!idx) { + screen->tick(); } } } - if (setLocalPlayerIdx(idx)) { - tick(bFirst, bLastTimerTick); - bFirst = false; - // clear the stored button downs since the tick for this - // player will now have actioned them - player->ullButtonsPressed = 0LL; - } else if (screen != nullptr) { - screen->updateEvents(); - // 4jcraft: this fixes the title screen panorama running - // faster than it should - if (!idx) { - screen->tick(); + ui.HandleGameTick(); + + setLocalPlayerIdx(ProfileManager.GetPrimaryPad()); + + // 4J - added - now do the equivalent of level::animateTick, + // but taking into account the positions of all our players + + for (int l = 0; l < levels.length; l++) { + if (levels[l]) { + levels[l]->animateTickDoWork(); } } + + // } catch (LevelConflictException e) { + // this.level = null; + // setLevel(null); + // setScreen(new LevelConflictScreen()); + // } + // SparseLightStorage::tick(); + // // 4J added + // CompressedTileStorage::tick(); // 4J added + // SparseDataStorage::tick(); + // // 4J added } + // int64_t tickDuraction = System::nanoTime() - beforeTickTime; + MemSect(31); + checkGlError(L"Pre render"); + MemSect(0); - ui.HandleGameTick(); + TileRenderer::fancy = options->fancyGraphics; - setLocalPlayerIdx(ProfileManager.GetPrimaryPad()); + // if (pause) timer.a = 1; - // 4J - added - now do the equivalent of level::animateTick, but - // taking into account the positions of all our players + PIXBeginNamedEvent(0, "Sound engine update"); + soundEngine->tick((std::shared_ptr*)localplayers, + timer->a); + PIXEndNamedEvent(); - for (int l = 0; l < levels.length; l++) { - if (levels[l]) { - levels[l]->animateTickDoWork(); - } - } + PIXBeginNamedEvent(0, "Light update"); - // } catch (LevelConflictException e) { - // this.level = null; - // setLevel(null); - // setScreen(new LevelConflictScreen()); - // } - // SparseLightStorage::tick(); - // // 4J added - // CompressedTileStorage::tick(); // 4J added - // SparseDataStorage::tick(); - // // 4J added - } - // int64_t tickDuraction = System::nanoTime() - beforeTickTime; - MemSect(31); - checkGlError(L"Pre render"); - MemSect(0); + // if (level != nullptr) level->updateLights(); + glEnable(GL_TEXTURE_2D); - TileRenderer::fancy = options->fancyGraphics; + PIXEndNamedEvent(); - // if (pause) timer.a = 1; + // if (!Keyboard::isKeyDown(Keyboard.KEY_F7)) + // Display.update(); // 4J - removed - PIXBeginNamedEvent(0, "Sound engine update"); - soundEngine->tick((std::shared_ptr*)localplayers, timer->a); - PIXEndNamedEvent(); + // 4J-PB - changing this to be per player + // if (player != nullptr && player->isInWall()) + // options->thirdPersonView = false; + if (player != nullptr && player->isInWall()) + player->SetThirdPersonView(0); - PIXBeginNamedEvent(0, "Light update"); + if (!noRender) { + bool bFirst = true; + int iPrimaryPad = ProfileManager.GetPrimaryPad(); + for (int i = 0; i < XUSER_MAX_COUNT; i++) { + if (setLocalPlayerIdx(i)) { + PIXBeginNamedEvent(0, "Game render player idx %d", + i); + RenderManager.StateSetViewport( + (C4JRender::eViewportType) + player->m_iScreenSection); + gameRenderer->render(timer->a, bFirst); + bFirst = false; + PIXEndNamedEvent(); - // if (level != nullptr) level->updateLights(); - glEnable(GL_TEXTURE_2D); - - PIXEndNamedEvent(); - - // if (!Keyboard::isKeyDown(Keyboard.KEY_F7)) - // Display.update(); // 4J - removed - - // 4J-PB - changing this to be per player - // if (player != nullptr && player->isInWall()) - // options->thirdPersonView = false; - if (player != nullptr && player->isInWall()) - player->SetThirdPersonView(0); - - if (!noRender) { - bool bFirst = true; - int iPrimaryPad = ProfileManager.GetPrimaryPad(); - for (int i = 0; i < XUSER_MAX_COUNT; i++) { - if (setLocalPlayerIdx(i)) { - PIXBeginNamedEvent(0, "Game render player idx %d", i); - RenderManager.StateSetViewport( - (C4JRender::eViewportType)player->m_iScreenSection); - gameRenderer->render(timer->a, bFirst); - bFirst = false; - PIXEndNamedEvent(); - - if (i == iPrimaryPad) { - // check to see if we need to capture a screenshot - // for the save game thumbnail - switch (app.GetXuiAction(i)) { - case eAppAction_ExitWorldCapturedThumbnail: - case eAppAction_SaveGameCapturedThumbnail: - case eAppAction_AutosaveSaveGameCapturedThumbnail: - // capture the save thumbnail - app.CaptureSaveThumbnail(); - break; - default: - break; + if (i == iPrimaryPad) { + // check to see if we need to capture a + // screenshot for the save game thumbnail + switch (app.GetXuiAction(i)) { + case eAppAction_ExitWorldCapturedThumbnail: + case eAppAction_SaveGameCapturedThumbnail: + case eAppAction_AutosaveSaveGameCapturedThumbnail: + // capture the save thumbnail + app.CaptureSaveThumbnail(); + break; + default: + break; + } } } } - } #if !defined(_ENABLEIGGY) - // On Linux, Iggy Flash UI is not available. If no players were - // rendered (menu / title-screen state), call GameRenderer - // directly so mc->screen draws. - if (bFirst) { - localPlayerIdx = 0; + // On Linux, Iggy Flash UI is not available. If no players + // were rendered (menu / title-screen state), call + // GameRenderer directly so mc->screen draws. + if (bFirst) { + localPlayerIdx = 0; + RenderManager.StateSetViewport( + C4JRender::VIEWPORT_TYPE_FULLSCREEN); + gameRenderer->render(timer->a, true); + } +#endif + + // If there's an unoccupied quadrant, then clear that to + // black + if (unoccupiedQuadrant > -1) { + // render a logo + RenderManager.StateSetViewport(( + C4JRender:: + eViewportType)(C4JRender:: + VIEWPORT_TYPE_QUADRANT_TOP_LEFT + + unoccupiedQuadrant)); + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + ui.SetEmptyQuadrantLogo( + C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT + + unoccupiedQuadrant); + } + setLocalPlayerIdx(iPrimaryPad); RenderManager.StateSetViewport( C4JRender::VIEWPORT_TYPE_FULLSCREEN); - gameRenderer->render(timer->a, true); } -#endif + glFlush(); - // If there's an unoccupied quadrant, then clear that to black - if (unoccupiedQuadrant > -1) { - // render a logo - RenderManager.StateSetViewport(( - C4JRender:: - eViewportType)(C4JRender:: - VIEWPORT_TYPE_QUADRANT_TOP_LEFT + - unoccupiedQuadrant)); - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); - - ui.SetEmptyQuadrantLogo( - C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT + - unoccupiedQuadrant); + /* 4J - removed + if (!Display::isActive()) + { + if (fullscreen) + { + this->toggleFullScreen(); } - setLocalPlayerIdx(iPrimaryPad); - RenderManager.StateSetViewport( - C4JRender::VIEWPORT_TYPE_FULLSCREEN); - } - glFlush(); - - /* 4J - removed - if (!Display::isActive()) - { - if (fullscreen) - { - this->toggleFullScreen(); - } - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - */ + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + */ #if PACKET_ENABLE_STAT_TRACKING - Packet::updatePacketStatsPIX(); + Packet::updatePacketStatsPIX(); #endif - if (options->renderDebug) { - // renderFpsMeter(tickDuraction); + if (options->renderDebug) { + // renderFpsMeter(tickDuraction); #if DEBUG_RENDER_SHOWS_PACKETS - // To show data for only one packet type - // Packet::renderPacketStats(31); + // To show data for only one packet type + // Packet::renderPacketStats(31); - // To show data for all packet types selected as being - // renderable in the Packet:static_ctor call to Packet::map - Packet::renderAllPacketStats(); + // To show data for all packet types selected as being + // renderable in the Packet:static_ctor call to Packet::map + Packet::renderAllPacketStats(); #else - // To show the size of the QNet queue in bytes and messages - g_NetworkManager.renderQueueMeter(); + // To show the size of the QNet queue in bytes and messages + g_NetworkManager.renderQueueMeter(); #endif - } else { - lastTimer = System::nanoTime(); - } + } else { + lastTimer = System::nanoTime(); + } - achievementPopup->render(); + achievementPopup->render(); - PIXBeginNamedEvent(0, "Sleeping"); - std::this_thread::yield(); // 4jcraft added now that we have - // portable thread yield. - // std::this_thread::sleep_for( - // std::chrono::milliseconds(0)); // 4J - was Thread.yield()) - PIXEndNamedEvent(); + PIXBeginNamedEvent(0, "Sleeping"); + std::this_thread::yield(); // 4jcraft added now that we have + // portable thread yield. + // std::this_thread::sleep_for( + // std::chrono::milliseconds(0)); // 4J - was + // Thread.yield()) + PIXEndNamedEvent(); - // if (Keyboard::isKeyDown(Keyboard::KEY_F7)) - // Display.update(); // 4J - removed condition - PIXBeginNamedEvent(0, "Display update"); - Display::update(); - PIXEndNamedEvent(); + // if (Keyboard::isKeyDown(Keyboard::KEY_F7)) + // Display.update(); // 4J - removed condition + PIXBeginNamedEvent(0, "Display update"); + Display::update(); + PIXEndNamedEvent(); - // checkScreenshot(); // 4J - removed + // checkScreenshot(); // 4J - removed - /* 4J - removed - if (parent != nullptr && !fullscreen) - { - if (parent.getWidth() != width || parent.getHeight() != height) - { - width = parent.getWidth(); - height = parent.getHeight(); - if (width <= 0) width = 1; - if (height <= 0) height = 1; + /* 4J - removed + if (parent != nullptr && !fullscreen) + { + if (parent.getWidth() != width || parent.getHeight() != height) + { + width = parent.getWidth(); + height = parent.getHeight(); + if (width <= 0) width = 1; + if (height <= 0) height = 1; - resize(width, height); - } - } - */ - MemSect(31); - checkGlError(L"Post render"); - MemSect(0); - frames++; - // pause = !isClientSide() && screen != nullptr && - // screen->isPauseScreen(); + resize(width, height); + } + } + */ + MemSect(31); + checkGlError(L"Post render"); + MemSect(0); + frames++; + // pause = !isClientSide() && screen != nullptr && + // screen->isPauseScreen(); #if defined(ENABLE_JAVA_GUIS) - pause = g_NetworkManager.IsLocalGame() && - g_NetworkManager.GetPlayerCount() == 1 && - screen != nullptr && screen->isPauseScreen(); + pause = g_NetworkManager.IsLocalGame() && + g_NetworkManager.GetPlayerCount() == 1 && + screen != nullptr && screen->isPauseScreen(); #else - pause = app.IsAppPaused(); + pause = app.IsAppPaused(); #endif #if !defined(_CONTENT_PACKAGE) - while (System::nanoTime() >= lastTime + 1000000000) { - MemSect(31); - fpsString = _toString(frames) + L" fps, " + - _toString(Chunk::updates) + L" chunk updates"; - MemSect(0); - Chunk::updates = 0; - lastTime += 1000000000; - frames = 0; - } + while (System::nanoTime() >= lastTime + 1000000000) { + MemSect(31); + fpsString = _toString(frames) + L" fps, " + + _toString(Chunk::updates) + + L" chunk updates"; + MemSect(0); + Chunk::updates = 0; + lastTime += 1000000000; + frames = 0; + } #endif + /* + } catch (LevelConflictException e) { + this.level = null; + setLevel(null); + setScreen(new LevelConflictScreen()); + } catch (OutOfMemoryError e) { + emergencySave(); + setScreen(new OutOfMemoryScreen()); + System.gc(); + } + */ + } /* - } catch (LevelConflictException e) { - this.level = null; - setLevel(null); - setScreen(new LevelConflictScreen()); - } catch (OutOfMemoryError e) { + } catch (StopGameException e) { + } catch (Throwable e) { emergencySave(); - setScreen(new OutOfMemoryScreen()); - System.gc(); + e.printStackTrace(); + crash(new CrashReport("Unexpected error", e)); + } finally { + destroy(); } */ } - /* - } catch (StopGameException e) { - } catch (Throwable e) { - emergencySave(); - e.printStackTrace(); - crash(new CrashReport("Unexpected error", e)); - } finally { - destroy(); - } - */ - } - } // lock_guard scope + } // lock_guard scope } void Minecraft::run_end() { destroy(); } diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index c5fb9936a..de1e9fda2 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -265,8 +265,9 @@ int MinecraftServer::runPostUpdate(void* lpParam) { { std::unique_lock lock(server->m_postProcessCS); int maxRequests = server->m_postProcessRequests.size(); - while (server->m_postProcessRequests.size() && - ShutdownManager::ShouldRun(ShutdownManager::ePostProcessThread)) { + while ( + server->m_postProcessRequests.size() && + ShutdownManager::ShouldRun(ShutdownManager::ePostProcessThread)) { MinecraftServer::postProcessRequest request = server->m_postProcessRequests.back(); server->m_postProcessRequests.pop_back(); @@ -287,9 +288,10 @@ int MinecraftServer::runPostUpdate(void* lpParam) { void MinecraftServer::addPostProcessRequest(ChunkSource* chunkSource, int x, int z) { - { std::lock_guard lock(m_postProcessCS); - m_postProcessRequests.push_back( - MinecraftServer::postProcessRequest(x, z, chunkSource)); + { + std::lock_guard lock(m_postProcessCS); + m_postProcessRequests.push_back( + MinecraftServer::postProcessRequest(x, z, chunkSource)); } } @@ -298,16 +300,17 @@ void MinecraftServer::postProcessTerminate(ProgressRenderer* mcprogress) { size_t postProcessItemCount = 0; size_t postProcessItemRemaining = 0; - { std::lock_guard lock(server->m_postProcessCS); - postProcessItemCount = server->m_postProcessRequests.size(); + { + std::lock_guard lock(server->m_postProcessCS); + postProcessItemCount = server->m_postProcessRequests.size(); } do { status = m_postUpdateThread->waitForCompletion(50); if (status == C4JThread::WaitResult::Timeout) { - { std::lock_guard lock(server->m_postProcessCS); - postProcessItemRemaining = - server->m_postProcessRequests.size(); + { + std::lock_guard lock(server->m_postProcessCS); + postProcessItemRemaining = server->m_postProcessRequests.size(); } if (postProcessItemCount) { diff --git a/Minecraft.Client/Network/MultiPlayerChunkCache.cpp b/Minecraft.Client/Network/MultiPlayerChunkCache.cpp index 984175ecb..960b231be 100644 --- a/Minecraft.Client/Network/MultiPlayerChunkCache.cpp +++ b/Minecraft.Client/Network/MultiPlayerChunkCache.cpp @@ -155,47 +155,51 @@ LevelChunk* MultiPlayerChunkCache::create(int x, int z) { LevelChunk* lastChunk = chunk; if (chunk == nullptr) { - { std::unique_lock lock(m_csLoadCreate); - - // LevelChunk *chunk; - if (g_NetworkManager.IsHost()) // force here to disable sharing of data { - // 4J-JEV: We are about to use shared data, abort if the server is - // stopped and the data is deleted. - if (MinecraftServer::getInstance()->serverHalted()) return nullptr; + std::unique_lock lock(m_csLoadCreate); - // If we're the host, then don't create the chunk, share data from - // the server's copy + // LevelChunk *chunk; + if (g_NetworkManager + .IsHost()) // force here to disable sharing of data + { + // 4J-JEV: We are about to use shared data, abort if the server + // is stopped and the data is deleted. + if (MinecraftServer::getInstance()->serverHalted()) + return nullptr; + + // If we're the host, then don't create the chunk, share data + // from the server's copy #ifdef _LARGE_WORLDS - LevelChunk* serverChunk = - MinecraftServer::getInstance() - ->getLevel(level->dimension->id) - ->cache->getChunkLoadedOrUnloaded(x, z); + LevelChunk* serverChunk = + MinecraftServer::getInstance() + ->getLevel(level->dimension->id) + ->cache->getChunkLoadedOrUnloaded(x, z); #else - LevelChunk* serverChunk = MinecraftServer::getInstance() - ->getLevel(level->dimension->id) - ->cache->getChunk(x, z); + LevelChunk* serverChunk = MinecraftServer::getInstance() + ->getLevel(level->dimension->id) + ->cache->getChunk(x, z); #endif - chunk = new LevelChunk(level, x, z, serverChunk); - // Let renderer know that this chunk has been created - it might - // have made render data from the EmptyChunk if it got to a chunk - // before the server sent it - level->setTilesDirty(x * 16, 0, z * 16, x * 16 + 15, 127, - z * 16 + 15); - hasData[idx] = true; - } else { - // Passing an empty array into the LevelChunk ctor, which it now - // detects and sets up the chunk as compressed & empty - byteArray bytes; + chunk = new LevelChunk(level, x, z, serverChunk); + // Let renderer know that this chunk has been created - it might + // have made render data from the EmptyChunk if it got to a + // chunk before the server sent it + level->setTilesDirty(x * 16, 0, z * 16, x * 16 + 15, 127, + z * 16 + 15); + hasData[idx] = true; + } else { + // Passing an empty array into the LevelChunk ctor, which it now + // detects and sets up the chunk as compressed & empty + byteArray bytes; - chunk = new LevelChunk(level, bytes, x, z); + chunk = new LevelChunk(level, bytes, x, z); - // 4J - changed to use new methods for lighting - chunk->setSkyLightDataAllBright(); - // Arrays::fill(chunk->skyLight->data, (byte) 255); - } + // 4J - changed to use new methods for lighting + chunk->setSkyLightDataAllBright(); + // Arrays::fill(chunk->skyLight->data, + //(byte) 255); + } - chunk->loaded = true; + chunk->loaded = true; } #if (defined _WIN64 || defined __LP64__) @@ -216,8 +220,9 @@ LevelChunk* MultiPlayerChunkCache::create(int x, int z) { } // Successfully updated the cache - { std::lock_guard lock(m_csLoadCreate); - loadedChunkList.push_back(chunk); + { + std::lock_guard lock(m_csLoadCreate); + loadedChunkList.push_back(chunk); } } else { // Something else must have updated the cache. Return that chunk and @@ -278,8 +283,9 @@ void MultiPlayerChunkCache::recreateLogicStructuresForChunk(int chunkX, std::wstring MultiPlayerChunkCache::gatherStats() { int size; - { std::lock_guard lock(m_csLoadCreate); - size = (int)loadedChunkList.size(); + { + std::lock_guard lock(m_csLoadCreate); + size = (int)loadedChunkList.size(); } return L"MultiplayerChunkCache: " + _toString(size); } diff --git a/Minecraft.Client/Network/PlayerConnection.cpp b/Minecraft.Client/Network/PlayerConnection.cpp index b9fec8180..eabe55c1f 100644 --- a/Minecraft.Client/Network/PlayerConnection.cpp +++ b/Minecraft.Client/Network/PlayerConnection.cpp @@ -69,9 +69,7 @@ PlayerConnection::PlayerConnection(MinecraftServer* server, app.GetGameHostOption(eGameHostOption_Gamertags) != 0 ? true : false); } -PlayerConnection::~PlayerConnection() { - delete connection; -} +PlayerConnection::~PlayerConnection() { delete connection; } void PlayerConnection::tick() { if (done) return; diff --git a/Minecraft.Client/Network/PlayerList.cpp b/Minecraft.Client/Network/PlayerList.cpp index 59a1ca273..6ad051886 100644 --- a/Minecraft.Client/Network/PlayerList.cpp +++ b/Minecraft.Client/Network/PlayerList.cpp @@ -48,7 +48,6 @@ PlayerList::PlayerList(MinecraftServer* server) { maxPlayers = server->settings->getInt(L"max-players", 20); doWhiteList = false; - } PlayerList::~PlayerList() { @@ -59,7 +58,6 @@ PlayerList::~PlayerList() { // back to this player (*it)->gameMode = nullptr; } - } void PlayerList::placeNewPlayer(Connection* connection, @@ -991,73 +989,76 @@ void PlayerList::tick() { } } - { std::lock_guard lock(m_closePlayersCS); - while (!m_smallIdsToClose.empty()) { - std::uint8_t smallId = m_smallIdsToClose.front(); - m_smallIdsToClose.pop_front(); + { + std::lock_guard lock(m_closePlayersCS); + while (!m_smallIdsToClose.empty()) { + std::uint8_t smallId = m_smallIdsToClose.front(); + m_smallIdsToClose.pop_front(); - std::shared_ptr player = nullptr; + std::shared_ptr player = nullptr; - for (unsigned int i = 0; i < players.size(); i++) { - std::shared_ptr p = players.at(i); - // 4J Stu - May be being a bit overprotective with all the nullptr - // checks, but adding late in TU7 so want to be safe - if (p != nullptr && p->connection != nullptr && - p->connection->connection != nullptr && - p->connection->connection->getSocket() != nullptr && - p->connection->connection->getSocket()->getSmallId() == - smallId) { - player = p; - break; + for (unsigned int i = 0; i < players.size(); i++) { + std::shared_ptr p = players.at(i); + // 4J Stu - May be being a bit overprotective with all the + // nullptr checks, but adding late in TU7 so want to be safe + if (p != nullptr && p->connection != nullptr && + p->connection->connection != nullptr && + p->connection->connection->getSocket() != nullptr && + p->connection->connection->getSocket()->getSmallId() == + smallId) { + player = p; + break; + } + } + + if (player != nullptr) { + player->connection->disconnect( + DisconnectPacket::eDisconnect_Closed); } } - - if (player != nullptr) { - player->connection->disconnect( - DisconnectPacket::eDisconnect_Closed); - } - } } - { std::lock_guard lock(m_kickPlayersCS); - while (!m_smallIdsToKick.empty()) { - std::uint8_t smallId = m_smallIdsToKick.front(); - m_smallIdsToKick.pop_front(); - INetworkPlayer* selectedPlayer = - g_NetworkManager.GetPlayerBySmallId(smallId); - if (selectedPlayer != nullptr) { - if (selectedPlayer->IsLocal() != true) { - // #if 0 - PlayerUID xuid = selectedPlayer->GetUID(); - // Kick this player from the game - std::shared_ptr player = nullptr; + { + std::lock_guard lock(m_kickPlayersCS); + while (!m_smallIdsToKick.empty()) { + std::uint8_t smallId = m_smallIdsToKick.front(); + m_smallIdsToKick.pop_front(); + INetworkPlayer* selectedPlayer = + g_NetworkManager.GetPlayerBySmallId(smallId); + if (selectedPlayer != nullptr) { + if (selectedPlayer->IsLocal() != true) { + // #if 0 + PlayerUID xuid = selectedPlayer->GetUID(); + // Kick this player from the game + std::shared_ptr player = nullptr; - for (unsigned int i = 0; i < players.size(); i++) { - std::shared_ptr p = players.at(i); - PlayerUID playersXuid = p->getOnlineXuid(); - if (p != nullptr && - ProfileManager.AreXUIDSEqual(playersXuid, xuid)) { - player = p; - break; + for (unsigned int i = 0; i < players.size(); i++) { + std::shared_ptr p = players.at(i); + PlayerUID playersXuid = p->getOnlineXuid(); + if (p != nullptr && + ProfileManager.AreXUIDSEqual(playersXuid, xuid)) { + player = p; + break; + } } - } - if (player != nullptr) { - m_bannedXuids.push_back(player->getOnlineXuid()); - // 4J Stu - If we have kicked a player, make sure that they - // have no privileges if they later try to join the world - // when trust players is off - player->enableAllPlayerPrivileges(false); - player->connection->setWasKicked(); - player->connection->send( - std::shared_ptr(new DisconnectPacket( - DisconnectPacket::eDisconnect_Kicked))); + if (player != nullptr) { + m_bannedXuids.push_back(player->getOnlineXuid()); + // 4J Stu - If we have kicked a player, make sure that + // they have no privileges if they later try to join the + // world when trust players is off + player->enableAllPlayerPrivileges(false); + player->connection->setWasKicked(); + player->connection->send( + std::shared_ptr( + new DisconnectPacket( + DisconnectPacket::eDisconnect_Kicked))); + } + // #endif } - // #endif } } } - } // Check our receiving players, and if they are dead see if we can replace // them @@ -1624,14 +1625,16 @@ bool PlayerList::canReceiveAllPackets(std::shared_ptr player) { } void PlayerList::kickPlayerByShortId(std::uint8_t networkSmallId) { - { std::lock_guard lock(m_kickPlayersCS); - m_smallIdsToKick.push_back(networkSmallId); + { + std::lock_guard lock(m_kickPlayersCS); + m_smallIdsToKick.push_back(networkSmallId); } } void PlayerList::closePlayerConnectionBySmallId(std::uint8_t networkSmallId) { - { std::lock_guard lock(m_closePlayersCS); - m_smallIdsToClose.push_back(networkSmallId); + { + std::lock_guard lock(m_closePlayersCS); + m_smallIdsToClose.push_back(networkSmallId); } } diff --git a/Minecraft.Client/Network/ServerChunkCache.cpp b/Minecraft.Client/Network/ServerChunkCache.cpp index 40628a484..79e5775af 100644 --- a/Minecraft.Client/Network/ServerChunkCache.cpp +++ b/Minecraft.Client/Network/ServerChunkCache.cpp @@ -38,7 +38,6 @@ ServerChunkCache::ServerChunkCache(ServerLevel* level, ChunkStorage* storage, m_unloadedCache = new LevelChunk*[XZSIZE * XZSIZE]; memset(m_unloadedCache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk*)); #endif - } // 4J-PB added @@ -144,18 +143,19 @@ LevelChunk* ServerChunkCache::create( LevelChunk* lastChunk = chunk; if ((chunk == nullptr) || (chunk->x != x) || (chunk->z != z)) { - { std::lock_guard lock(m_csLoadCreate); - chunk = load(x, z); - if (chunk == nullptr) { - if (source == nullptr) { - chunk = emptyChunk; - } else { - chunk = source->getChunk(x, z); + { + std::lock_guard lock(m_csLoadCreate); + chunk = load(x, z); + if (chunk == nullptr) { + if (source == nullptr) { + chunk = emptyChunk; + } else { + chunk = source->getChunk(x, z); + } + } + if (chunk != nullptr) { + chunk->load(); } - } - if (chunk != nullptr) { - chunk->load(); - } } #if defined(_WIN64) || defined(__LP64__) @@ -649,11 +649,12 @@ bool ServerChunkCache::saveAllEntities() { PIXBeginNamedEvent(0, "Save all entities"); PIXBeginNamedEvent(0, "saving to NBT"); - { std::lock_guard lock(m_csLoadCreate); - for (auto it = m_loadedChunkList.begin(); it != m_loadedChunkList.end(); - ++it) { - storage->saveEntities(level, *it); - } + { + std::lock_guard lock(m_csLoadCreate); + for (auto it = m_loadedChunkList.begin(); it != m_loadedChunkList.end(); + ++it) { + storage->saveEntities(level, *it); + } } PIXEndNamedEvent(); @@ -860,7 +861,8 @@ int ServerChunkCache::runSaveThreadProc(void* lpParam) { // Wait for the producer thread to tell us to start params->wakeEvent->waitForSignal( - C4JThread::kInfiniteTimeout); // WaitForSingleObject(params->wakeEvent,INFINITE); + C4JThread:: + kInfiniteTimeout); // WaitForSingleObject(params->wakeEvent,INFINITE); // app.DebugPrintf("Save thread has started\n"); @@ -887,7 +889,8 @@ int ServerChunkCache::runSaveThreadProc(void* lpParam) { // Wait for the producer thread to tell us to go again params->wakeEvent->waitForSignal( - C4JThread::kInfiniteTimeout); // WaitForSingleObject(params->wakeEvent,INFINITE); + C4JThread:: + kInfiniteTimeout); // WaitForSingleObject(params->wakeEvent,INFINITE); PIXEndNamedEvent(); } diff --git a/Minecraft.Client/Network/ServerConnection.cpp b/Minecraft.Client/Network/ServerConnection.cpp index a8edd72d2..13aab0dd6 100644 --- a/Minecraft.Client/Network/ServerConnection.cpp +++ b/Minecraft.Client/Network/ServerConnection.cpp @@ -34,17 +34,19 @@ void ServerConnection::addPlayerConnection( } void ServerConnection::handleConnection(std::shared_ptr uc) { - { std::lock_guard lock(pending_cs); - pending.push_back(uc); + { + std::lock_guard lock(pending_cs); + pending.push_back(uc); } } void ServerConnection::stop() { - { std::lock_guard lock(pending_cs); - for (unsigned int i = 0; i < pending.size(); i++) { - std::shared_ptr uc = pending[i]; - uc->connection->close(DisconnectPacket::eDisconnect_Closed); - } + { + std::lock_guard lock(pending_cs); + for (unsigned int i = 0; i < pending.size(); i++) { + std::shared_ptr uc = pending[i]; + uc->connection->close(DisconnectPacket::eDisconnect_Closed); + } } for (unsigned int i = 0; i < players.size(); i++) { @@ -58,8 +60,9 @@ void ServerConnection::tick() { // MGH - changed this so that the the CS lock doesn't cover the tick // (was causing a lockup when 2 players tried to join) std::vector > tempPending; - { std::lock_guard lock(pending_cs); - tempPending = pending; + { + std::lock_guard lock(pending_cs); + tempPending = pending; } for (unsigned int i = 0; i < tempPending.size(); i++) { @@ -76,12 +79,13 @@ void ServerConnection::tick() { } // now remove from the pending list - { std::lock_guard lock(pending_cs); - for (unsigned int i = 0; i < pending.size(); i++) - if (pending[i]->done) { - pending.erase(pending.begin() + i); - i--; - } + { + std::lock_guard lock(pending_cs); + for (unsigned int i = 0; i < pending.size(); i++) + if (pending[i]->done) { + pending.erase(pending.begin() + i); + i--; + } } for (unsigned int i = 0; i < players.size(); i++) { diff --git a/Minecraft.Client/Platform/Common/Consoles_App.cpp b/Minecraft.Client/Platform/Common/Consoles_App.cpp index edc049903..e6ea0b3c5 100644 --- a/Minecraft.Client/Platform/Common/Consoles_App.cpp +++ b/Minecraft.Client/Platform/Common/Consoles_App.cpp @@ -4613,9 +4613,10 @@ bool CMinecraftApp::DefaultCapeExists() { std::wstring wTex = L"Special_Cape.png"; bool val = false; - { std::lock_guard lock(csMemFilesLock); - auto it = m_MEM_Files.find(wTex); - if (it != m_MEM_Files.end()) val = true; + { + std::lock_guard lock(csMemFilesLock); + auto it = m_MEM_Files.find(wTex); + if (it != m_MEM_Files.end()) val = true; } return val; @@ -4624,9 +4625,10 @@ bool CMinecraftApp::DefaultCapeExists() { bool CMinecraftApp::IsFileInMemoryTextures(const std::wstring& wName) { bool val = false; - { std::lock_guard lock(csMemFilesLock); - auto it = m_MEM_Files.find(wName); - if (it != m_MEM_Files.end()) val = true; + { + std::lock_guard lock(csMemFilesLock); + auto it = m_MEM_Files.find(wName); + if (it != m_MEM_Files.end()) val = true; } return val; @@ -4678,9 +4680,10 @@ int CMinecraftApp::GetTPConfigVal(wchar_t* pwchDataFile) { return -1; } bool CMinecraftApp::IsFileInTPD(int iConfig) { bool val = false; - { std::lock_guard lock(csMemTPDLock); - auto it = m_MEM_TPD.find(iConfig); - if (it != m_MEM_TPD.end()) val = true; + { + std::lock_guard lock(csMemTPDLock); + auto it = m_MEM_TPD.find(iConfig); + if (it != m_MEM_TPD.end()) val = true; } return val; @@ -6607,41 +6610,42 @@ std::uint32_t CMinecraftApp::m_dwContentTypeA[e_Marketplace_MAX] = { unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, bool bPromote) { // lock access - { std::lock_guard lock(csDLCDownloadQueue); + { + std::lock_guard lock(csDLCDownloadQueue); - // If it's already in there, promote it to the top of the list - int iPosition = 0; - for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); - ++it) { - DLCRequest* pCurrent = *it; + // If it's already in there, promote it to the top of the list + int iPosition = 0; + for (auto it = m_DLCDownloadQueue.begin(); + it != m_DLCDownloadQueue.end(); ++it) { + DLCRequest* pCurrent = *it; - if (pCurrent->dwType == m_dwContentTypeA[eType]) { - // already got this in the list - if (pCurrent->eState == e_DLC_ContentState_Retrieving || - pCurrent->eState == e_DLC_ContentState_Retrieved) { - // already retrieved this - return 0; - } else { - // promote - if (bPromote) { - m_DLCDownloadQueue.erase(m_DLCDownloadQueue.begin() + - iPosition); - m_DLCDownloadQueue.insert(m_DLCDownloadQueue.begin(), - pCurrent); + if (pCurrent->dwType == m_dwContentTypeA[eType]) { + // already got this in the list + if (pCurrent->eState == e_DLC_ContentState_Retrieving || + pCurrent->eState == e_DLC_ContentState_Retrieved) { + // already retrieved this + return 0; + } else { + // promote + if (bPromote) { + m_DLCDownloadQueue.erase(m_DLCDownloadQueue.begin() + + iPosition); + m_DLCDownloadQueue.insert(m_DLCDownloadQueue.begin(), + pCurrent); + } + return 0; } - return 0; } + iPosition++; } - iPosition++; - } - DLCRequest* pDLCreq = new DLCRequest; - pDLCreq->dwType = m_dwContentTypeA[eType]; - pDLCreq->eState = e_DLC_ContentState_Idle; + DLCRequest* pDLCreq = new DLCRequest; + pDLCreq->dwType = m_dwContentTypeA[eType]; + pDLCreq->eState = e_DLC_ContentState_Idle; - m_DLCDownloadQueue.push_back(pDLCreq); + m_DLCDownloadQueue.push_back(pDLCreq); - m_bAllDLCContentRetrieved = false; + m_bAllDLCContentRetrieved = false; } app.DebugPrintf("[Consoles_App] Added DLC request.\n"); @@ -6859,41 +6863,42 @@ bool CMinecraftApp::RetrieveNextDLCContent() { // online. } - { std::lock_guard lock(csDLCDownloadQueue); - for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); - ++it) { - DLCRequest* pCurrent = *it; + { + std::lock_guard lock(csDLCDownloadQueue); + for (auto it = m_DLCDownloadQueue.begin(); + it != m_DLCDownloadQueue.end(); ++it) { + DLCRequest* pCurrent = *it; - if (pCurrent->eState == e_DLC_ContentState_Retrieving) { - return true; + if (pCurrent->eState == e_DLC_ContentState_Retrieving) { + return true; + } } - } - // Now look for the next retrieval - for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); - ++it) { - DLCRequest* pCurrent = *it; + // Now look for the next retrieval + for (auto it = m_DLCDownloadQueue.begin(); + it != m_DLCDownloadQueue.end(); ++it) { + DLCRequest* pCurrent = *it; - if (pCurrent->eState == e_DLC_ContentState_Idle) { + if (pCurrent->eState == e_DLC_ContentState_Idle) { #if defined(_DEBUG) - app.DebugPrintf("RetrieveNextDLCContent - type = %d\n", - pCurrent->dwType); + app.DebugPrintf("RetrieveNextDLCContent - type = %d\n", + pCurrent->dwType); #endif - C4JStorage::EDLCStatus status = StorageManager.GetDLCOffers( - ProfileManager.GetPrimaryPad(), - &CMinecraftApp::DLCOffersReturned, this, pCurrent->dwType); - if (status == C4JStorage::EDLC_Pending) { - pCurrent->eState = e_DLC_ContentState_Retrieving; - } else { - // no content of this type, or some other problem - app.DebugPrintf("RetrieveNextDLCContent - PROBLEM\n"); - pCurrent->eState = e_DLC_ContentState_Retrieved; + C4JStorage::EDLCStatus status = StorageManager.GetDLCOffers( + ProfileManager.GetPrimaryPad(), + &CMinecraftApp::DLCOffersReturned, this, pCurrent->dwType); + if (status == C4JStorage::EDLC_Pending) { + pCurrent->eState = e_DLC_ContentState_Retrieving; + } else { + // no content of this type, or some other problem + app.DebugPrintf("RetrieveNextDLCContent - PROBLEM\n"); + pCurrent->eState = e_DLC_ContentState_Retrieved; + } + return true; } - return true; } } - } app.DebugPrintf("[Consoles_App] Finished downloading dlc content.\n"); return false; @@ -6905,46 +6910,48 @@ int CMinecraftApp::TMSPPFileReturned(void* pParam, int iPad, int iUserData, CMinecraftApp* pClass = (CMinecraftApp*)pParam; // find the right one in the vector - { std::lock_guard lock(pClass->csTMSPPDownloadQueue); - for (auto it = pClass->m_TMSPPDownloadQueue.begin(); - it != pClass->m_TMSPPDownloadQueue.end(); ++it) { - TMSPPRequest* pCurrent = *it; + { + std::lock_guard lock(pClass->csTMSPPDownloadQueue); + for (auto it = pClass->m_TMSPPDownloadQueue.begin(); + it != pClass->m_TMSPPDownloadQueue.end(); ++it) { + TMSPPRequest* pCurrent = *it; #if defined(_WINDOWS64) - char szFile[MAX_TMSFILENAME_SIZE]; - wcstombs(szFile, pCurrent->wchFilename, MAX_TMSFILENAME_SIZE); + char szFile[MAX_TMSFILENAME_SIZE]; + wcstombs(szFile, pCurrent->wchFilename, MAX_TMSFILENAME_SIZE); - if (strcmp(szFilename, szFile) == 0) + if (strcmp(szFilename, szFile) == 0) #endif - { - // set this to retrieved whether it found it or not - pCurrent->eState = e_TMS_ContentState_Retrieved; + { + // set this to retrieved whether it found it or not + pCurrent->eState = e_TMS_ContentState_Retrieved; - if (pFileData != nullptr) { - switch (pCurrent->eType) { - case e_DLC_TexturePackData: { - app.DebugPrintf("--- Got texturepack data %ls\n", - pCurrent->wchFilename); - // get the config value for the texture pack - int iConfig = app.GetTPConfigVal(pCurrent->wchFilename); - app.AddMemoryTPDFile(iConfig, pFileData->pbData, - pFileData->size); - } break; - default: - app.DebugPrintf("--- Got image data - %ls\n", - pCurrent->wchFilename); - app.AddMemoryTextureFile(pCurrent->wchFilename, - pFileData->pbData, + if (pFileData != nullptr) { + switch (pCurrent->eType) { + case e_DLC_TexturePackData: { + app.DebugPrintf("--- Got texturepack data %ls\n", + pCurrent->wchFilename); + // get the config value for the texture pack + int iConfig = + app.GetTPConfigVal(pCurrent->wchFilename); + app.AddMemoryTPDFile(iConfig, pFileData->pbData, pFileData->size); - break; + } break; + default: + app.DebugPrintf("--- Got image data - %ls\n", + pCurrent->wchFilename); + app.AddMemoryTextureFile(pCurrent->wchFilename, + pFileData->pbData, + pFileData->size); + break; + } + } else { + app.DebugPrintf("TMSImageReturned failed (%s)...\n", + szFilename); } - } else { - app.DebugPrintf("TMSImageReturned failed (%s)...\n", - szFilename); + break; } - break; } } - } return 0; } @@ -6963,16 +6970,17 @@ void CMinecraftApp::ClearAndResetDLCDownloadQueue() { app.DebugPrintf("[Consoles_App] Clear and reset download queue.\n"); int iPosition = 0; - { std::lock_guard lock(csTMSPPDownloadQueue); - for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); - ++it) { - DLCRequest* pCurrent = *it; + { + std::lock_guard lock(csTMSPPDownloadQueue); + for (auto it = m_DLCDownloadQueue.begin(); + it != m_DLCDownloadQueue.end(); ++it) { + DLCRequest* pCurrent = *it; - delete pCurrent; - iPosition++; - } - m_DLCDownloadQueue.clear(); - m_bAllDLCContentRetrieved = true; + delete pCurrent; + iPosition++; + } + m_DLCDownloadQueue.clear(); + m_bAllDLCContentRetrieved = true; } } @@ -6985,16 +6993,17 @@ void CMinecraftApp::TickTMSPPFilesRetrieved() { } void CMinecraftApp::ClearTMSPPFilesRetrieved() { int iPosition = 0; - { std::lock_guard lock(csTMSPPDownloadQueue); - for (auto it = m_TMSPPDownloadQueue.begin(); - it != m_TMSPPDownloadQueue.end(); ++it) { - TMSPPRequest* pCurrent = *it; + { + std::lock_guard lock(csTMSPPDownloadQueue); + for (auto it = m_TMSPPDownloadQueue.begin(); + it != m_TMSPPDownloadQueue.end(); ++it) { + TMSPPRequest* pCurrent = *it; - delete pCurrent; - iPosition++; - } - m_TMSPPDownloadQueue.clear(); - m_bAllTMSContentRetrieved = true; + delete pCurrent; + iPosition++; + } + m_TMSPPDownloadQueue.clear(); + m_bAllTMSContentRetrieved = true; } } @@ -7003,24 +7012,25 @@ int CMinecraftApp::DLCOffersReturned(void* pParam, int iOfferC, CMinecraftApp* pClass = (CMinecraftApp*)pParam; // find the right one in the vector - { std::lock_guard lock(pClass->csTMSPPDownloadQueue); - for (auto it = pClass->m_DLCDownloadQueue.begin(); - it != pClass->m_DLCDownloadQueue.end(); ++it) { - DLCRequest* pCurrent = *it; + { + std::lock_guard lock(pClass->csTMSPPDownloadQueue); + for (auto it = pClass->m_DLCDownloadQueue.begin(); + it != pClass->m_DLCDownloadQueue.end(); ++it) { + DLCRequest* pCurrent = *it; - // avatar items are coming back as type Content, so we can't trust the - // type setting - if (pCurrent->dwType == static_cast(dwType)) { - pClass->m_iDLCOfferC = iOfferC; - app.DebugPrintf( - "DLCOffersReturned - type %u, count %d - setting to " - "retrieved\n", - dwType, iOfferC); - pCurrent->eState = e_DLC_ContentState_Retrieved; - break; + // avatar items are coming back as type Content, so we can't trust + // the type setting + if (pCurrent->dwType == static_cast(dwType)) { + pClass->m_iDLCOfferC = iOfferC; + app.DebugPrintf( + "DLCOffersReturned - type %u, count %d - setting to " + "retrieved\n", + dwType, iOfferC); + pCurrent->eState = e_DLC_ContentState_Retrieved; + break; + } } } - } return 0; } @@ -7057,29 +7067,32 @@ void CMinecraftApp::SetAdditionalSkinBoxes(std::uint32_t dwSkinID, std::vector* pvModelPart = new std::vector; std::vector* pvSkinBoxes = new std::vector; - { std::lock_guard lock_mp(csAdditionalModelParts); - std::lock_guard lock_sb(csAdditionalSkinBoxes); + { + std::lock_guard lock_mp(csAdditionalModelParts); + std::lock_guard lock_sb(csAdditionalSkinBoxes); - app.DebugPrintf( - "*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from " - "array of Skin Boxes\n", - dwSkinID & 0x0FFFFFFF); + app.DebugPrintf( + "*** SetAdditionalSkinBoxes - Inserting model parts for skin %d " + "from " + "array of Skin Boxes\n", + dwSkinID & 0x0FFFFFFF); - // convert the skin boxes into model parts, and add to the humanoid model - for (unsigned int i = 0; i < dwSkinBoxC; i++) { - if (pModel) { - ModelPart* pModelPart = pModel->AddOrRetrievePart(&SkinBoxA[i]); - pvModelPart->push_back(pModelPart); - pvSkinBoxes->push_back(&SkinBoxA[i]); + // convert the skin boxes into model parts, and add to the humanoid + // model + for (unsigned int i = 0; i < dwSkinBoxC; i++) { + if (pModel) { + ModelPart* pModelPart = pModel->AddOrRetrievePart(&SkinBoxA[i]); + pvModelPart->push_back(pModelPart); + pvSkinBoxes->push_back(&SkinBoxA[i]); + } } - } - m_AdditionalModelParts.insert( - std::pair*>(dwSkinID, - pvModelPart)); - m_AdditionalSkinBoxes.insert( - std::pair*>(dwSkinID, - pvSkinBoxes)); + m_AdditionalModelParts.insert( + std::pair*>(dwSkinID, + pvModelPart)); + m_AdditionalSkinBoxes.insert( + std::pair*>(dwSkinID, + pvSkinBoxes)); } } @@ -7090,27 +7103,30 @@ std::vector* CMinecraftApp::SetAdditionalSkinBoxes( Model* pModel = renderer->getModel(); std::vector* pvModelPart = new std::vector; - { std::lock_guard lock_mp(csAdditionalModelParts); - std::lock_guard lock_sb(csAdditionalSkinBoxes); - app.DebugPrintf( - "*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from " - "array of Skin Boxes\n", - dwSkinID & 0x0FFFFFFF); + { + std::lock_guard lock_mp(csAdditionalModelParts); + std::lock_guard lock_sb(csAdditionalSkinBoxes); + app.DebugPrintf( + "*** SetAdditionalSkinBoxes - Inserting model parts for skin %d " + "from " + "array of Skin Boxes\n", + dwSkinID & 0x0FFFFFFF); - // convert the skin boxes into model parts, and add to the humanoid model - for (auto it = pvSkinBoxA->begin(); it != pvSkinBoxA->end(); ++it) { - if (pModel) { - ModelPart* pModelPart = pModel->AddOrRetrievePart(*it); - pvModelPart->push_back(pModelPart); + // convert the skin boxes into model parts, and add to the humanoid + // model + for (auto it = pvSkinBoxA->begin(); it != pvSkinBoxA->end(); ++it) { + if (pModel) { + ModelPart* pModelPart = pModel->AddOrRetrievePart(*it); + pvModelPart->push_back(pModelPart); + } } - } - m_AdditionalModelParts.insert( - std::pair*>(dwSkinID, - pvModelPart)); - m_AdditionalSkinBoxes.insert( - std::pair*>(dwSkinID, - pvSkinBoxA)); + m_AdditionalModelParts.insert( + std::pair*>(dwSkinID, + pvModelPart)); + m_AdditionalSkinBoxes.insert( + std::pair*>(dwSkinID, + pvSkinBoxA)); } return pvModelPart; } diff --git a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp index 600a3e3f3..7397abb93 100644 --- a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp +++ b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp @@ -33,7 +33,6 @@ SonyLeaderboardManager::SonyLeaderboardManager() { m_openSessions = 0; - m_running = false; m_threadScoreboard = nullptr; } @@ -49,7 +48,6 @@ SonyLeaderboardManager::~SonyLeaderboardManager() { } delete m_threadScoreboard; - } int SonyLeaderboardManager::scoreboardThreadEntry(void* lpParam) { @@ -66,8 +64,9 @@ int SonyLeaderboardManager::scoreboardThreadEntry(void* lpParam) { self->scoreboardThreadInternal(); } - { std::lock_guard lock(self->m_csViewsLock); - needsWriting = self->m_views.size() > 0; + { + std::lock_guard lock(self->m_csViewsLock); + needsWriting = self->m_views.size() > 0; } // 4J Stu - We can't write while we aren't signed in to live @@ -165,8 +164,9 @@ void SonyLeaderboardManager::scoreboardThreadInternal() { // we'll manage the write queue seperately. bool hasWork; - { std::lock_guard lock(m_csViewsLock); - hasWork = !m_views.empty(); + { + std::lock_guard lock(m_csViewsLock); + hasWork = !m_views.empty(); } if (hasWork) { @@ -493,9 +493,10 @@ bool SonyLeaderboardManager::setScore() { // Get next job. RegisterScore rscore; - { std::lock_guard lock(m_csViewsLock); - rscore = m_views.front(); - m_views.pop(); + { + std::lock_guard lock(m_csViewsLock); + rscore = m_views.front(); + m_views.pop(); } if (ProfileManager.IsGuest(rscore.m_iPad)) { @@ -641,7 +642,8 @@ bool SonyLeaderboardManager::OpenSession() { m_threadScoreboard = new C4JThread(&scoreboardThreadEntry, this, "4JScoreboard"); m_threadScoreboard->setProcessor(CPU_CORE_LEADERBOARDS); - m_threadScoreboard->setPriority(C4JThread::ThreadPriority::BelowNormal); + m_threadScoreboard->setPriority( + C4JThread::ThreadPriority::BelowNormal); m_threadScoreboard->run(); } @@ -682,16 +684,18 @@ bool SonyLeaderboardManager::WriteStats(unsigned int viewCount, ViewIn views) { // Write relevant parameters. // RegisterScore *regScore = reinterpret_cast(views); - { std::lock_guard lock(m_csViewsLock); - for (int i = 0; i < viewCount; i++) { - app.DebugPrintf( - "[SonyLeaderboardManager] WriteStats(), starting. difficulty=%i, " - "statsType=%i, score=%i\n", - views[i].m_difficulty, views[i].m_commentData.m_statsType, - views[i].m_score); + { + std::lock_guard lock(m_csViewsLock); + for (int i = 0; i < viewCount; i++) { + app.DebugPrintf( + "[SonyLeaderboardManager] WriteStats(), starting. " + "difficulty=%i, " + "statsType=%i, score=%i\n", + views[i].m_difficulty, views[i].m_commentData.m_statsType, + views[i].m_score); - m_views.push(views[i]); - } + m_views.push(views[i]); + } } delete[] views; //*regScore; diff --git a/Minecraft.Client/Platform/Common/UI/UIController.cpp b/Minecraft.Client/Platform/Common/UI/UIController.cpp index dcff5c66f..341b9d78e 100644 --- a/Minecraft.Client/Platform/Common/UI/UIController.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIController.cpp @@ -616,8 +616,9 @@ void UIController::StartReloadSkinThread() { int UIController::reloadSkinThreadProc(void* lpParam) { { - std::lock_guard lock(ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy movies - // while the skins were being reloaded + std::lock_guard lock( + ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy + // movies while the skins were being reloaded UIController* controller = (UIController*)lpParam; // Load new skin controller->loadSkins(); @@ -1400,9 +1401,7 @@ UIScene* UIController::GetSceneFromCallbackId(size_t id) { return scene; } -void UIController::lockCallbackScenes() { - m_registeredCallbackScenesCS.lock(); -} +void UIController::lockCallbackScenes() { m_registeredCallbackScenesCS.lock(); } void UIController::unlockCallbackScenes() { m_registeredCallbackScenesCS.unlock(); diff --git a/Minecraft.Client/Platform/Common/UI/UIScene.cpp b/Minecraft.Client/Platform/Common/UI/UIScene.cpp index fe1b1df1e..632273c6b 100644 --- a/Minecraft.Client/Platform/Common/UI/UIScene.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIScene.cpp @@ -247,8 +247,8 @@ bool UIScene::mapElementsAndNames() { extern std::mutex s_loadSkinCS; void UIScene::loadMovie() { UIController::ms_reloadSkinCS.lock(); // MGH - added to prevent crash - // loading Iggy movies while the skins - // were being reloaded + // loading Iggy movies while the + // skins were being reloaded std::wstring moviePath = getMoviePath(); #if defined(_WINDOWS64) diff --git a/Minecraft.Client/Rendering/Chunk.cpp b/Minecraft.Client/Rendering/Chunk.cpp index 9b3681b46..091f45ddc 100644 --- a/Minecraft.Client/Rendering/Chunk.cpp +++ b/Minecraft.Client/Rendering/Chunk.cpp @@ -93,8 +93,8 @@ void Chunk::reconcileRenderableTileEntities( // TODO - 4J see how input entity vector is set up and decide what way is best // to pass this to the function Chunk::Chunk(Level* level, LevelRenderer::rteMap& globalRenderableTileEntities, - std::mutex& globalRenderableTileEntities_cs, int x, int y, - int z, ClipChunk* clipChunk) + std::mutex& globalRenderableTileEntities_cs, int x, int y, int z, + ClipChunk* clipChunk) : globalRenderableTileEntities(&globalRenderableTileEntities), globalRenderableTileEntities_cs(&globalRenderableTileEntities_cs) { clipChunk->visible = false; @@ -151,25 +151,27 @@ void Chunk::setPos(int x, int y, int z) { assigned = true; { - std::lock_guard lock(levelRenderer->m_csDirtyChunks); + std::lock_guard lock( + levelRenderer->m_csDirtyChunks); unsigned char refCount = levelRenderer->incGlobalChunkRefCount(x, y, z, level); // printf("\t\t [inc] refcount %d at %d, %d, %d\n",refCount,x,y,z); // int idx = levelRenderer->getGlobalIndexForChunk(x, y, z, level); - // If we're the first thing to be referencing this, mark it up as dirty to - // get rebuilt + // If we're the first thing to be referencing this, mark it up as dirty + // to get rebuilt if (refCount == 1) { // printf("Setting %d %d %d dirty [%d]\n",x,y,z, idx); - // Chunks being made dirty in this way can be very numerous (eg the full - // visible area of the world at start up, or a whole edge of the world - // when moving). On account of this, don't want to stick them into our - // lock free queue that we would normally use for letting the render - // update thread know about this chunk. Instead, just set the flag to - // say this is dirty, and then pass a special value of 1 through to the - // lock free stack which lets that thread know that at least one chunk - // other than the ones in the stack itself have been made dirty. + // Chunks being made dirty in this way can be very numerous (eg the + // full visible area of the world at start up, or a whole edge of + // the world when moving). On account of this, don't want to stick + // them into our lock free queue that we would normally use for + // letting the render update thread know about this chunk. Instead, + // just set the flag to say this is dirty, and then pass a special + // value of 1 through to the lock free stack which lets that thread + // know that at least one chunk other than the ones in the stack + // itself have been made dirty. levelRenderer->setGlobalChunkFlag(x, y, z, level, LevelRenderer::CHUNK_FLAG_DIRTY); PIXSetMarkerDeprecated(0, "Non-stack event pushed"); @@ -722,7 +724,8 @@ void Chunk::reset() { bool retireRenderableTileEntities = false; { - std::lock_guard lock(levelRenderer->m_csDirtyChunks); + std::lock_guard lock( + levelRenderer->m_csDirtyChunks); oldKey = levelRenderer->getGlobalIndexForChunk(x, y, z, level); unsigned char refCount = levelRenderer->decGlobalChunkRefCount(x, y, z, level); @@ -735,8 +738,8 @@ void Chunk::reset() { if (lists >= 0) { lists += levelRenderer->chunkLists; for (int i = 0; i < 2; i++) { - // 4J - added - clear any renderer data associated with this - // unused list + // 4J - added - clear any renderer data associated with + // this unused list RenderManager.CBuffClear(lists + i); } levelRenderer->setGlobalChunkFlags(x, y, z, level, 0); diff --git a/Minecraft.Client/Rendering/Chunk.h b/Minecraft.Client/Rendering/Chunk.h index 0aacdb2c8..90c5004fb 100644 --- a/Minecraft.Client/Rendering/Chunk.h +++ b/Minecraft.Client/Rendering/Chunk.h @@ -61,8 +61,8 @@ private: public: Chunk(Level* level, LevelRenderer::rteMap& globalRenderableTileEntities, - std::mutex& globalRenderableTileEntities_cs, int x, int y, - int z, ClipChunk* clipChunk); + std::mutex& globalRenderableTileEntities_cs, int x, int y, int z, + ClipChunk* clipChunk); Chunk(); void setPos(int x, int y, int z); diff --git a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp index 795daf8fb..68ed3dbad 100644 --- a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp +++ b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp @@ -34,7 +34,8 @@ void ProgressRenderer::_progressStart(int title) { } { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock( + ProgressRenderer::s_progress); lastPercent = 0; this->title = title; } @@ -48,7 +49,8 @@ void ProgressRenderer::progressStage(int status) { lastTime = 0; { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock( + ProgressRenderer::s_progress); m_eType = eProgressStringType_ID; this->status = status; } @@ -60,7 +62,8 @@ void ProgressRenderer::progressStagePercentage(int i) { // 4J Stu - Removing all progressRenderer rendering. This will be replaced // on the xbox { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock( + ProgressRenderer::s_progress); lastPercent = i; } } @@ -68,7 +71,8 @@ void ProgressRenderer::progressStagePercentage(int i) { int ProgressRenderer::getCurrentPercent() { int returnValue = 0; { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock( + ProgressRenderer::s_progress); returnValue = lastPercent; } return returnValue; @@ -77,7 +81,8 @@ int ProgressRenderer::getCurrentPercent() { int ProgressRenderer::getCurrentTitle() { int returnValue; { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock( + ProgressRenderer::s_progress); returnValue = title; } return returnValue; @@ -86,7 +91,8 @@ int ProgressRenderer::getCurrentTitle() { int ProgressRenderer::getCurrentStatus() { int returnValue; { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock( + ProgressRenderer::s_progress); returnValue = status; } return returnValue; @@ -95,7 +101,8 @@ int ProgressRenderer::getCurrentStatus() { ProgressRenderer::eProgressStringType ProgressRenderer::getType() { eProgressStringType returnValue; { - std::lock_guard lock(ProgressRenderer::s_progress); + std::lock_guard lock( + ProgressRenderer::s_progress); returnValue = m_eType; } return returnValue; diff --git a/Minecraft.Client/Rendering/GameRenderer.cpp b/Minecraft.Client/Rendering/GameRenderer.cpp index b74a05259..b3f1b9458 100644 --- a/Minecraft.Client/Rendering/GameRenderer.cpp +++ b/Minecraft.Client/Rendering/GameRenderer.cpp @@ -1062,9 +1062,7 @@ void GameRenderer::AddForDelete(SparseDataStorage* deleteThis) { m_deleteStackSparseDataStorage.push_back(deleteThis); } -void GameRenderer::FinishedReassigning() { - m_csDeleteStack.unlock(); -} +void GameRenderer::FinishedReassigning() { m_csDeleteStack.unlock(); } int GameRenderer::runUpdate(void* lpParam) { Minecraft* minecraft = Minecraft::GetInstance(); @@ -1135,8 +1133,8 @@ int GameRenderer::runUpdate(void* lpParam) { i < m_deleteStackCompressedTileStorage.size(); i++) delete m_deleteStackCompressedTileStorage[i]; m_deleteStackCompressedTileStorage.clear(); - for (unsigned int i = 0; - i < m_deleteStackSparseDataStorage.size(); i++) + for (unsigned int i = 0; i < m_deleteStackSparseDataStorage.size(); + i++) delete m_deleteStackSparseDataStorage[i]; m_deleteStackSparseDataStorage.clear(); } @@ -1175,7 +1173,8 @@ void GameRenderer::DisableUpdateThread() { "------------------DisableUpdateThread--------------------\n"); updateRunning = false; m_updateEvents->clear(eUpdateCanRun); - m_updateEvents->waitForSingle(eUpdateEventIsFinished, C4JThread::kInfiniteTimeout); + m_updateEvents->waitForSingle(eUpdateEventIsFinished, + C4JThread::kInfiniteTimeout); #endif } diff --git a/Minecraft.Client/Rendering/LevelRenderer.cpp b/Minecraft.Client/Rendering/LevelRenderer.cpp index 434f1134e..57ac3f6f6 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.cpp +++ b/Minecraft.Client/Rendering/LevelRenderer.cpp @@ -513,7 +513,6 @@ void LevelRenderer::allChanged(int playerIndex) { noEntityRenderFrames = 2; Minecraft::GetInstance()->gameRenderer->EnableUpdateThread(); - } void LevelRenderer::renderEntities(Vec3* cam, Culler* culler, float a) { @@ -620,7 +619,8 @@ void LevelRenderer::renderEntities(Vec3* cam, Culler* culler, float a) { it != renderableTileEntities.end(); it++) { int idx = it->first; // Don't render if it isn't in the same dimension as this player - if (!isGlobalIndexInSameDimension(idx, level[playerIndex])) continue; + if (!isGlobalIndexInSameDimension(idx, level[playerIndex])) + continue; for (auto it2 = it->second.tiles.begin(); it2 != it->second.tiles.end(); it2++) { @@ -3973,7 +3973,6 @@ void LevelRenderer::DestroyedTileManager::addAABBs(Level* level, AABB* box, } } } - } void LevelRenderer::DestroyedTileManager::tick() { diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp index 30185c309..38d550b8e 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp +++ b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp @@ -774,13 +774,9 @@ int ConsoleSaveFileOriginal::getOriginalSaveVersion() { return header.getOriginalSaveVersion(); } -void ConsoleSaveFileOriginal::LockSaveAccess() { - m_lock.lock(); -} +void ConsoleSaveFileOriginal::LockSaveAccess() { m_lock.lock(); } -void ConsoleSaveFileOriginal::ReleaseSaveAccess() { - m_lock.unlock(); -} +void ConsoleSaveFileOriginal::ReleaseSaveAccess() { m_lock.unlock(); } ESavePlatform ConsoleSaveFileOriginal::getSavePlatform() { return header.getSavePlatform(); diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp index 0b7e17f2f..28c00eacd 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp +++ b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp @@ -396,7 +396,6 @@ ConsoleSaveFileSplit::ConsoleSaveFileSplit(ConsoleSaveFile* sourceSave, void ConsoleSaveFileSplit::_init(const std::wstring& fileName, void* pvSaveData, unsigned int fileSize, ESavePlatform plat) { - m_lastTickTime = 0; // One time initialise of static stuff required for our storage @@ -1504,9 +1503,7 @@ int ConsoleSaveFileSplit::getOriginalSaveVersion() { void ConsoleSaveFileSplit::LockSaveAccess() { m_lock.lock(); } -void ConsoleSaveFileSplit::ReleaseSaveAccess() { - m_lock.unlock(); -} +void ConsoleSaveFileSplit::ReleaseSaveAccess() { m_lock.unlock(); } ESavePlatform ConsoleSaveFileSplit::getSavePlatform() { return header.getSavePlatform(); diff --git a/Minecraft.World/IO/Streams/Compression.cpp b/Minecraft.World/IO/Streams/Compression.cpp index 0f3d31e3f..91c840fa3 100644 --- a/Minecraft.World/IO/Streams/Compression.cpp +++ b/Minecraft.World/IO/Streams/Compression.cpp @@ -92,44 +92,46 @@ int32_t Compression::CompressLZXRLE(void* pDestination, unsigned int* pDestSize, int32_t Compression::CompressRLE(void* pDestination, unsigned int* pDestSize, void* pSource, unsigned int SrcSize) { unsigned int rleSize; - { std::lock_guard lock(rleCompressLock); - // static unsigned char rleBuf[1024*100]; + { + std::lock_guard lock(rleCompressLock); + // static unsigned char rleBuf[1024*100]; - unsigned char* pucIn = (unsigned char*)pSource; - unsigned char* pucEnd = pucIn + SrcSize; - unsigned char* pucOut = (unsigned char*)rleCompressBuf; + unsigned char* pucIn = (unsigned char*)pSource; + unsigned char* pucEnd = pucIn + SrcSize; + unsigned char* pucOut = (unsigned char*)rleCompressBuf; - // Compress with RLE first: - // 0 - 254 - encodes a single byte - // 255 followed by 0, 1, 2 - encodes a 1, 2, or 3 255s - // 255 followed by 3-255, followed by a byte - encodes a run of n + 1 bytes - PIXBeginNamedEvent(0, "RLE compression"); - do { - unsigned char thisOne = *pucIn++; + // Compress with RLE first: + // 0 - 254 - encodes a single byte + // 255 followed by 0, 1, 2 - encodes a 1, 2, or 3 255s + // 255 followed by 3-255, followed by a byte - encodes a run of n + 1 + // bytes + PIXBeginNamedEvent(0, "RLE compression"); + do { + unsigned char thisOne = *pucIn++; - unsigned int count = 1; - while ((pucIn != pucEnd) && (*pucIn == thisOne) && (count < 256)) { - pucIn++; - count++; - } + unsigned int count = 1; + while ((pucIn != pucEnd) && (*pucIn == thisOne) && (count < 256)) { + pucIn++; + count++; + } - if (count <= 3) { - if (thisOne == 255) { + if (count <= 3) { + if (thisOne == 255) { + *pucOut++ = 255; + *pucOut++ = count - 1; + } else { + for (unsigned int i = 0; i < count; i++) { + *pucOut++ = thisOne; + } + } + } else { *pucOut++ = 255; *pucOut++ = count - 1; - } else { - for (unsigned int i = 0; i < count; i++) { - *pucOut++ = thisOne; - } + *pucOut++ = thisOne; } - } else { - *pucOut++ = 255; - *pucOut++ = count - 1; - *pucOut++ = thisOne; - } - } while (pucIn != pucEnd); - rleSize = (unsigned int)(pucOut - rleCompressBuf); - PIXEndNamedEvent(); + } while (pucIn != pucEnd); + rleSize = (unsigned int)(pucOut - rleCompressBuf); + PIXEndNamedEvent(); } // Return diff --git a/Minecraft.World/Level/Level.cpp b/Minecraft.World/Level/Level.cpp index b4c8d017f..98bf3d669 100644 --- a/Minecraft.World/Level/Level.cpp +++ b/Minecraft.World/Level/Level.cpp @@ -1615,10 +1615,11 @@ bool Level::addEntity(std::shared_ptr e) { MemSect(42); getChunk(xc, zc)->addEntity(e); MemSect(0); - { std::lock_guard lock(m_entitiesCS); - MemSect(43); - entities.push_back(e); - MemSect(0); + { + std::lock_guard lock(m_entitiesCS); + MemSect(43); + entities.push_back(e); + MemSect(0); } MemSect(44); entityAdded(e); @@ -1700,14 +1701,15 @@ void Level::removeEntityImmediately(std::shared_ptr e) { getChunk(xc, zc)->removeEntity(e); } - { std::lock_guard lock(m_entitiesCS); - std::vector >::iterator it = entities.begin(); - std::vector >::iterator endIt = entities.end(); - while (it != endIt && *it != e) it++; + { + std::lock_guard lock(m_entitiesCS); + std::vector >::iterator it = entities.begin(); + std::vector >::iterator endIt = entities.end(); + while (it != endIt && *it != e) it++; - if (it != endIt) { - entities.erase(it); - } + if (it != endIt) { + entities.erase(it); + } } entityRemoved(e); } @@ -2076,23 +2078,24 @@ void Level::tickEntities() { } } - { std::lock_guard lock(m_entitiesCS); + { + std::lock_guard lock(m_entitiesCS); - for (auto it = entities.begin(); it != entities.end();) { - bool found = false; - for (auto it2 = entitiesToRemove.begin(); it2 != entitiesToRemove.end(); - it2++) { - if ((*it) == (*it2)) { - found = true; - break; + for (auto it = entities.begin(); it != entities.end();) { + bool found = false; + for (auto it2 = entitiesToRemove.begin(); + it2 != entitiesToRemove.end(); it2++) { + if ((*it) == (*it2)) { + found = true; + break; + } + } + if (found) { + it = entities.erase(it); + } else { + it++; } } - if (found) { - it = entities.erase(it); - } else { - it++; - } - } } auto itETREnd = entitiesToRemove.end(); @@ -2117,138 +2120,144 @@ void Level::tickEntities() { /* 4J Jev, using an iterator causes problems here as * the vector is modified from inside this loop. */ - { std::lock_guard lock(m_entitiesCS); + { + std::lock_guard lock(m_entitiesCS); - for (unsigned int i = 0; i < entities.size();) { - std::shared_ptr e = entities.at(i); + for (unsigned int i = 0; i < entities.size();) { + std::shared_ptr e = entities.at(i); - if (e->riding != nullptr) { - if (e->riding->removed || e->riding->rider.lock() != e) { - e->riding->rider = std::weak_ptr(); - e->riding = nullptr; - } else { - i++; - continue; + if (e->riding != nullptr) { + if (e->riding->removed || e->riding->rider.lock() != e) { + e->riding->rider = std::weak_ptr(); + e->riding = nullptr; + } else { + i++; + continue; + } } - } - if (!e->removed) { + if (!e->removed) { #if !defined(_FINAL_BUILD) - if (!(app.DebugSettingsOn() && app.GetMobsDontTickEnabled() && - e->instanceof(eTYPE_MOB) && !e->instanceof(eTYPE_PLAYER))) -#endif - { - tick(e); - } - } - - if (e->removed) { - int xc = e->xChunk; - int zc = e->zChunk; - if (e->inChunk && hasChunk(xc, zc)) { - getChunk(xc, zc)->removeEntity(e); - } - // entities.remove(i--); - // itE = entities.erase( itE ); - - // 4J Find the entity again before deleting, as things might have - // moved in the entity array eg from the explosion created by tnt - auto it = find(entities.begin(), entities.end(), e); - if (it != entities.end()) { - entities.erase(it); - } - - entityRemoved(e); - } else { - i++; - } - } - } - - { std::lock_guard lock(m_tileEntityListCS); - - updatingTileEntities = true; - for (auto it = tileEntityList.begin(); it != tileEntityList.end();) { - std::shared_ptr te = - *it; // tilevector >.at(i); - if (!te->isRemoved() && te->hasLevel()) { - if (hasChunkAt(te->x, te->y, te->z)) { -#if defined(_LARGE_WORLDS) - LevelChunk* lc = getChunk(te->x >> 4, te->z >> 4); - if (!isClientSide || !lc->isUnloaded()) + if (!(app.DebugSettingsOn() && app.GetMobsDontTickEnabled() && + e->instanceof(eTYPE_MOB) && !e->instanceof(eTYPE_PLAYER))) #endif { - te->tick(); + tick(e); } } - } - if (te->isRemoved()) { - it = tileEntityList.erase(it); - if (hasChunk(te->x >> 4, te->z >> 4)) { - LevelChunk* lc = getChunk(te->x >> 4, te->z >> 4); - if (lc != nullptr) - lc->removeTileEntity(te->x & 15, te->y, te->z & 15); + if (e->removed) { + int xc = e->xChunk; + int zc = e->zChunk; + if (e->inChunk && hasChunk(xc, zc)) { + getChunk(xc, zc)->removeEntity(e); + } + // entities.remove(i--); + // itE = entities.erase( itE ); + + // 4J Find the entity again before deleting, as things might + // have moved in the entity array eg from the explosion created + // by tnt + auto it = find(entities.begin(), entities.end(), e); + if (it != entities.end()) { + entities.erase(it); + } + + entityRemoved(e); + } else { + i++; } - } else { - it++; } } - updatingTileEntities = false; - // 4J-PB - Stuart - check this is correct here - - if (!tileEntitiesToUnload.empty()) { - FRAME_PROFILE_SCOPE(TileEntityUnloadCleanup); + { + std::lock_guard lock(m_tileEntityListCS); + updatingTileEntities = true; for (auto it = tileEntityList.begin(); it != tileEntityList.end();) { - if (tileEntitiesToUnload.find(*it) != tileEntitiesToUnload.end()) { - if (isClientSide) { - __debugbreak(); + std::shared_ptr te = + *it; // tilevector >.at(i); + if (!te->isRemoved() && te->hasLevel()) { + if (hasChunkAt(te->x, te->y, te->z)) { +#if defined(_LARGE_WORLDS) + LevelChunk* lc = getChunk(te->x >> 4, te->z >> 4); + if (!isClientSide || !lc->isUnloaded()) +#endif + { + te->tick(); + } } + } + + if (te->isRemoved()) { it = tileEntityList.erase(it); + if (hasChunk(te->x >> 4, te->z >> 4)) { + LevelChunk* lc = getChunk(te->x >> 4, te->z >> 4); + if (lc != nullptr) + lc->removeTileEntity(te->x & 15, te->y, te->z & 15); + } } else { it++; } } - tileEntitiesToUnload.clear(); - } + updatingTileEntities = false; - if (!pendingTileEntities.empty()) { - for (auto it = pendingTileEntities.begin(); - it != pendingTileEntities.end(); it++) { - std::shared_ptr e = *it; - if (!e->isRemoved()) { - if (find(tileEntityList.begin(), tileEntityList.end(), e) == - tileEntityList.end()) { - tileEntityList.push_back(e); - } - if (hasChunk(e->x >> 4, e->z >> 4)) { - LevelChunk* lc = getChunk(e->x >> 4, e->z >> 4); - if (lc != nullptr) - lc->setTileEntity(e->x & 15, e->y, e->z & 15, e); - } + // 4J-PB - Stuart - check this is correct here - sendTileUpdated(e->x, e->y, e->z); + if (!tileEntitiesToUnload.empty()) { + FRAME_PROFILE_SCOPE(TileEntityUnloadCleanup); + + for (auto it = tileEntityList.begin(); + it != tileEntityList.end();) { + if (tileEntitiesToUnload.find(*it) != + tileEntitiesToUnload.end()) { + if (isClientSide) { + __debugbreak(); + } + it = tileEntityList.erase(it); + } else { + it++; + } } + tileEntitiesToUnload.clear(); + } + + if (!pendingTileEntities.empty()) { + for (auto it = pendingTileEntities.begin(); + it != pendingTileEntities.end(); it++) { + std::shared_ptr e = *it; + if (!e->isRemoved()) { + if (find(tileEntityList.begin(), tileEntityList.end(), e) == + tileEntityList.end()) { + tileEntityList.push_back(e); + } + if (hasChunk(e->x >> 4, e->z >> 4)) { + LevelChunk* lc = getChunk(e->x >> 4, e->z >> 4); + if (lc != nullptr) + lc->setTileEntity(e->x & 15, e->y, e->z & 15, e); + } + + sendTileUpdated(e->x, e->y, e->z); + } + } + pendingTileEntities.clear(); } - pendingTileEntities.clear(); - } } } void Level::addAllPendingTileEntities( std::vector >& entities) { - { std::lock_guard lock(m_tileEntityListCS); - if (updatingTileEntities) { - for (auto it = entities.begin(); it != entities.end(); it++) { - pendingTileEntities.push_back(*it); + { + std::lock_guard lock(m_tileEntityListCS); + if (updatingTileEntities) { + for (auto it = entities.begin(); it != entities.end(); it++) { + pendingTileEntities.push_back(*it); + } + } else { + for (auto it = entities.begin(); it != entities.end(); it++) { + tileEntityList.push_back(*it); + } } - } else { - for (auto it = entities.begin(); it != entities.end(); it++) { - tileEntityList.push_back(*it); - } - } } } @@ -2587,8 +2596,9 @@ return shared_ptr(); std::wstring Level::gatherStats() { wchar_t buf[64]; - { std::lock_guard lock(m_entitiesCS); - swprintf(buf, 64, L"All:%d", entities.size()); + { + std::lock_guard lock(m_entitiesCS); + swprintf(buf, 64, L"All:%d", entities.size()); } return std::wstring(buf); } @@ -2604,15 +2614,16 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { std::shared_ptr tileEntity = nullptr; if (updatingTileEntities) { - { std::lock_guard lock(m_tileEntityListCS); - for (int i = 0; i < pendingTileEntities.size(); i++) { - std::shared_ptr e = pendingTileEntities.at(i); - if (!e->isRemoved() && e->x == x && e->y == y && e->z == z) { - tileEntity = e; - break; + { + std::lock_guard lock(m_tileEntityListCS); + for (int i = 0; i < pendingTileEntities.size(); i++) { + std::shared_ptr e = pendingTileEntities.at(i); + if (!e->isRemoved() && e->x == x && e->y == y && e->z == z) { + tileEntity = e; + break; + } } } - } } if (tileEntity == nullptr) { @@ -2623,17 +2634,18 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { } if (tileEntity == nullptr) { - { std::lock_guard lock(m_tileEntityListCS); - for (auto it = pendingTileEntities.begin(); - it != pendingTileEntities.end(); it++) { - std::shared_ptr e = *it; + { + std::lock_guard lock(m_tileEntityListCS); + for (auto it = pendingTileEntities.begin(); + it != pendingTileEntities.end(); it++) { + std::shared_ptr e = *it; - if (!e->isRemoved() && e->x == x && e->y == y && e->z == z) { - tileEntity = e; - break; + if (!e->isRemoved() && e->x == x && e->y == y && e->z == z) { + tileEntity = e; + break; + } } } - } } return tileEntity; } @@ -2641,66 +2653,71 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { void Level::setTileEntity(int x, int y, int z, std::shared_ptr tileEntity) { if (tileEntity != nullptr && !tileEntity->isRemoved()) { - { std::lock_guard lock(m_tileEntityListCS); - if (updatingTileEntities) { - tileEntity->x = x; - tileEntity->y = y; - tileEntity->z = z; + { + std::lock_guard lock(m_tileEntityListCS); + if (updatingTileEntities) { + tileEntity->x = x; + tileEntity->y = y; + tileEntity->z = z; - // avoid adding duplicates - for (auto it = pendingTileEntities.begin(); - it != pendingTileEntities.end();) { - std::shared_ptr next = *it; - if (next->x == x && next->y == y && next->z == z) { - next->setRemoved(); - it = pendingTileEntities.erase(it); - } else { - ++it; + // avoid adding duplicates + for (auto it = pendingTileEntities.begin(); + it != pendingTileEntities.end();) { + std::shared_ptr next = *it; + if (next->x == x && next->y == y && next->z == z) { + next->setRemoved(); + it = pendingTileEntities.erase(it); + } else { + ++it; + } } + + pendingTileEntities.push_back(tileEntity); + } else { + tileEntityList.push_back(tileEntity); + + LevelChunk* lc = getChunk(x >> 4, z >> 4); + if (lc != nullptr) + lc->setTileEntity(x & 15, y, z & 15, tileEntity); } - - pendingTileEntities.push_back(tileEntity); - } else { - tileEntityList.push_back(tileEntity); - - LevelChunk* lc = getChunk(x >> 4, z >> 4); - if (lc != nullptr) lc->setTileEntity(x & 15, y, z & 15, tileEntity); - } } } } void Level::removeTileEntity(int x, int y, int z) { - { std::lock_guard lock(m_tileEntityListCS); - std::shared_ptr te = getTileEntity(x, y, z); - if (te != nullptr && updatingTileEntities) { - te->setRemoved(); - auto it = - find(pendingTileEntities.begin(), pendingTileEntities.end(), te); - if (it != pendingTileEntities.end()) { - pendingTileEntities.erase(it); - } - } else { - if (te != nullptr) { + { + std::lock_guard lock(m_tileEntityListCS); + std::shared_ptr te = getTileEntity(x, y, z); + if (te != nullptr && updatingTileEntities) { + te->setRemoved(); auto it = find(pendingTileEntities.begin(), pendingTileEntities.end(), te); if (it != pendingTileEntities.end()) { pendingTileEntities.erase(it); } - auto it2 = find(tileEntityList.begin(), tileEntityList.end(), te); - if (it2 != tileEntityList.end()) { - tileEntityList.erase(it2); + } else { + if (te != nullptr) { + auto it = find(pendingTileEntities.begin(), + pendingTileEntities.end(), te); + if (it != pendingTileEntities.end()) { + pendingTileEntities.erase(it); + } + auto it2 = + find(tileEntityList.begin(), tileEntityList.end(), te); + if (it2 != tileEntityList.end()) { + tileEntityList.erase(it2); + } } + LevelChunk* lc = getChunk(x >> 4, z >> 4); + if (lc != nullptr) lc->removeTileEntity(x & 15, y, z & 15); } - LevelChunk* lc = getChunk(x >> 4, z >> 4); - if (lc != nullptr) lc->removeTileEntity(x & 15, y, z & 15); - } } } void Level::markForRemoval(std::shared_ptr entity) { - { std::lock_guard lock(m_tileEntityListCS); - tileEntitiesToUnload.insert(entity); + { + std::lock_guard lock(m_tileEntityListCS); + tileEntitiesToUnload.insert(entity); } } @@ -3097,234 +3114,248 @@ void Level::checkLight(LightLayer::variety layer, int xc, int yc, int zc, if (!hasChunksAt(xc, yc, zc, 17)) return; } - { std::lock_guard lock(m_checkLightCS); - - initCachePartial(cache, xc, yc, zc); - - // If we're in cached mode, then use memory allocated after the cached data - // itself for the toCheck array, in an attempt to make both that & the other - // cached data sit on the CPU L2 cache better. - - int* toCheck; - if (cache == nullptr) { - toCheck = toCheckLevel; - } else { - toCheck = (int*)(cache + (16 * 16 * 16)); - } - - int checkedPosition = 0; - int toCheckCount = 0; - // int darktcc = 0; - - // 4J - added - int minXZ = -(dimension->getXZSize() * 16) / 2; - int maxXZ = (dimension->getXZSize() * 16) / 2 - 1; - if ((xc > maxXZ) || (xc < minXZ) || (zc > maxXZ) || (zc < minXZ)) { - return; - } - - // Lock 128K of cache (containing all the lighting cache + first 112K of - // toCheck array) on L2 to try and stop any cached data getting knocked out - // of L2 by other non-cached reads (or vice-versa) - // if( cache ) XLockL2(XLOCKL2_INDEX_TITLE, cache, 128 * 1024, - // XLOCKL2_LOCK_SIZE_1_WAY, 0 ); - { - int centerCurrent = getBrightnessCached(cache, layer, xc, yc, zc); - int centerExpected = getExpectedLight(cache, xc, yc, zc, layer, false); + std::lock_guard lock(m_checkLightCS); - if (centerExpected != centerCurrent && cache) { - initCacheComplete(cache, xc, yc, zc); + initCachePartial(cache, xc, yc, zc); + + // If we're in cached mode, then use memory allocated after the cached + // data itself for the toCheck array, in an attempt to make both that & + // the other cached data sit on the CPU L2 cache better. + + int* toCheck; + if (cache == nullptr) { + toCheck = toCheckLevel; + } else { + toCheck = (int*)(cache + (16 * 16 * 16)); } - if (centerExpected > centerCurrent) { - toCheck[toCheckCount++] = 32 | (32 << 6) | (32 << 12); - } else if (centerExpected < centerCurrent) { - // 4J - added tcn. This is the code that is run when checkLight has - // been called for a light source that has got darker / turned off. - // In the original version, after zeroing tiles brightnesses that - // are deemed to come from this light source, all the zeroed tiles - // are then passed to the next stage of the function to potentially - // have their brightnesses put back up again. We shouldn't need to - // consider All these tiles as starting points for this process, now - // just considering the edge tiles (defined as a tile where we have - // a neighbour that is brightner than can be explained by the - // original light source we are turning off) - int tcn = 0; - if (layer == LightLayer::Block || true) { - toCheck[toCheckCount++] = - 32 | (32 << 6) | (32 << 12) | (centerCurrent << 18); - while (checkedPosition < toCheckCount) { - int p = toCheck[checkedPosition++]; - int x = ((p) & 63) - 32 + xc; - int y = ((p >> 6) & 63) - 32 + yc; - int z = ((p >> 12) & 63) - 32 + zc; - int expected = ((p >> 18) & 15); - int current = getBrightnessCached(cache, layer, x, y, z); - if (current == expected) { - setBrightnessCached(cache, &cacheUse, layer, x, y, z, - 0); - // cexp--; // 4J - removed, change - // from 1.2.3 - if (expected > 0) { - int xd = Mth::abs(x - xc); - int yd = Mth::abs(y - yc); - int zd = Mth::abs(z - zc); - if (xd + yd + zd < 17) { - bool edge = false; - for (int face = 0; face < 6; face++) { - int xx = x + Facing::STEP_X[face]; - int yy = y + Facing::STEP_Y[face]; - int zz = z + Facing::STEP_Z[face]; + int checkedPosition = 0; + int toCheckCount = 0; + // int darktcc = 0; - // 4J - added - don't let this lighting - // creep out of the normal fixed world and - // into the infinite water chunks beyond - if ((xx > maxXZ) || (xx < minXZ) || - (zz > maxXZ) || (zz < minXZ)) - continue; - if ((yy < 0) || (yy >= maxBuildHeight)) - continue; + // 4J - added + int minXZ = -(dimension->getXZSize() * 16) / 2; + int maxXZ = (dimension->getXZSize() * 16) / 2 - 1; + if ((xc > maxXZ) || (xc < minXZ) || (zc > maxXZ) || (zc < minXZ)) { + return; + } - // 4J - some changes here brought forward - // from 1.2.3 - int block = std::max( - 1, - getBlockingCached(cache, layer, nullptr, - xx, yy, zz)); - current = getBrightnessCached(cache, layer, - xx, yy, zz); - if ((current == expected - block) && - (toCheckCount < - (32 * 32 * 32))) // 4J - 32 * 32 * 32 - // was toCheck.length - { - toCheck[toCheckCount++] = - (xx - xc + 32) | - ((yy - yc + 32) << 6) | - ((zz - zc + 32) << 12) | - ((expected - block) << 18); - } else { - // 4J - added - keep track of which - // tiles form the edge of the region we - // are zeroing - if (current > (expected - block)) { - edge = true; + // Lock 128K of cache (containing all the lighting cache + first 112K of + // toCheck array) on L2 to try and stop any cached data getting knocked + // out of L2 by other non-cached reads (or vice-versa) + // if( cache ) XLockL2(XLOCKL2_INDEX_TITLE, cache, 128 * 1024, + // XLOCKL2_LOCK_SIZE_1_WAY, 0 ); + + { + int centerCurrent = getBrightnessCached(cache, layer, xc, yc, zc); + int centerExpected = + getExpectedLight(cache, xc, yc, zc, layer, false); + + if (centerExpected != centerCurrent && cache) { + initCacheComplete(cache, xc, yc, zc); + } + + if (centerExpected > centerCurrent) { + toCheck[toCheckCount++] = 32 | (32 << 6) | (32 << 12); + } else if (centerExpected < centerCurrent) { + // 4J - added tcn. This is the code that is run when checkLight + // has been called for a light source that has got darker / + // turned off. In the original version, after zeroing tiles + // brightnesses that are deemed to come from this light source, + // all the zeroed tiles are then passed to the next stage of the + // function to potentially have their brightnesses put back up + // again. We shouldn't need to consider All these tiles as + // starting points for this process, now just considering the + // edge tiles (defined as a tile where we have a neighbour that + // is brightner than can be explained by the original light + // source we are turning off) + int tcn = 0; + if (layer == LightLayer::Block || true) { + toCheck[toCheckCount++] = + 32 | (32 << 6) | (32 << 12) | (centerCurrent << 18); + while (checkedPosition < toCheckCount) { + int p = toCheck[checkedPosition++]; + int x = ((p) & 63) - 32 + xc; + int y = ((p >> 6) & 63) - 32 + yc; + int z = ((p >> 12) & 63) - 32 + zc; + int expected = ((p >> 18) & 15); + int current = + getBrightnessCached(cache, layer, x, y, z); + if (current == expected) { + setBrightnessCached(cache, &cacheUse, layer, x, y, + z, 0); + // cexp--; // 4J - removed, change + // from 1.2.3 + if (expected > 0) { + int xd = Mth::abs(x - xc); + int yd = Mth::abs(y - yc); + int zd = Mth::abs(z - zc); + if (xd + yd + zd < 17) { + bool edge = false; + for (int face = 0; face < 6; face++) { + int xx = x + Facing::STEP_X[face]; + int yy = y + Facing::STEP_Y[face]; + int zz = z + Facing::STEP_Z[face]; + + // 4J - added - don't let this lighting + // creep out of the normal fixed world + // and into the infinite water chunks + // beyond + if ((xx > maxXZ) || (xx < minXZ) || + (zz > maxXZ) || (zz < minXZ)) + continue; + if ((yy < 0) || (yy >= maxBuildHeight)) + continue; + + // 4J - some changes here brought + // forward from 1.2.3 + int block = std::max( + 1, getBlockingCached(cache, layer, + nullptr, xx, + yy, zz)); + current = getBrightnessCached( + cache, layer, xx, yy, zz); + if ((current == expected - block) && + (toCheckCount < + (32 * 32 * + 32))) // 4J - 32 * 32 * 32 + // was toCheck.length + { + toCheck[toCheckCount++] = + (xx - xc + 32) | + ((yy - yc + 32) << 6) | + ((zz - zc + 32) << 12) | + ((expected - block) << 18); + } else { + // 4J - added - keep track of which + // tiles form the edge of the region + // we are zeroing + if (current > (expected - block)) { + edge = true; + } } } - } - // 4J - added - keep track of which tiles form - // the edge of the region we are zeroing - can - // store over the original elements in the array - // because tcn must be <= tcp - if (edge == true) { - toCheck[tcn++] = p; + // 4J - added - keep track of which tiles + // form the edge of the region we are + // zeroing - can store over the original + // elements in the array because tcn must be + // <= tcp + if (edge == true) { + toCheck[tcn++] = p; + } } } } } } - } - checkedPosition = 0; - // darktcc = tcc; - ///////////////////////////////////////////////////// - toCheckCount = tcn; // 4J added - we've moved all the edge tiles to - // the start of the array, so only need to - // process these now. The original processes - // all tcc tiles again in the next section - } - } - - while (checkedPosition < toCheckCount) { - int p = toCheck[checkedPosition++]; - int x = ((p) & 63) - 32 + xc; - int y = ((p >> 6) & 63) - 32 + yc; - int z = ((p >> 12) & 63) - 32 + zc; - - // If force is set, then this is being used to in a special mode to try - // and light lava tiles as chunks are being loaded in. In this case, we - // don't want a lighting update to drag in any neighbouring chunks that - // aren't loaded yet. - if (force) { - if (!hasChunkAt(x, y, z)) { - continue; + checkedPosition = 0; + // darktcc = tcc; + ///////////////////////////////////////////////////// + toCheckCount = + tcn; // 4J added - we've moved all the edge tiles to + // the start of the array, so only need to + // process these now. The original processes + // all tcc tiles again in the next section } } - int current = getBrightnessCached(cache, layer, x, y, z); - // If rootOnlyEmissive flag is set, then only consider the starting tile - // to be possibly emissive. - bool propagatedOnly = false; - if (layer == LightLayer::Block) { - if (rootOnlyEmissive) { - propagatedOnly = (x != xc) || (y != yc) || (z != zc); + while (checkedPosition < toCheckCount) { + int p = toCheck[checkedPosition++]; + int x = ((p) & 63) - 32 + xc; + int y = ((p >> 6) & 63) - 32 + yc; + int z = ((p >> 12) & 63) - 32 + zc; + + // If force is set, then this is being used to in a special mode to + // try and light lava tiles as chunks are being loaded in. In this + // case, we don't want a lighting update to drag in any neighbouring + // chunks that aren't loaded yet. + if (force) { + if (!hasChunkAt(x, y, z)) { + continue; + } } - } - int expected = getExpectedLight(cache, x, y, z, layer, propagatedOnly); + int current = getBrightnessCached(cache, layer, x, y, z); - if (expected != current) { - setBrightnessCached(cache, &cacheUse, layer, x, y, z, expected); + // If rootOnlyEmissive flag is set, then only consider the starting + // tile to be possibly emissive. + bool propagatedOnly = false; + if (layer == LightLayer::Block) { + if (rootOnlyEmissive) { + propagatedOnly = (x != xc) || (y != yc) || (z != zc); + } + } + int expected = + getExpectedLight(cache, x, y, z, layer, propagatedOnly); - if (expected > current) { - int xd = abs(x - xc); - int yd = abs(y - yc); - int zd = abs(z - zc); - bool withinBounds = - toCheckCount < - (32 * 32 * 32) - 6; // 4J - 32 * 32 * 32 was toCheck.length - if (xd + yd + zd < 17 && withinBounds) { - // 4J - added extra checks here to stop lighting updates - // moving out of the actual fixed world and into the - // infinite water chunks - if ((x - 1) >= minXZ) { - if (getBrightnessCached(cache, layer, x - 1, y, z) < - expected) - toCheck[toCheckCount++] = (((x - 1 - xc) + 32)) + - (((y - yc) + 32) << 6) + - (((z - zc) + 32) << 12); - } - if ((x + 1) <= maxXZ) { - if (getBrightnessCached(cache, layer, x + 1, y, z) < - expected) - toCheck[toCheckCount++] = (((x + 1 - xc) + 32)) + - (((y - yc) + 32) << 6) + - (((z - zc) + 32) << 12); - } - if ((y - 1) >= 0) { - if (getBrightnessCached(cache, layer, x, y - 1, z) < - expected) - toCheck[toCheckCount++] = - (((x - xc) + 32)) + (((y - 1 - yc) + 32) << 6) + - (((z - zc) + 32) << 12); - } - if ((y + 1) < maxBuildHeight) { - if (getBrightnessCached(cache, layer, x, y + 1, z) < - expected) - toCheck[toCheckCount++] = - (((x - xc) + 32)) + (((y + 1 - yc) + 32) << 6) + - (((z - zc) + 32) << 12); - } - if ((z - 1) >= minXZ) { - if (getBrightnessCached(cache, layer, x, y, z - 1) < - expected) - toCheck[toCheckCount++] = - (((x - xc) + 32)) + (((y - yc) + 32) << 6) + - (((z - 1 - zc) + 32) << 12); - } - if ((z + 1) <= maxXZ) { - if (getBrightnessCached(cache, layer, x, y, z + 1) < - expected) - toCheck[toCheckCount++] = - (((x - xc) + 32)) + (((y - yc) + 32) << 6) + - (((z + 1 - zc) + 32) << 12); + if (expected != current) { + setBrightnessCached(cache, &cacheUse, layer, x, y, z, expected); + + if (expected > current) { + int xd = abs(x - xc); + int yd = abs(y - yc); + int zd = abs(z - zc); + bool withinBounds = + toCheckCount < + (32 * 32 * 32) - + 6; // 4J - 32 * 32 * 32 was toCheck.length + if (xd + yd + zd < 17 && withinBounds) { + // 4J - added extra checks here to stop lighting updates + // moving out of the actual fixed world and into the + // infinite water chunks + if ((x - 1) >= minXZ) { + if (getBrightnessCached(cache, layer, x - 1, y, z) < + expected) + toCheck[toCheckCount++] = + (((x - 1 - xc) + 32)) + + (((y - yc) + 32) << 6) + + (((z - zc) + 32) << 12); + } + if ((x + 1) <= maxXZ) { + if (getBrightnessCached(cache, layer, x + 1, y, z) < + expected) + toCheck[toCheckCount++] = + (((x + 1 - xc) + 32)) + + (((y - yc) + 32) << 6) + + (((z - zc) + 32) << 12); + } + if ((y - 1) >= 0) { + if (getBrightnessCached(cache, layer, x, y - 1, z) < + expected) + toCheck[toCheckCount++] = + (((x - xc) + 32)) + + (((y - 1 - yc) + 32) << 6) + + (((z - zc) + 32) << 12); + } + if ((y + 1) < maxBuildHeight) { + if (getBrightnessCached(cache, layer, x, y + 1, z) < + expected) + toCheck[toCheckCount++] = + (((x - xc) + 32)) + + (((y + 1 - yc) + 32) << 6) + + (((z - zc) + 32) << 12); + } + if ((z - 1) >= minXZ) { + if (getBrightnessCached(cache, layer, x, y, z - 1) < + expected) + toCheck[toCheckCount++] = + (((x - xc) + 32)) + (((y - yc) + 32) << 6) + + (((z - 1 - zc) + 32) << 12); + } + if ((z + 1) <= maxXZ) { + if (getBrightnessCached(cache, layer, x, y, z + 1) < + expected) + toCheck[toCheckCount++] = + (((x - xc) + 32)) + (((y - yc) + 32) << 6) + + (((z + 1 - zc) + 32) << 12); + } } } } } - } - // if( cache ) XUnlockL2(XLOCKL2_INDEX_TITLE); + // if( cache ) XUnlockL2(XLOCKL2_INDEX_TITLE); - flushCache(cache, cacheUse, layer); + flushCache(cache, cacheUse, layer); } } @@ -3429,27 +3460,28 @@ unsigned int Level::countInstanceOf( unsigned int count = 0; if (protectedCount) *protectedCount = 0; if (couldWanderCount) *couldWanderCount = 0; - { std::lock_guard lock(m_entitiesCS); - auto itEnd = entities.end(); - for (auto it = entities.begin(); it != itEnd; it++) { - std::shared_ptr e = *it; // entities.at(i); - if (singleType) { - if (e->GetType() == clas) { - if (protectedCount && e->isDespawnProtected()) { - (*protectedCount)++; - } + { + std::lock_guard lock(m_entitiesCS); + auto itEnd = entities.end(); + for (auto it = entities.begin(); it != itEnd; it++) { + std::shared_ptr e = *it; // entities.at(i); + if (singleType) { + if (e->GetType() == clas) { + if (protectedCount && e->isDespawnProtected()) { + (*protectedCount)++; + } - if (couldWanderCount && e->couldWander()) { - (*couldWanderCount)++; - } + if (couldWanderCount && e->couldWander()) { + (*couldWanderCount)++; + } - count++; + count++; + } + } else { + if (e->instanceof(clas)) count++; } - } else { - if (e->instanceof(clas)) count++; } } - } return count; } @@ -3457,60 +3489,62 @@ unsigned int Level::countInstanceOf( unsigned int Level::countInstanceOfInRange(eINSTANCEOF clas, bool singleType, int range, int x, int y, int z) { unsigned int count = 0; - { std::lock_guard lock(m_entitiesCS); - auto itEnd = entities.end(); - for (auto it = entities.begin(); it != itEnd; it++) { - std::shared_ptr e = *it; // entities.at(i); + { + std::lock_guard lock(m_entitiesCS); + auto itEnd = entities.end(); + for (auto it = entities.begin(); it != itEnd; it++) { + std::shared_ptr e = *it; // entities.at(i); - float sd = e->distanceTo(x, y, z); - if (sd * sd > range * range) { - continue; - } - - if (singleType) { - if (e->GetType() == clas) { - count++; + float sd = e->distanceTo(x, y, z); + if (sd * sd > range * range) { + continue; + } + + if (singleType) { + if (e->GetType() == clas) { + count++; + } + } else { + if (e->instanceof(clas)) count++; } - } else { - if (e->instanceof(clas)) count++; } } - } return count; } void Level::addEntities(std::vector >* list) { // entities.addAll(list); - { std::lock_guard lock(m_entitiesCS); - entities.insert(entities.end(), list->begin(), list->end()); - auto itEnd = list->end(); - bool deleteDragons = false; - for (auto it = list->begin(); it != itEnd; it++) { - entityAdded(*it); + { + std::lock_guard lock(m_entitiesCS); + entities.insert(entities.end(), list->begin(), list->end()); + auto itEnd = list->end(); + bool deleteDragons = false; + for (auto it = list->begin(); it != itEnd; it++) { + entityAdded(*it); - // 4J Stu - Special change to remove duplicate enderdragons that a - // previous bug might have produced - if ((*it)->GetType() == eTYPE_ENDERDRAGON) { - deleteDragons = true; - } - } - - if (deleteDragons) { - deleteDragons = false; - for (auto it = entities.begin(); it != entities.end(); ++it) { // 4J Stu - Special change to remove duplicate enderdragons that a // previous bug might have produced if ((*it)->GetType() == eTYPE_ENDERDRAGON) { - if (deleteDragons) { - (*it)->remove(); - } else { - deleteDragons = true; + deleteDragons = true; + } + } + + if (deleteDragons) { + deleteDragons = false; + for (auto it = entities.begin(); it != entities.end(); ++it) { + // 4J Stu - Special change to remove duplicate enderdragons that + // a previous bug might have produced + if ((*it)->GetType() == eTYPE_ENDERDRAGON) { + if (deleteDragons) { + (*it)->remove(); + } else { + deleteDragons = true; + } } } } } - } } void Level::removeEntities(std::vector >* list) { @@ -3925,10 +3959,11 @@ void Level::ensureAdded(std::shared_ptr entity) { } // if (!entities.contains(entity)) - { std::lock_guard lock(m_entitiesCS); - if (find(entities.begin(), entities.end(), entity) == entities.end()) { - entities.push_back(entity); - } + { + std::lock_guard lock(m_entitiesCS); + if (find(entities.begin(), entities.end(), entity) == entities.end()) { + entities.push_back(entity); + } } } diff --git a/Minecraft.World/Level/Level.h b/Minecraft.World/Level/Level.h index c0950a638..9503e1d2d 100644 --- a/Minecraft.World/Level/Level.h +++ b/Minecraft.World/Level/Level.h @@ -109,8 +109,8 @@ protected: std::vector > entitiesToRemove; public: - bool hasEntitiesToRemove(); // 4J added - bool m_bDisableAddNewTileEntities; // 4J Added + bool hasEntitiesToRemove(); // 4J added + bool m_bDisableAddNewTileEntities; // 4J Added std::recursive_mutex m_tileEntityListCS; // 4J added std::vector > tileEntityList; diff --git a/Minecraft.World/Level/LevelChunk.cpp b/Minecraft.World/Level/LevelChunk.cpp index 97fe9d7bb..69d4a9ebc 100644 --- a/Minecraft.World/Level/LevelChunk.cpp +++ b/Minecraft.World/Level/LevelChunk.cpp @@ -28,17 +28,17 @@ std::recursive_mutex LevelChunk::m_csEntities; std::recursive_mutex LevelChunk::m_csTileEntities; bool LevelChunk::touchedSky = false; -void LevelChunk::staticCtor() { -} +void LevelChunk::staticCtor() {} void LevelChunk::init(Level* level, int x, int z) { biomes = byteArray(16 * 16); for (int i = 0; i < 16 * 16; i++) { biomes[i] = 0xff; } - { std::lock_guard lock(m_csEntities); - entityBlocks = - new std::vector >*[ENTITY_BLOCKS_LENGTH]; + { + std::lock_guard lock(m_csEntities); + entityBlocks = + new std::vector >*[ENTITY_BLOCKS_LENGTH]; } terrainPopulated = 0; @@ -59,10 +59,11 @@ void LevelChunk::init(Level* level, int x, int z) { this->z = z; MemSect(1); heightmap = byteArray(16 * 16); - { std::lock_guard lock(m_csEntities); - for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { - entityBlocks[i] = new std::vector >(); - } + { + std::lock_guard lock(m_csEntities); + for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { + entityBlocks[i] = new std::vector >(); + } } MemSect(0); @@ -224,61 +225,63 @@ void LevelChunk::setUnsaved(bool unsaved) { void LevelChunk::stopSharingTilesAndData() { #if defined(SHARING_ENABLED) - { std::lock_guard lock(m_csSharing); - lastUnsharedTime = System::currentTimeMillis(); - if (!sharingTilesAndData) { - return; - } + { + std::lock_guard lock(m_csSharing); + lastUnsharedTime = System::currentTimeMillis(); + if (!sharingTilesAndData) { + return; + } - // If we've got a reference to a server chunk's terrainPopulated flag that - // this LevelChunk is sharing with, then don't consider unsharing if it - // hasn't been set. This is because post-processing things that update the - // server chunks won't actually cause the server to send any updates to the - // tiles that they alter, so they completely depend on the data not being - // shared for it to get from the server to here - if ((serverTerrainPopulated) && - (((*serverTerrainPopulated) & sTerrainPopulatedAllAffecting) != - sTerrainPopulatedAllAffecting)) { - return; - } + // If we've got a reference to a server chunk's terrainPopulated flag + // that this LevelChunk is sharing with, then don't consider unsharing + // if it hasn't been set. This is because post-processing things that + // update the server chunks won't actually cause the server to send any + // updates to the tiles that they alter, so they completely depend on + // the data not being shared for it to get from the server to here + if ((serverTerrainPopulated) && + (((*serverTerrainPopulated) & sTerrainPopulatedAllAffecting) != + sTerrainPopulatedAllAffecting)) { + return; + } - // If this is the empty chunk, then it will have a x & z of 0,0 - if we - // don't drop out here we'll end up unsharing the chunk at this location for - // no reason - if (isEmpty()) { - return; - } + // If this is the empty chunk, then it will have a x & z of 0,0 - if we + // don't drop out here we'll end up unsharing the chunk at this location + // for no reason + if (isEmpty()) { + return; + } - MemSect(47); + MemSect(47); - // Changed to used compressed storage - these CTORs make deep copies of the - // storage passed as a parameter - lowerBlocks = new CompressedTileStorage(lowerBlocks); + // Changed to used compressed storage - these CTORs make deep copies of + // the storage passed as a parameter + lowerBlocks = new CompressedTileStorage(lowerBlocks); - // Changed to use new sparse data storage - this CTOR makes a deep copy of - // the storage passed as a parameter - lowerData = new SparseDataStorage(lowerData); + // Changed to use new sparse data storage - this CTOR makes a deep copy + // of the storage passed as a parameter + lowerData = new SparseDataStorage(lowerData); - if (Level::maxBuildHeight > Level::COMPRESSED_CHUNK_SECTION_HEIGHT) { - upperBlocks = new CompressedTileStorage(upperBlocks); - upperData = new SparseDataStorage(upperData); - } else { - upperBlocks = nullptr; - upperData = nullptr; - } + if (Level::maxBuildHeight > Level::COMPRESSED_CHUNK_SECTION_HEIGHT) { + upperBlocks = new CompressedTileStorage(upperBlocks); + upperData = new SparseDataStorage(upperData); + } else { + upperBlocks = nullptr; + upperData = nullptr; + } - /* - newDataLayer = new DataLayer(skyLight->data.length*2, level->depthBits); - XMemCpy(newDataLayer->data.data, skyLight->data.data, - skyLight->data.length); skyLight = newDataLayer; + /* + newDataLayer = new DataLayer(skyLight->data.length*2, level->depthBits); + XMemCpy(newDataLayer->data.data, skyLight->data.data, + skyLight->data.length); skyLight = newDataLayer; - newDataLayer = new DataLayer(blockLight->data.length*2, level->depthBits); - XMemCpy(newDataLayer->data.data, blockLight->data.data, - blockLight->data.length); blockLight = newDataLayer; - */ + newDataLayer = new DataLayer(blockLight->data.length*2, + level->depthBits); XMemCpy(newDataLayer->data.data, + blockLight->data.data, blockLight->data.length); blockLight = + newDataLayer; + */ - sharingTilesAndData = false; - MemSect(0); + sharingTilesAndData = false; + MemSect(0); } #endif } @@ -290,108 +293,110 @@ void LevelChunk::stopSharingTilesAndData() { // not sharing void LevelChunk::reSyncLighting() { #if defined(SHARING_ENABLED) - { std::lock_guard lock(m_csSharing); + { + std::lock_guard lock(m_csSharing); - if (isEmpty()) { - return; - } + if (isEmpty()) { + return; + } #if defined(_LARGE_WORLDS) - LevelChunk* lc = MinecraftServer::getInstance() - ->getLevel(level->dimension->id) - ->cache->getChunkLoadedOrUnloaded(x, z); + LevelChunk* lc = MinecraftServer::getInstance() + ->getLevel(level->dimension->id) + ->cache->getChunkLoadedOrUnloaded(x, z); #else - LevelChunk* lc = MinecraftServer::getInstance() - ->getLevel(level->dimension->id) - ->cache->getChunk(x, z); + LevelChunk* lc = MinecraftServer::getInstance() + ->getLevel(level->dimension->id) + ->cache->getChunk(x, z); #endif - GameRenderer::AddForDelete(lowerSkyLight); - lowerSkyLight = new SparseLightStorage(lc->lowerSkyLight); - GameRenderer::FinishedReassigning(); - GameRenderer::AddForDelete(lowerBlockLight); - lowerBlockLight = new SparseLightStorage(lc->lowerBlockLight); - GameRenderer::FinishedReassigning(); + GameRenderer::AddForDelete(lowerSkyLight); + lowerSkyLight = new SparseLightStorage(lc->lowerSkyLight); + GameRenderer::FinishedReassigning(); + GameRenderer::AddForDelete(lowerBlockLight); + lowerBlockLight = new SparseLightStorage(lc->lowerBlockLight); + GameRenderer::FinishedReassigning(); - if (Level::maxBuildHeight > Level::COMPRESSED_CHUNK_SECTION_HEIGHT) { - GameRenderer::AddForDelete(upperSkyLight); - upperSkyLight = new SparseLightStorage(lc->upperSkyLight); - GameRenderer::FinishedReassigning(); - GameRenderer::AddForDelete(upperBlockLight); - upperBlockLight = new SparseLightStorage(lc->upperBlockLight); - GameRenderer::FinishedReassigning(); - } + if (Level::maxBuildHeight > Level::COMPRESSED_CHUNK_SECTION_HEIGHT) { + GameRenderer::AddForDelete(upperSkyLight); + upperSkyLight = new SparseLightStorage(lc->upperSkyLight); + GameRenderer::FinishedReassigning(); + GameRenderer::AddForDelete(upperBlockLight); + upperBlockLight = new SparseLightStorage(lc->upperBlockLight); + GameRenderer::FinishedReassigning(); + } } #endif } void LevelChunk::startSharingTilesAndData(int forceMs) { #if defined(SHARING_ENABLED) - { std::lock_guard lock(m_csSharing); - if (sharingTilesAndData) { - return; - } + { + std::lock_guard lock(m_csSharing); + if (sharingTilesAndData) { + return; + } - // If this is the empty chunk, then it will have a x & z of 0,0 - we'll end - // up potentially loading the 0,0 block if we proceed. And it obviously - // doesn't make sense to go resharing the 0,0 block on behalf of an empty - // chunk either - if (isEmpty()) { - return; - } + // If this is the empty chunk, then it will have a x & z of 0,0 - we'll + // end up potentially loading the 0,0 block if we proceed. And it + // obviously doesn't make sense to go resharing the 0,0 block on behalf + // of an empty chunk either + if (isEmpty()) { + return; + } #if defined(_LARGE_WORLDS) - LevelChunk* lc = MinecraftServer::getInstance() - ->getLevel(level->dimension->id) - ->cache->getChunkLoadedOrUnloaded(x, z); + LevelChunk* lc = MinecraftServer::getInstance() + ->getLevel(level->dimension->id) + ->cache->getChunkLoadedOrUnloaded(x, z); #else - LevelChunk* lc = MinecraftServer::getInstance() - ->getLevel(level->dimension->id) - ->cache->getChunk(x, z); + LevelChunk* lc = MinecraftServer::getInstance() + ->getLevel(level->dimension->id) + ->cache->getChunk(x, z); #endif - // In normal usage, chunks should only reshare if their local data matched - // that on the server. The forceMs parameter though can be used to force a - // share if resharing hasn't happened after a period of time - if (forceMs == 0) { - // Normal behaviour - just check that the data matches, and don't start - // sharing data if it doesn't (yet) - if (!lowerBlocks->isSameAs(lc->lowerBlocks) || - (upperBlocks && lc->upperBlocks && - !upperBlocks->isSameAs(lc->upperBlocks))) { - return; + // In normal usage, chunks should only reshare if their local data + // matched that on the server. The forceMs parameter though can be used + // to force a share if resharing hasn't happened after a period of time + if (forceMs == 0) { + // Normal behaviour - just check that the data matches, and don't + // start sharing data if it doesn't (yet) + if (!lowerBlocks->isSameAs(lc->lowerBlocks) || + (upperBlocks && lc->upperBlocks && + !upperBlocks->isSameAs(lc->upperBlocks))) { + return; + } + } else { + // Only force if it has been more than forceMs milliseconds since we + // last wanted to unshare this chunk + int64_t timenow = System::currentTimeMillis(); + if ((timenow - lastUnsharedTime) < forceMs) { + return; + } } - } else { - // Only force if it has been more than forceMs milliseconds since we - // last wanted to unshare this chunk - int64_t timenow = System::currentTimeMillis(); - if ((timenow - lastUnsharedTime) < forceMs) { - return; - } - } - // Note - data that was shared isn't directly deleted here, as it might - // still be in use in the game render update thread. Let that thread delete - // it when it is safe to do so instead. - GameRenderer::AddForDelete(lowerBlocks); - lowerBlocks = lc->lowerBlocks; - GameRenderer::FinishedReassigning(); - - GameRenderer::AddForDelete(lowerData); - lowerData = lc->lowerData; - GameRenderer::FinishedReassigning(); - - if (Level::maxBuildHeight > Level::COMPRESSED_CHUNK_SECTION_HEIGHT) { - GameRenderer::AddForDelete(upperBlocks); - upperBlocks = lc->upperBlocks; + // Note - data that was shared isn't directly deleted here, as it might + // still be in use in the game render update thread. Let that thread + // delete it when it is safe to do so instead. + GameRenderer::AddForDelete(lowerBlocks); + lowerBlocks = lc->lowerBlocks; GameRenderer::FinishedReassigning(); - GameRenderer::AddForDelete(upperData); - upperData = lc->upperData; + GameRenderer::AddForDelete(lowerData); + lowerData = lc->lowerData; GameRenderer::FinishedReassigning(); - } - sharingTilesAndData = true; + if (Level::maxBuildHeight > Level::COMPRESSED_CHUNK_SECTION_HEIGHT) { + GameRenderer::AddForDelete(upperBlocks); + upperBlocks = lc->upperBlocks; + GameRenderer::FinishedReassigning(); + + GameRenderer::AddForDelete(upperData); + upperData = lc->upperData; + GameRenderer::FinishedReassigning(); + } + + sharingTilesAndData = true; } #endif } @@ -1150,8 +1155,9 @@ void LevelChunk::addEntity(std::shared_ptr e) { e->yChunk = yc; e->zChunk = z; - { std::lock_guard lock(m_csEntities); - entityBlocks[yc]->push_back(e); + { + std::lock_guard lock(m_csEntities); + entityBlocks[yc]->push_back(e); } } @@ -1163,19 +1169,19 @@ void LevelChunk::removeEntity(std::shared_ptr e, int yc) { if (yc < 0) yc = 0; if (yc >= ENTITY_BLOCKS_LENGTH) yc = ENTITY_BLOCKS_LENGTH - 1; - { std::lock_guard lock(m_csEntities); - - // 4J - was entityBlocks[yc]->remove(e); - auto it = find(entityBlocks[yc]->begin(), entityBlocks[yc]->end(), e); - if (it != entityBlocks[yc]->end()) { - entityBlocks[yc]->erase(it); - // 4J - we don't want storage creeping up here as thinkgs move round the - // world accumulating up spare space - MemSect(31); - entityBlocks[yc]->shrink_to_fit(); - MemSect(0); - } + { + std::lock_guard lock(m_csEntities); + // 4J - was entityBlocks[yc]->remove(e); + auto it = find(entityBlocks[yc]->begin(), entityBlocks[yc]->end(), e); + if (it != entityBlocks[yc]->end()) { + entityBlocks[yc]->erase(it); + // 4J - we don't want storage creeping up here as thinkgs move round + // the world accumulating up spare space + MemSect(31); + entityBlocks[yc]->shrink_to_fit(); + MemSect(0); + } } } @@ -1201,50 +1207,56 @@ std::shared_ptr LevelChunk::getTileEntity(int x, int y, int z) { // insert when we don't want one) // shared_ptr tileEntity = tileEntities[pos]; std::shared_ptr tileEntity = nullptr; - { std::unique_lock lock(m_csTileEntities); - auto it = tileEntities.find(pos); + { + std::unique_lock lock(m_csTileEntities); + auto it = tileEntities.find(pos); - if (it == tileEntities.end()) { - lock.unlock(); // Note: don't assume iterator is valid for - // tileEntities after this point + if (it == tileEntities.end()) { + lock.unlock(); // Note: don't assume iterator is valid for + // tileEntities after this point - // Fix for #48450 - All: Code Defect: Hang: Game hangs in tutorial, when - // player arrive at the particular coordinate 4J Stu - Chests try to get - // their neighbours when being destroyed, which then causes new tile - // entities to be created if the neighbour has already been destroyed - if (level->m_bDisableAddNewTileEntities) return nullptr; + // Fix for #48450 - All: Code Defect: Hang: Game hangs in tutorial, + // when player arrive at the particular coordinate 4J Stu - Chests + // try to get their neighbours when being destroyed, which then + // causes new tile entities to be created if the neighbour has + // already been destroyed + if (level->m_bDisableAddNewTileEntities) return nullptr; - int t = getTile(x, y, z); - if (t <= 0 || !Tile::tiles[t]->isEntityTile()) return nullptr; + int t = getTile(x, y, z); + if (t <= 0 || !Tile::tiles[t]->isEntityTile()) return nullptr; - // 4J-PB changed from this in 1.7.3 - // EntityTile *et = (EntityTile *) Tile::tiles[t]; - // et->onPlace(level, this->x * 16 + x, y, this->z * 16 + z); + // 4J-PB changed from this in 1.7.3 + // EntityTile *et = (EntityTile *) Tile::tiles[t]; + // et->onPlace(level, this->x * 16 + x, y, this->z * 16 + z); - // if (tileEntity == nullptr) - //{ - tileEntity = - dynamic_cast(Tile::tiles[t])->newTileEntity(level); - level->setTileEntity(this->x * 16 + x, y, this->z * 16 + z, tileEntity); - //} + // if (tileEntity == nullptr) + //{ + tileEntity = + dynamic_cast(Tile::tiles[t])->newTileEntity(level); + level->setTileEntity(this->x * 16 + x, y, this->z * 16 + z, + tileEntity); + //} - // tileEntity = tileEntities[pos]; // 4J - TODO - this - // doesn't seem right - assignment wrong way? Check + // tileEntity = tileEntities[pos]; // 4J - TODO - this + // doesn't seem right - assignment wrong way? Check - // 4J Stu - It should have been inserted by now, but check to be sure - { std::lock_guard lock2(m_csTileEntities); - auto newIt = tileEntities.find(pos); - if (newIt != tileEntities.end()) { - tileEntity = newIt->second; + // 4J Stu - It should have been inserted by now, but check to be + // sure + { + std::lock_guard lock2(m_csTileEntities); + auto newIt = tileEntities.find(pos); + if (newIt != tileEntities.end()) { + tileEntity = newIt->second; + } + } + } else { + tileEntity = it->second; } - } - } else { - tileEntity = it->second; - } } if (tileEntity != nullptr && tileEntity->isRemoved()) { - { std::lock_guard lock(m_csTileEntities); - tileEntities.erase(pos); + { + std::lock_guard lock(m_csTileEntities); + tileEntities.erase(pos); } return nullptr; } @@ -1259,7 +1271,8 @@ void LevelChunk::addTileEntity(std::shared_ptr te) { setTileEntity(xx, yy, zz, te); if (loaded) { { - std::lock_guard lock(level->m_tileEntityListCS); + std::lock_guard lock( + level->m_tileEntityListCS); level->tileEntityList.push_back(te); } } @@ -1289,8 +1302,9 @@ void LevelChunk::setTileEntity(int x, int y, int z, tileEntity->clearRemoved(); - { std::lock_guard lock(m_csTileEntities); - tileEntities[pos] = tileEntity; + { + std::lock_guard lock(m_csTileEntities); + tileEntities[pos] = tileEntity; } } @@ -1303,20 +1317,21 @@ void LevelChunk::removeTileEntity(int x, int y, int z) { // if (removeThis != null) { // removeThis.setRemoved(); // } - { std::lock_guard lock(m_csTileEntities); - auto it = tileEntities.find(pos); - if (it != tileEntities.end()) { - std::shared_ptr te = tileEntities[pos]; - tileEntities.erase(pos); - if (te != nullptr) { - if (level->isClientSide) { - app.DebugPrintf("Removing tile entity of type %d\n", - te->GetType()); + { + std::lock_guard lock(m_csTileEntities); + auto it = tileEntities.find(pos); + if (it != tileEntities.end()) { + std::shared_ptr te = tileEntities[pos]; + tileEntities.erase(pos); + if (te != nullptr) { + if (level->isClientSide) { + app.DebugPrintf("Removing tile entity of type %d\n", + te->GetType()); + } + te->setRemoved(); } - te->setRemoved(); } } - } } } @@ -1361,17 +1376,20 @@ void LevelChunk::load() { #endif std::vector > values; - { std::lock_guard lock(m_csTileEntities); - for (auto it = tileEntities.begin(); it != tileEntities.end(); it++) { - values.push_back(it->second); - } + { + std::lock_guard lock(m_csTileEntities); + for (auto it = tileEntities.begin(); it != tileEntities.end(); + it++) { + values.push_back(it->second); + } } level->addAllPendingTileEntities(values); - { std::lock_guard lock(m_csEntities); - for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { - level->addEntities(entityBlocks[i]); - } + { + std::lock_guard lock(m_csEntities); + for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { + level->addEntities(entityBlocks[i]); + } } } else { #if defined(_LARGE_WORLDS) @@ -1385,10 +1403,12 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter loaded = false; if (unloadTileEntities) { std::vector > tileEntitiesToRemove; - { std::lock_guard lock(m_csTileEntities); - for (auto it = tileEntities.begin(); it != tileEntities.end(); it++) { - tileEntitiesToRemove.push_back(it->second); - } + { + std::lock_guard lock(m_csTileEntities); + for (auto it = tileEntities.begin(); it != tileEntities.end(); + it++) { + tileEntitiesToRemove.push_back(it->second); + } } auto itEnd = tileEntitiesToRemove.end(); @@ -1398,10 +1418,11 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter } } - { std::lock_guard lock(m_csEntities); - for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { - level->removeEntities(entityBlocks[i]); - } + { + std::lock_guard lock(m_csEntities); + for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { + level->removeEntities(entityBlocks[i]); + } } // app.DebugPrintf("Unloaded chunk %d, %d\n", x, z); @@ -1418,22 +1439,23 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter PIXBeginNamedEvent(0, "Saving entities"); ListTag* entityTags = new ListTag(); - { std::lock_guard lock(m_csEntities); - for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { - auto itEnd = entityBlocks[i]->end(); - for (std::vector >::iterator it = - entityBlocks[i]->begin(); - it != itEnd; it++) { - std::shared_ptr e = *it; - CompoundTag* teTag = new CompoundTag(); - if (e->save(teTag)) { - entityTags->add(teTag); + { + std::lock_guard lock(m_csEntities); + for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { + auto itEnd = entityBlocks[i]->end(); + for (std::vector >::iterator it = + entityBlocks[i]->begin(); + it != itEnd; it++) { + std::shared_ptr e = *it; + CompoundTag* teTag = new CompoundTag(); + if (e->save(teTag)) { + entityTags->add(teTag); + } } - } - // Clear out this list - entityBlocks[i]->clear(); - } + // Clear out this list + entityBlocks[i]->clear(); + } } m_unloadedEntitiesTag->put(L"Entities", entityTags); @@ -1463,16 +1485,17 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter } bool LevelChunk::containsPlayer() { - { std::lock_guard lock(m_csEntities); - for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { - std::vector >* vecEntity = entityBlocks[i]; - for (int j = 0; j < vecEntity->size(); j++) { - if (vecEntity->at(j)->GetType() == eTYPE_SERVERPLAYER) { - return true; + { + std::lock_guard lock(m_csEntities); + for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { + std::vector >* vecEntity = entityBlocks[i]; + for (int j = 0; j < vecEntity->size(); j++) { + if (vecEntity->at(j)->GetType() == eTYPE_SERVERPLAYER) { + return true; + } } } } - } return false; } @@ -1492,31 +1515,32 @@ void LevelChunk::getEntities(std::shared_ptr except, AABB* bb, // AP - locking is expensive so enter once in // Level::getEntities - { std::lock_guard lock(m_csEntities); - for (int yc = yc0; yc <= yc1; yc++) { - std::vector >* entities = entityBlocks[yc]; + { + std::lock_guard lock(m_csEntities); + for (int yc = yc0; yc <= yc1; yc++) { + std::vector >* entities = entityBlocks[yc]; - auto itEnd = entities->end(); - for (auto it = entities->begin(); it != itEnd; it++) { - std::shared_ptr e = *it; // entities->at(i); - if (e != except && e->bb.intersects(*bb) && - (selector == nullptr || selector->matches(e))) { - es.push_back(e); - std::vector >* subs = - e->getSubEntities(); - if (subs != nullptr) { - for (int j = 0; j < subs->size(); j++) { - e = subs->at(j); - if (e != except && e->bb.intersects(*bb) && - (selector == nullptr || selector->matches(e))) { - es.push_back(e); + auto itEnd = entities->end(); + for (auto it = entities->begin(); it != itEnd; it++) { + std::shared_ptr e = *it; // entities->at(i); + if (e != except && e->bb.intersects(*bb) && + (selector == nullptr || selector->matches(e))) { + es.push_back(e); + std::vector >* subs = + e->getSubEntities(); + if (subs != nullptr) { + for (int j = 0; j < subs->size(); j++) { + e = subs->at(j); + if (e != except && e->bb.intersects(*bb) && + (selector == nullptr || selector->matches(e))) { + es.push_back(e); + } } } } } } } - } } void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, @@ -1538,55 +1562,57 @@ void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, // AP - locking is expensive so enter once in // Level::getEntitiesOfClass - { std::lock_guard lock(m_csEntities); - for (int yc = yc0; yc <= yc1; yc++) { - std::vector >* entities = entityBlocks[yc]; + { + std::lock_guard lock(m_csEntities); + for (int yc = yc0; yc <= yc1; yc++) { + std::vector >* entities = entityBlocks[yc]; - auto itEnd = entities->end(); - for (auto it = entities->begin(); it != itEnd; it++) { - std::shared_ptr e = *it; // entities->at(i); + auto itEnd = entities->end(); + for (auto it = entities->begin(); it != itEnd; it++) { + std::shared_ptr e = *it; // entities->at(i); - bool isAssignableFrom = false; - // Some special cases where the base class is a general type that - // our class may be derived from, otherwise do a direct comparison - // of type_info - if (ec == typeid(Player)) - isAssignableFrom = e->instanceof(eTYPE_PLAYER); - else if (ec == typeid(Entity)) - isAssignableFrom = e->instanceof(eTYPE_ENTITY); - else if (ec == typeid(Mob)) - isAssignableFrom = e->instanceof(eTYPE_MOB); - else if (ec == typeid(LivingEntity)) - isAssignableFrom = e->instanceof(eTYPE_LIVINGENTITY); - else if (ec == typeid(ItemEntity)) - isAssignableFrom = e->instanceof(eTYPE_ITEMENTITY); - else if (ec == typeid(Minecart)) - isAssignableFrom = e->instanceof(eTYPE_MINECART); - else if (ec == typeid(Monster)) - isAssignableFrom = e->instanceof(eTYPE_MONSTER); - else if (ec == typeid(Zombie)) - isAssignableFrom = e->instanceof(eTYPE_ZOMBIE); - else if (Entity* entity = e.get(); - entity != nullptr && ec == typeid(*entity)) - isAssignableFrom = true; - if (isAssignableFrom && e->bb.intersects(*bb)) { - if (selector == nullptr || selector->matches(e)) { - es.push_back(e); + bool isAssignableFrom = false; + // Some special cases where the base class is a general type + // that our class may be derived from, otherwise do a direct + // comparison of type_info + if (ec == typeid(Player)) + isAssignableFrom = e->instanceof(eTYPE_PLAYER); + else if (ec == typeid(Entity)) + isAssignableFrom = e->instanceof(eTYPE_ENTITY); + else if (ec == typeid(Mob)) + isAssignableFrom = e->instanceof(eTYPE_MOB); + else if (ec == typeid(LivingEntity)) + isAssignableFrom = e->instanceof(eTYPE_LIVINGENTITY); + else if (ec == typeid(ItemEntity)) + isAssignableFrom = e->instanceof(eTYPE_ITEMENTITY); + else if (ec == typeid(Minecart)) + isAssignableFrom = e->instanceof(eTYPE_MINECART); + else if (ec == typeid(Monster)) + isAssignableFrom = e->instanceof(eTYPE_MONSTER); + else if (ec == typeid(Zombie)) + isAssignableFrom = e->instanceof(eTYPE_ZOMBIE); + else if (Entity* entity = e.get(); + entity != nullptr && ec == typeid(*entity)) + isAssignableFrom = true; + if (isAssignableFrom && e->bb.intersects(*bb)) { + if (selector == nullptr || selector->matches(e)) { + es.push_back(e); + } } + // 4J - note needs to be equivalent to + // baseClass.isAssignableFrom(e.getClass()) } - // 4J - note needs to be equivalent to - // baseClass.isAssignableFrom(e.getClass()) } } - } } int LevelChunk::countEntities() { int entityCount = 0; - { std::lock_guard lock(m_csEntities); - for (int yc = 0; yc < ENTITY_BLOCKS_LENGTH; yc++) { - entityCount += (int)entityBlocks[yc]->size(); - } + { + std::lock_guard lock(m_csEntities); + for (int yc = 0; yc < ENTITY_BLOCKS_LENGTH; yc++) { + entityCount += (int)entityBlocks[yc]->size(); + } } return entityCount; } @@ -2131,11 +2157,12 @@ void LevelChunk::compressBlocks() { // Note - only the extraction of the pointers needs to be done in the // lock, since even if the data is unshared whilst we are // processing this data is still valid (for the server) - { std::lock_guard lock(m_csSharing); - if (sharingTilesAndData) { - blocksToCompressLower = lowerBlocks; - blocksToCompressUpper = upperBlocks; - } + { + std::lock_guard lock(m_csSharing); + if (sharingTilesAndData) { + blocksToCompressLower = lowerBlocks; + blocksToCompressUpper = upperBlocks; + } } } else { // Not the host, simple case @@ -2230,11 +2257,12 @@ void LevelChunk::compressData() { // Note - only the extraction of the pointers needs to be done in the // lock, since even if the data is unshared whilst we are // processing this data is still valid (for the server) - { std::lock_guard lock(m_csSharing); - if (sharingTilesAndData) { - dataToCompressLower = lowerData; - dataToCompressUpper = upperData; - } + { + std::lock_guard lock(m_csSharing); + if (sharingTilesAndData) { + dataToCompressLower = lowerData; + dataToCompressUpper = upperData; + } } } else { // Not the host, simple case diff --git a/Minecraft.World/Level/Storage/CompressedTileStorage.cpp b/Minecraft.World/Level/Storage/CompressedTileStorage.cpp index 46c1da9eb..a2b3f921c 100644 --- a/Minecraft.World/Level/Storage/CompressedTileStorage.cpp +++ b/Minecraft.World/Level/Storage/CompressedTileStorage.cpp @@ -33,16 +33,17 @@ CompressedTileStorage::CompressedTileStorage() { } CompressedTileStorage::CompressedTileStorage(CompressedTileStorage* copyFrom) { - { std::lock_guard lock(cs_write); - allocatedSize = copyFrom->allocatedSize; - if (allocatedSize > 0) { - indicesAndData = (unsigned char*)XPhysicalAlloc( - allocatedSize, MAXULONG_PTR, 4096, - PAGE_READWRITE); //(unsigned char *)malloc(allocatedSize); - XMemCpy(indicesAndData, copyFrom->indicesAndData, allocatedSize); - } else { - indicesAndData = nullptr; - } + { + std::lock_guard lock(cs_write); + allocatedSize = copyFrom->allocatedSize; + if (allocatedSize > 0) { + indicesAndData = (unsigned char*)XPhysicalAlloc( + allocatedSize, MAXULONG_PTR, 4096, + PAGE_READWRITE); //(unsigned char *)malloc(allocatedSize); + XMemCpy(indicesAndData, copyFrom->indicesAndData, allocatedSize); + } else { + indicesAndData = nullptr; + } } #if defined(PSVITA_PRECOMPUTED_TABLE) diff --git a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp index bba7b774a..27808d7af 100644 --- a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp @@ -184,8 +184,9 @@ void McRegionChunkStorage::save(Level* level, LevelChunk* levelChunk) { // Note - have added use of a mutex round sections of code that // do a lot of memory alloc/free operations. This is because when we are - // running saves on multiple threads these sections have a lot of contention. - // Better to let each thread have its turn at a higher level of granularity. + // running saves on multiple threads these sections have a lot of + // contention. Better to let each thread have its turn at a higher level of + // granularity. MemSect(30); PIXBeginNamedEvent(0, "Getting output stream\n"); DataOutputStream* output = RegionFileCache::getChunkDataOutputStream( @@ -199,22 +200,24 @@ void McRegionChunkStorage::save(Level* level, LevelChunk* levelChunk) { PIXEndNamedEvent(); PIXBeginNamedEvent(0, "Updating chunk queue"); - { std::lock_guard lock(cs_memory); - s_chunkDataQueue.push_back(output); + { + std::lock_guard lock(cs_memory); + s_chunkDataQueue.push_back(output); } PIXEndNamedEvent(); } else { CompoundTag* tag; - { std::lock_guard lock(cs_memory); - PIXBeginNamedEvent(0, "Creating tags\n"); - tag = new CompoundTag(); - CompoundTag* levelData = new CompoundTag(); - tag->put(L"Level", levelData); - OldChunkStorage::save(levelChunk, level, levelData); - PIXEndNamedEvent(); - PIXBeginNamedEvent(0, "NbtIo writing\n"); - NbtIo::write(tag, output); - PIXEndNamedEvent(); + { + std::lock_guard lock(cs_memory); + PIXBeginNamedEvent(0, "Creating tags\n"); + tag = new CompoundTag(); + CompoundTag* levelData = new CompoundTag(); + tag->put(L"Level", levelData); + OldChunkStorage::save(levelChunk, level, levelData); + PIXEndNamedEvent(); + PIXBeginNamedEvent(0, "NbtIo writing\n"); + NbtIo::write(tag, output); + PIXEndNamedEvent(); } PIXBeginNamedEvent(0, "Output closing\n"); output->close(); @@ -223,11 +226,12 @@ void McRegionChunkStorage::save(Level* level, LevelChunk* levelChunk) { // 4J Stu - getChunkDataOutputStream makes a new DataOutputStream that // points to a new ChunkBuffer( ByteArrayOutputStream ) We should clean // these up when we are done - { std::lock_guard lock(cs_memory); - PIXBeginNamedEvent(0, "Cleaning up\n"); - output->deleteChildStream(); - delete output; - delete tag; + { + std::lock_guard lock(cs_memory); + PIXBeginNamedEvent(0, "Cleaning up\n"); + output->deleteChildStream(); + delete output; + delete tag; } PIXEndNamedEvent(); } @@ -355,32 +359,34 @@ int McRegionChunkStorage::runSaveThreadProc(void* lpParam) { DataOutputStream* dos = nullptr; while (running) { - { std::unique_lock lock(cs_memory, std::try_to_lock); - if (lock.owns_lock()) { - lastQueueSize = s_chunkDataQueue.size(); - if (lastQueueSize > 0) { - dos = s_chunkDataQueue.front(); - s_chunkDataQueue.pop_front(); - } - s_runningThreadCount++; - lock.unlock(); + { + std::unique_lock lock(cs_memory, std::try_to_lock); + if (lock.owns_lock()) { + lastQueueSize = s_chunkDataQueue.size(); + if (lastQueueSize > 0) { + dos = s_chunkDataQueue.front(); + s_chunkDataQueue.pop_front(); + } + s_runningThreadCount++; + lock.unlock(); - if (dos) { - PIXBeginNamedEvent(0, "Saving chunk"); - // app.DebugPrintf("Compressing chunk data (%d left)\n", - // lastQueueSize - 1); - dos->close(); - dos->deleteChildStream(); - PIXEndNamedEvent(); - } - delete dos; - dos = nullptr; + if (dos) { + PIXBeginNamedEvent(0, "Saving chunk"); + // app.DebugPrintf("Compressing chunk data (%d left)\n", + // lastQueueSize - 1); + dos->close(); + dos->deleteChildStream(); + PIXEndNamedEvent(); + } + delete dos; + dos = nullptr; - { std::lock_guard lock2(cs_memory); - s_runningThreadCount--; + { + std::lock_guard lock2(cs_memory); + s_runningThreadCount--; + } } } - } // If there was more than one thing in the queue last time we checked, // then we want to spin round again soon Otherwise wait a bit longer @@ -404,30 +410,34 @@ void McRegionChunkStorage::WaitIfTooManyQueuedChunks() { WaitForSaves(); } void McRegionChunkStorage::WaitForAllSaves() { // Wait for there to be no more tasks to be processed... size_t queueSize; - { std::lock_guard lock(cs_memory); - queueSize = s_chunkDataQueue.size(); + { + std::lock_guard lock(cs_memory); + queueSize = s_chunkDataQueue.size(); } while (queueSize > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); - { std::lock_guard lock(cs_memory); - queueSize = s_chunkDataQueue.size(); + { + std::lock_guard lock(cs_memory); + queueSize = s_chunkDataQueue.size(); } } // And then wait for there to be no running threads that are processing // these tasks int runningThreadCount; - { std::lock_guard lock(cs_memory); - runningThreadCount = s_runningThreadCount; + { + std::lock_guard lock(cs_memory); + runningThreadCount = s_runningThreadCount; } while (runningThreadCount > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); - { std::lock_guard lock(cs_memory); - runningThreadCount = s_runningThreadCount; + { + std::lock_guard lock(cs_memory); + runningThreadCount = s_runningThreadCount; } } } @@ -439,16 +449,18 @@ void McRegionChunkStorage::WaitForSaves() { // Wait for the queue to reduce to a level where we should add more elements size_t queueSize; - { std::lock_guard lock(cs_memory); - queueSize = s_chunkDataQueue.size(); + { + std::lock_guard lock(cs_memory); + queueSize = s_chunkDataQueue.size(); } if (queueSize > MAX_QUEUE_SIZE) { while (queueSize > DESIRED_QUEUE_SIZE) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); - { std::lock_guard lock(cs_memory); - queueSize = s_chunkDataQueue.size(); + { + std::lock_guard lock(cs_memory); + queueSize = s_chunkDataQueue.size(); } } } diff --git a/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp b/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp index c1b151104..92b41eb56 100644 --- a/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp @@ -218,7 +218,8 @@ void ZonedChunkStorage::saveEntities(Level* level, LevelChunk* lc) { { std::lock_guard lock(lc->m_csEntities); for (int i = 0; i < LevelChunk::ENTITY_BLOCKS_LENGTH; i++) { - std::vector >* entities = lc->entityBlocks[i]; + std::vector >* entities = + lc->entityBlocks[i]; auto itEndTags = entities->end(); for (auto it = entities->begin(); it != itEndTags; it++) { diff --git a/Minecraft.World/Network/Connection.cpp b/Minecraft.World/Network/Connection.cpp index 6b5849d20..871560dc2 100644 --- a/Minecraft.World/Network/Connection.cpp +++ b/Minecraft.World/Network/Connection.cpp @@ -462,7 +462,8 @@ void Connection::tick() { { std::lock_guard lock(incoming_cs); while (!disconnected && !g_NetworkManager.IsLeavingGame() && - g_NetworkManager.IsInSession() && !incoming.empty() && max-- >= 0) { + g_NetworkManager.IsInSession() && !incoming.empty() && + max-- >= 0) { std::shared_ptr packet = incoming.front(); packetsToHandle.push_back(packet); incoming.pop(); diff --git a/Minecraft.World/Network/Connection.h b/Minecraft.World/Network/Connection.h index 4cf68a8b1..7759e6c1f 100644 --- a/Minecraft.World/Network/Connection.h +++ b/Minecraft.World/Network/Connection.h @@ -55,7 +55,7 @@ private: bool running; std::queue > - incoming; // 4J - was using synchronizedList... + incoming; // 4J - was using synchronizedList... std::mutex incoming_cs; // ... now has this mutex std::queue > outgoing; // 4J - was using synchronizedList - but don't think it is diff --git a/Minecraft.World/Network/Socket.cpp b/Minecraft.World/Network/Socket.cpp index c0d16bd82..120cd5700 100644 --- a/Minecraft.World/Network/Socket.cpp +++ b/Minecraft.World/Network/Socket.cpp @@ -47,7 +47,8 @@ void Socket::Initialise(ServerConnection* serverConnection) { // Streams already exist – just reset queue state and re-open streams. for (int i = 0; i < 2; i++) { { - std::unique_lock lock(s_hostQueueLock[i], std::try_to_lock); + std::unique_lock lock(s_hostQueueLock[i], + std::try_to_lock); if (lock.owns_lock()) { // Clear the queue std::queue empty; @@ -246,7 +247,8 @@ int Socket::SocketInputStreamLocal::read() { while (m_streamOpen && ShutdownManager::ShouldRun( ShutdownManager::eConnectionReadThreads)) { { - std::unique_lock lock(s_hostQueueLock[m_queueIdx], std::try_to_lock); + std::unique_lock lock(s_hostQueueLock[m_queueIdx], + std::try_to_lock); if (lock.owns_lock()) { if (s_hostQueue[m_queueIdx].size()) { std::uint8_t retval = s_hostQueue[m_queueIdx].front(); @@ -272,7 +274,8 @@ int Socket::SocketInputStreamLocal::read(byteArray b, unsigned int offset, unsigned int length) { while (m_streamOpen) { { - std::unique_lock lock(s_hostQueueLock[m_queueIdx], std::try_to_lock); + std::unique_lock lock(s_hostQueueLock[m_queueIdx], + std::try_to_lock); if (lock.owns_lock()) { if (s_hostQueue[m_queueIdx].size() >= length) { for (unsigned int i = 0; i < length; i++) { @@ -356,7 +359,8 @@ int Socket::SocketInputStreamNetwork::read() { while (m_streamOpen && ShutdownManager::ShouldRun( ShutdownManager::eConnectionReadThreads)) { { - std::unique_lock lock(m_socket->m_queueLockNetwork[m_queueIdx], std::try_to_lock); + std::unique_lock lock( + m_socket->m_queueLockNetwork[m_queueIdx], std::try_to_lock); if (lock.owns_lock()) { if (m_socket->m_queueNetwork[m_queueIdx].size()) { std::uint8_t retval = @@ -383,7 +387,8 @@ int Socket::SocketInputStreamNetwork::read(byteArray b, unsigned int offset, unsigned int length) { while (m_streamOpen) { { - std::unique_lock lock(m_socket->m_queueLockNetwork[m_queueIdx], std::try_to_lock); + std::unique_lock lock( + m_socket->m_queueLockNetwork[m_queueIdx], std::try_to_lock); if (lock.owns_lock()) { if (m_socket->m_queueNetwork[m_queueIdx].size() >= length) { for (unsigned int i = 0; i < length; i++) { @@ -449,7 +454,8 @@ void Socket::SocketOutputStreamNetwork::writeWithFlags(byteArray b, queueIdx = SOCKET_CLIENT_END; { - std::lock_guard lock(m_socket->m_queueLockNetwork[queueIdx]); + std::lock_guard lock( + m_socket->m_queueLockNetwork[queueIdx]); for (unsigned int i = 0; i < length; i++) { m_socket->m_queueNetwork[queueIdx].push(b[offset + i]); } diff --git a/Minecraft.World/Network/Socket.h b/Minecraft.World/Network/Socket.h index 18719598a..6a26e1001 100644 --- a/Minecraft.World/Network/Socket.h +++ b/Minecraft.World/Network/Socket.h @@ -115,7 +115,7 @@ private: // For network connections std::queue m_queueNetwork[2]; // For input data - std::mutex m_queueLockNetwork[2]; // For input data + std::mutex m_queueLockNetwork[2]; // For input data SocketInputStreamNetwork* m_inputStream[2]; SocketOutputStreamNetwork* m_outputStream[2]; bool m_endClosed[2]; diff --git a/Minecraft.World/Util/C4JThread.cpp b/Minecraft.World/Util/C4JThread.cpp index f3ba46fc8..56b620e6d 100644 --- a/Minecraft.World/Util/C4JThread.cpp +++ b/Minecraft.World/Util/C4JThread.cpp @@ -215,14 +215,30 @@ void setPriorityPlatform(std::thread& threadHandle, bool isSelf, using enum C4JThread::ThreadPriority; int niceValue = 0; switch (priority) { - case TimeCritical: niceValue = -15; break; - case Highest: niceValue = -10; break; - case AboveNormal: niceValue = -5; break; - case Normal: niceValue = 0; break; - case BelowNormal: niceValue = 5; break; - case Lowest: niceValue = 10; break; - case Idle: niceValue = 19; break; - default: niceValue = 0; break; + case TimeCritical: + niceValue = -15; + break; + case Highest: + niceValue = -10; + break; + case AboveNormal: + niceValue = -5; + break; + case Normal: + niceValue = 0; + break; + case BelowNormal: + niceValue = 5; + break; + case Lowest: + niceValue = 10; + break; + case Idle: + niceValue = 19; + break; + default: + niceValue = 0; + break; } errno = 0; @@ -401,8 +417,8 @@ bool C4JThread::isMainThread() noexcept { } void C4JThread::setThreadName(std::uint32_t threadId, const char* threadName) { - const char* safe = (threadName && threadName[0] != '\0') ? threadName - : "(4J) Unnamed"; + const char* safe = + (threadName && threadName[0] != '\0') ? threadName : "(4J) Unnamed"; setThreadNamePlatform(threadId, safe); } @@ -477,10 +493,9 @@ std::uint32_t C4JThread::EventArray::waitForSingle(int index, int timeoutMs) { const std::uint32_t bitMask = 1U << static_cast(index); std::unique_lock lock(m_mutex); - if (!waitForCondition(m_condition, lock, timeoutMs, - [this, bitMask] { - return (m_signaledMask & bitMask) != 0U; - })) { + if (!waitForCondition(m_condition, lock, timeoutMs, [this, bitMask] { + return (m_signaledMask & bitMask) != 0U; + })) { return WaitResult::Timeout; } if (m_mode == Mode::AutoClear) m_signaledMask &= ~bitMask; @@ -491,10 +506,9 @@ std::uint32_t C4JThread::EventArray::waitForAll(int timeoutMs) { const std::uint32_t bitMask = buildMaskForSize(m_size); std::unique_lock lock(m_mutex); - if (!waitForCondition(m_condition, lock, timeoutMs, - [this, bitMask] { - return (m_signaledMask & bitMask) == bitMask; - })) { + if (!waitForCondition(m_condition, lock, timeoutMs, [this, bitMask] { + return (m_signaledMask & bitMask) == bitMask; + })) { return WaitResult::Timeout; } if (m_mode == Mode::AutoClear) m_signaledMask &= ~bitMask; @@ -505,15 +519,13 @@ std::uint32_t C4JThread::EventArray::waitForAny(int timeoutMs) { const std::uint32_t bitMask = buildMaskForSize(m_size); std::unique_lock lock(m_mutex); - if (!waitForCondition(m_condition, lock, timeoutMs, - [this, bitMask] { - return (m_signaledMask & bitMask) != 0U; - })) { + if (!waitForCondition(m_condition, lock, timeoutMs, [this, bitMask] { + return (m_signaledMask & bitMask) != 0U; + })) { return WaitResult::Timeout; } - const std::uint32_t readyIndex = - firstSetBitIndex(m_signaledMask & bitMask); + const std::uint32_t readyIndex = firstSetBitIndex(m_signaledMask & bitMask); if (m_mode == Mode::AutoClear) m_signaledMask &= ~(1U << readyIndex); return WaitResult::Signaled + readyIndex; }