mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-06-08 06:32:59 +00:00
perf(render): optimise tile entity cleanup and profiling
This commit is contained in:
parent
51ad1434db
commit
c6fa51d592
|
|
@ -8,6 +8,7 @@
|
|||
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h"
|
||||
#include "LevelRenderer.h"
|
||||
#include "../Utils/FrameProfiler.h"
|
||||
#include <unordered_set>
|
||||
|
||||
#ifdef __PS3__
|
||||
#include "../Platform/PS3/SPU_Tasks/ChunkUpdate/ChunkRebuildData.h"
|
||||
|
|
@ -36,6 +37,66 @@ Tesselator* Chunk::t = Tesselator::getInstance();
|
|||
#endif
|
||||
LevelRenderer* Chunk::levelRenderer;
|
||||
|
||||
void Chunk::reconcileRenderableTileEntities(
|
||||
const std::vector<std::shared_ptr<TileEntity> >& renderableTileEntities) {
|
||||
int key =
|
||||
levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
|
||||
AUTO_VAR(it, globalRenderableTileEntities->find(key));
|
||||
if (!renderableTileEntities.empty()) {
|
||||
std::unordered_set<TileEntity*> currentRenderableTileEntitySet;
|
||||
currentRenderableTileEntitySet.reserve(renderableTileEntities.size());
|
||||
for (size_t i = 0; i < renderableTileEntities.size(); i++) {
|
||||
currentRenderableTileEntitySet.insert(renderableTileEntities[i].get());
|
||||
}
|
||||
|
||||
if (it != globalRenderableTileEntities->end()) {
|
||||
LevelRenderer::RenderableTileEntityBucket& existingBucket =
|
||||
it->second;
|
||||
|
||||
for (AUTO_VAR(it2, existingBucket.tiles.begin());
|
||||
it2 != existingBucket.tiles.end(); it2++) {
|
||||
TileEntity* tileEntity = (*it2).get();
|
||||
if (currentRenderableTileEntitySet.find(tileEntity) ==
|
||||
currentRenderableTileEntitySet.end()) {
|
||||
(*it2)->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
|
||||
levelRenderer->queueRenderableTileEntityForRemoval_Locked(
|
||||
key, tileEntity);
|
||||
} else {
|
||||
(*it2)->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageKeep);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < renderableTileEntities.size(); i++) {
|
||||
renderableTileEntities[i]->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageKeep);
|
||||
if (existingBucket.indexByTile.find(renderableTileEntities[i].get()) ==
|
||||
existingBucket.indexByTile.end()) {
|
||||
levelRenderer->addRenderableTileEntity_Locked(
|
||||
key, renderableTileEntities[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < renderableTileEntities.size(); i++) {
|
||||
renderableTileEntities[i]->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageKeep);
|
||||
levelRenderer->addRenderableTileEntity_Locked(
|
||||
key, renderableTileEntities[i]);
|
||||
}
|
||||
}
|
||||
} else if (it != globalRenderableTileEntities->end()) {
|
||||
for (AUTO_VAR(it2, it->second.tiles.begin());
|
||||
it2 != it->second.tiles.end();
|
||||
it2++) {
|
||||
(*it2)->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
|
||||
levelRenderer->queueRenderableTileEntityForRemoval_Locked(key,
|
||||
(*it2).get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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,
|
||||
|
|
@ -519,57 +580,8 @@ void Chunk::rebuild() {
|
|||
// from the dimension and chunk position (using same index as is used for
|
||||
// global flags)
|
||||
#if 1
|
||||
int key =
|
||||
levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
|
||||
EnterCriticalSection(globalRenderableTileEntities_cs);
|
||||
if (renderableTileEntities.size()) {
|
||||
AUTO_VAR(it, globalRenderableTileEntities->find(key));
|
||||
if (it != globalRenderableTileEntities->end()) {
|
||||
// We've got some renderable tile entities that we want associated
|
||||
// with this chunk, and an existing list of things that used to be.
|
||||
// We need to flag any that we don't need any more to be removed,
|
||||
// keep those that we do, and add any new ones
|
||||
|
||||
// First pass - flag everything already existing to be removed
|
||||
for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
|
||||
it2++) {
|
||||
(*it2)->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
|
||||
}
|
||||
|
||||
// Now go through the current list. If these are already in the
|
||||
// list, then unflag the remove flag. If they aren't, then add
|
||||
for (int i = 0; i < renderableTileEntities.size(); i++) {
|
||||
AUTO_VAR(it2, find(it->second.begin(), it->second.end(),
|
||||
renderableTileEntities[i]));
|
||||
if (it2 == it->second.end()) {
|
||||
(*globalRenderableTileEntities)[key].push_back(
|
||||
renderableTileEntities[i]);
|
||||
} else {
|
||||
(*it2)->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageKeep);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Easy case - nothing already existing for this chunk. Add them all
|
||||
// in.
|
||||
for (int i = 0; i < renderableTileEntities.size(); i++) {
|
||||
(*globalRenderableTileEntities)[key].push_back(
|
||||
renderableTileEntities[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Another easy case - we don't want any renderable tile entities
|
||||
// associated with this chunk. Flag all to be removed.
|
||||
AUTO_VAR(it, globalRenderableTileEntities->find(key));
|
||||
if (it != globalRenderableTileEntities->end()) {
|
||||
for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
|
||||
it2++) {
|
||||
(*it2)->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
reconcileRenderableTileEntities(renderableTileEntities);
|
||||
LeaveCriticalSection(globalRenderableTileEntities_cs);
|
||||
PIXEndNamedEvent();
|
||||
#else
|
||||
|
|
@ -831,57 +843,8 @@ void Chunk::rebuild_SPU() {
|
|||
// from the dimension and chunk position (using same index as is used for
|
||||
// global flags)
|
||||
#if 1
|
||||
int key =
|
||||
levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
|
||||
EnterCriticalSection(globalRenderableTileEntities_cs);
|
||||
if (renderableTileEntities.size()) {
|
||||
AUTO_VAR(it, globalRenderableTileEntities->find(key));
|
||||
if (it != globalRenderableTileEntities->end()) {
|
||||
// We've got some renderable tile entities that we want associated
|
||||
// with this chunk, and an existing list of things that used to be.
|
||||
// We need to flag any that we don't need any more to be removed,
|
||||
// keep those that we do, and add any new ones
|
||||
|
||||
// First pass - flag everything already existing to be removed
|
||||
for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
|
||||
it2++) {
|
||||
(*it2)->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
|
||||
}
|
||||
|
||||
// Now go through the current list. If these are already in the
|
||||
// list, then unflag the remove flag. If they aren't, then add
|
||||
for (int i = 0; i < renderableTileEntities.size(); i++) {
|
||||
AUTO_VAR(it2, find(it->second.begin(), it->second.end(),
|
||||
renderableTileEntities[i]));
|
||||
if (it2 == it->second.end()) {
|
||||
(*globalRenderableTileEntities)[key].push_back(
|
||||
renderableTileEntities[i]);
|
||||
} else {
|
||||
(*it2)->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageKeep);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Easy case - nothing already existing for this chunk. Add them all
|
||||
// in.
|
||||
for (int i = 0; i < renderableTileEntities.size(); i++) {
|
||||
(*globalRenderableTileEntities)[key].push_back(
|
||||
renderableTileEntities[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Another easy case - we don't want any renderable tile entities
|
||||
// associated with this chunk. Flag all to be removed.
|
||||
AUTO_VAR(it, globalRenderableTileEntities->find(key));
|
||||
if (it != globalRenderableTileEntities->end()) {
|
||||
for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
|
||||
it2++) {
|
||||
(*it2)->setRenderRemoveStage(
|
||||
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
reconcileRenderableTileEntities(renderableTileEntities);
|
||||
LeaveCriticalSection(globalRenderableTileEntities_cs);
|
||||
#else
|
||||
// Find the removed ones:
|
||||
|
|
@ -1108,15 +1071,19 @@ uint64_t Chunk::computeConnectivity(const uint8_t* tileIds) {
|
|||
}
|
||||
void Chunk::reset() {
|
||||
if (assigned) {
|
||||
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) {
|
||||
int lists =
|
||||
levelRenderer->getGlobalIndexForChunk(x, y, z, level) * 2;
|
||||
if (refCount == 0 && oldKey != -1) {
|
||||
retireRenderableTileEntities = true;
|
||||
int lists = oldKey * 2;
|
||||
if (lists >= 0) {
|
||||
lists += levelRenderer->chunkLists;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
|
|
@ -1128,6 +1095,10 @@ void Chunk::reset() {
|
|||
}
|
||||
}
|
||||
LeaveCriticalSection(&levelRenderer->m_csDirtyChunks);
|
||||
|
||||
if (retireRenderableTileEntities) {
|
||||
levelRenderer->retireRenderableTileEntitiesForChunkKey(oldKey);
|
||||
}
|
||||
}
|
||||
|
||||
clipChunk->visible = false;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ public:
|
|||
|
||||
private:
|
||||
void translateToPos();
|
||||
void reconcileRenderableTileEntities(
|
||||
const std::vector<std::shared_ptr<TileEntity> >& renderableTileEntities);
|
||||
|
||||
public:
|
||||
void makeCopyForRebuild(Chunk* source);
|
||||
|
|
|
|||
|
|
@ -410,8 +410,12 @@ void LevelRenderer::setLevel(int playerIndex, MultiPlayerLevel* level) {
|
|||
// tile entities in the world dissappear We should only do this when
|
||||
// actually exiting the game, so only when the primary player sets there
|
||||
// level to NULL
|
||||
if (playerIndex == ProfileManager.GetPrimaryPad())
|
||||
if (playerIndex == ProfileManager.GetPrimaryPad()) {
|
||||
EnterCriticalSection(&m_csRenderableTileEntities);
|
||||
renderableTileEntities.clear();
|
||||
m_renderableTileEntitiesPendingRemoval.clear();
|
||||
LeaveCriticalSection(&m_csRenderableTileEntities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -641,34 +645,13 @@ void LevelRenderer::renderEntities(Vec3* cam, Culler* culler, float a) {
|
|||
// Don't render if it isn't in the same dimension as this player
|
||||
if (!isGlobalIndexInSameDimension(idx, level[playerIndex])) continue;
|
||||
|
||||
for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
|
||||
for (AUTO_VAR(it2, it->second.tiles.begin());
|
||||
it2 != it->second.tiles.end();
|
||||
it2++) {
|
||||
TileEntityRenderDispatcher::instance->render(*it2, a);
|
||||
}
|
||||
}
|
||||
|
||||
// Now consider if any of these renderable tile entities have been flagged
|
||||
// for removal, and if so, remove
|
||||
for (AUTO_VAR(it, renderableTileEntities.begin());
|
||||
it != renderableTileEntities.end();) {
|
||||
int idx = it->first;
|
||||
|
||||
for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();) {
|
||||
// If it has been flagged for removal, remove
|
||||
if ((*it2)->shouldRemoveForRender()) {
|
||||
it2 = it->second.erase(it2);
|
||||
} else {
|
||||
it2++;
|
||||
}
|
||||
}
|
||||
|
||||
// If there aren't any entities left for this key, then delete the key
|
||||
if (it->second.size() == 0) {
|
||||
it = renderableTileEntities.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m_csRenderableTileEntities);
|
||||
|
||||
|
|
@ -4181,16 +4164,87 @@ unsigned char LevelRenderer::decGlobalChunkRefCount(int x, int y, int z,
|
|||
}
|
||||
}
|
||||
|
||||
void LevelRenderer::queueRenderableTileEntityForRemoval_Locked(
|
||||
int key, TileEntity* tileEntity) {
|
||||
m_renderableTileEntitiesPendingRemoval[key].insert(tileEntity);
|
||||
}
|
||||
|
||||
void LevelRenderer::addRenderableTileEntity_Locked(
|
||||
int key, const std::shared_ptr<TileEntity>& tileEntity) {
|
||||
RenderableTileEntityBucket& bucket = renderableTileEntities[key];
|
||||
TileEntity* tileEntityPtr = tileEntity.get();
|
||||
if (bucket.indexByTile.find(tileEntityPtr) != bucket.indexByTile.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t index = bucket.tiles.size();
|
||||
bucket.tiles.push_back(tileEntity);
|
||||
bucket.indexByTile.insert(std::make_pair(tileEntityPtr, index));
|
||||
}
|
||||
|
||||
void LevelRenderer::eraseRenderableTileEntity_Locked(
|
||||
RenderableTileEntityBucket& bucket, TileEntity* tileEntity) {
|
||||
auto it = bucket.indexByTile.find(tileEntity);
|
||||
if (it == bucket.indexByTile.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t index = it->second;
|
||||
size_t lastIndex = bucket.tiles.size() - 1;
|
||||
if (index != lastIndex) {
|
||||
std::shared_ptr<TileEntity> moved = bucket.tiles[lastIndex];
|
||||
bucket.tiles[index] = moved;
|
||||
bucket.indexByTile[moved.get()] = index;
|
||||
}
|
||||
|
||||
bucket.tiles.pop_back();
|
||||
bucket.indexByTile.erase(it);
|
||||
}
|
||||
|
||||
void LevelRenderer::retireRenderableTileEntitiesForChunkKey(int key) {
|
||||
if (key == -1) return;
|
||||
|
||||
EnterCriticalSection(&m_csRenderableTileEntities);
|
||||
renderableTileEntities.erase(key);
|
||||
m_renderableTileEntitiesPendingRemoval.erase(key);
|
||||
LeaveCriticalSection(&m_csRenderableTileEntities);
|
||||
}
|
||||
|
||||
// 4J added
|
||||
void LevelRenderer::fullyFlagRenderableTileEntitiesToBeRemoved() {
|
||||
FRAME_PROFILE_SCOPE(RenderableTileEntityCleanup);
|
||||
|
||||
EnterCriticalSection(&m_csRenderableTileEntities);
|
||||
AUTO_VAR(itChunkEnd, renderableTileEntities.end());
|
||||
for (AUTO_VAR(it, renderableTileEntities.begin()); it != itChunkEnd; it++) {
|
||||
AUTO_VAR(itTEEnd, it->second.end());
|
||||
for (AUTO_VAR(it2, it->second.begin()); it2 != itTEEnd; it2++) {
|
||||
(*it2)->upgradeRenderRemoveStage();
|
||||
if (m_renderableTileEntitiesPendingRemoval.empty()) {
|
||||
LeaveCriticalSection(&m_csRenderableTileEntities);
|
||||
return;
|
||||
}
|
||||
|
||||
auto itKeyEnd = m_renderableTileEntitiesPendingRemoval.end();
|
||||
for (auto itKey = m_renderableTileEntitiesPendingRemoval.begin();
|
||||
itKey != itKeyEnd; itKey++) {
|
||||
auto itChunk = renderableTileEntities.find(itKey->first);
|
||||
if (itChunk == renderableTileEntities.end()) continue;
|
||||
|
||||
RenderableTileEntityBucket& bucket = itChunk->second;
|
||||
for (AUTO_VAR(itPending, itKey->second.begin());
|
||||
itPending != itKey->second.end(); itPending++) {
|
||||
if (bucket.indexByTile.find(*itPending) == bucket.indexByTile.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(*itPending)->finalizeRenderRemoveStage()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eraseRenderableTileEntity_Locked(bucket, *itPending);
|
||||
}
|
||||
|
||||
if (bucket.tiles.empty()) {
|
||||
renderableTileEntities.erase(itChunk);
|
||||
}
|
||||
}
|
||||
m_renderableTileEntitiesPendingRemoval.clear();
|
||||
LeaveCriticalSection(&m_csRenderableTileEntities);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#ifdef __PS3__
|
||||
#include "../Platform/PS3/PS3Extras/C4JSpursJob.h"
|
||||
#endif
|
||||
#include <unordered_set>
|
||||
class MultiPlayerLevel;
|
||||
class Textures;
|
||||
class Chunk;
|
||||
|
|
@ -163,8 +164,13 @@ public:
|
|||
void destroyTileProgress(int id, int x, int y, int z, int progress);
|
||||
void registerTextures(IconRegister* iconRegister);
|
||||
|
||||
typedef std::unordered_map<int, std::vector<std::shared_ptr<TileEntity> >,
|
||||
IntKeyHash, IntKeyEq>
|
||||
struct RenderableTileEntityBucket {
|
||||
std::vector<std::shared_ptr<TileEntity> > tiles;
|
||||
std::unordered_map<TileEntity*, size_t> indexByTile;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<int, RenderableTileEntityBucket, IntKeyHash,
|
||||
IntKeyEq>
|
||||
rteMap;
|
||||
|
||||
private:
|
||||
|
|
@ -176,6 +182,10 @@ private:
|
|||
rteMap renderableTileEntities; // 4J - changed - was
|
||||
// std::vector<std::shared_ptr<TileEntity>,
|
||||
// now hashed by chunk so we can find them
|
||||
typedef std::unordered_set<TileEntity*> rtePendingRemovalSet;
|
||||
typedef std::unordered_map<int, rtePendingRemovalSet, IntKeyHash, IntKeyEq>
|
||||
rtePendingRemovalMap;
|
||||
rtePendingRemovalMap m_renderableTileEntitiesPendingRemoval;
|
||||
CRITICAL_SECTION m_csRenderableTileEntities;
|
||||
MultiPlayerLevel* level[4]; // 4J - now one per player
|
||||
Textures* textures;
|
||||
|
|
@ -214,6 +224,14 @@ private:
|
|||
std::unordered_map<int, BlockDestructionProgress*> destroyingBlocks;
|
||||
Icon** breakingTextures;
|
||||
|
||||
void addRenderableTileEntity_Locked(
|
||||
int key, const std::shared_ptr<TileEntity>& tileEntity);
|
||||
void eraseRenderableTileEntity_Locked(
|
||||
RenderableTileEntityBucket& bucket, TileEntity* tileEntity);
|
||||
void queueRenderableTileEntityForRemoval_Locked(int key,
|
||||
TileEntity* tileEntity);
|
||||
void retireRenderableTileEntitiesForChunkKey(int key);
|
||||
|
||||
public:
|
||||
void fullyFlagRenderableTileEntitiesToBeRemoved(); // 4J added
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ constexpr std::array<FrameProfiler::BucketDescriptor, kBucketCount>
|
|||
{Bucket::ChunkBlockFaceCull, "chunkBlockFaceCull"},
|
||||
{Bucket::ChunkBlockLighting, "chunkBlockLighting"},
|
||||
{Bucket::ChunkBlockEmit, "chunkBlockEmit"},
|
||||
{Bucket::RenderableTileEntityCleanup, "renderableTileEntityCleanup"},
|
||||
{Bucket::TileEntityUnloadCleanup, "tileEntityUnloadCleanup"},
|
||||
{Bucket::Entity, "entities"},
|
||||
{Bucket::Particle, "particles"},
|
||||
{Bucket::WeatherSky, "weather"},
|
||||
|
|
@ -133,8 +135,7 @@ inline void recordWorkerBucket(Bucket bucket, std::uint64_t elapsedNs) noexcept
|
|||
return t_threadState.frameScopeDepth != 0;
|
||||
}
|
||||
|
||||
FRAME_PROFILER_NOINLINE
|
||||
[[nodiscard]] bool computeEnabled() noexcept {
|
||||
FRAME_PROFILER_NOINLINE bool computeEnabled() noexcept {
|
||||
const char* const envValue = std::getenv("C4J_FRAME_PROFILER");
|
||||
if (envValue == nullptr) return true;
|
||||
return !envSaysDisabled(envValue);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ public:
|
|||
ChunkBlockFaceCull,
|
||||
ChunkBlockLighting,
|
||||
ChunkBlockEmit,
|
||||
RenderableTileEntityCleanup,
|
||||
TileEntityUnloadCleanup,
|
||||
Entity,
|
||||
Particle,
|
||||
WeatherSky,
|
||||
|
|
|
|||
|
|
@ -187,6 +187,15 @@ void TileEntity::upgradeRenderRemoveStage() {
|
|||
}
|
||||
}
|
||||
|
||||
bool TileEntity::finalizeRenderRemoveStage() {
|
||||
if (renderRemoveStage == e_RenderRemoveStageFlaggedAtChunk) {
|
||||
renderRemoveStage = e_RenderRemoveStageRemove;
|
||||
return true;
|
||||
}
|
||||
|
||||
return renderRemoveStage == e_RenderRemoveStageRemove;
|
||||
}
|
||||
|
||||
// 4J Added
|
||||
void TileEntity::clone(std::shared_ptr<TileEntity> tileEntity) {
|
||||
tileEntity->level = this->level;
|
||||
|
|
@ -195,4 +204,4 @@ void TileEntity::clone(std::shared_ptr<TileEntity> tileEntity) {
|
|||
tileEntity->z = this->z;
|
||||
tileEntity->data = this->data;
|
||||
tileEntity->tile = this->tile;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ public:
|
|||
|
||||
void setRenderRemoveStage(unsigned char stage); // 4J added
|
||||
void upgradeRenderRemoveStage(); // 4J added
|
||||
bool finalizeRenderRemoveStage(); // 4J added
|
||||
bool shouldRemoveForRender(); // 4J added
|
||||
|
||||
virtual Level* getLevel();
|
||||
|
|
@ -77,4 +78,4 @@ public:
|
|||
|
||||
protected:
|
||||
void clone(std::shared_ptr<TileEntity> tileEntity);
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "../../Minecraft.Client/Platform/Common/DLC/DLCPack.h"
|
||||
#include "../../Minecraft.Client/Platform/PS3/PS3Extras/ShutdownManager.h"
|
||||
#include "../../Minecraft.Client/MinecraftServer.h"
|
||||
#include "../../Minecraft.Client/Utils/FrameProfiler.h"
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
|
@ -2206,19 +2207,11 @@ void Level::tickEntities() {
|
|||
// 4J-PB - Stuart - check this is correct here
|
||||
|
||||
if (!tileEntitiesToUnload.empty()) {
|
||||
// tileEntityList.removeAll(tileEntitiesToUnload);
|
||||
FRAME_PROFILE_SCOPE(TileEntityUnloadCleanup);
|
||||
|
||||
for (AUTO_VAR(it, tileEntityList.begin());
|
||||
it != tileEntityList.end();) {
|
||||
bool found = false;
|
||||
for (AUTO_VAR(it2, tileEntitiesToUnload.begin());
|
||||
it2 != tileEntitiesToUnload.end(); it2++) {
|
||||
if ((*it) == (*it2)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
if (tileEntitiesToUnload.find(*it) != tileEntitiesToUnload.end()) {
|
||||
if (isClientSide) {
|
||||
__debugbreak();
|
||||
}
|
||||
|
|
@ -2731,7 +2724,9 @@ void Level::removeTileEntity(int x, int y, int z) {
|
|||
}
|
||||
|
||||
void Level::markForRemoval(std::shared_ptr<TileEntity> entity) {
|
||||
tileEntitiesToUnload.push_back(entity);
|
||||
EnterCriticalSection(&m_tileEntityListCS);
|
||||
tileEntitiesToUnload.insert(entity);
|
||||
LeaveCriticalSection(&m_tileEntityListCS);
|
||||
}
|
||||
|
||||
bool Level::isSolidRenderTile(int x, int y, int z) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "../WorldGen/Biomes/Biome.h"
|
||||
#include "../Util/C4JThread.h"
|
||||
#include <cstdint>
|
||||
#include <unordered_set>
|
||||
|
||||
#ifdef __PSVITA__
|
||||
#include "../../Minecraft.Client/Platform/PSVita/PSVitaExtras/CustomSet.h"
|
||||
|
|
@ -118,7 +119,7 @@ public:
|
|||
|
||||
private:
|
||||
std::vector<std::shared_ptr<TileEntity> > pendingTileEntities;
|
||||
std::vector<std::shared_ptr<TileEntity> > tileEntitiesToUnload;
|
||||
std::unordered_set<std::shared_ptr<TileEntity> > tileEntitiesToUnload;
|
||||
bool updatingTileEntities;
|
||||
|
||||
public:
|
||||
|
|
@ -665,3 +666,4 @@ public:
|
|||
|
||||
bool canCreateMore(eINSTANCEOF type, ESPAWN_TYPE spawnType);
|
||||
};
|
||||
#include <unordered_set>
|
||||
|
|
|
|||
|
|
@ -1558,13 +1558,19 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter
|
|||
{
|
||||
loaded = false;
|
||||
if (unloadTileEntities) {
|
||||
std::vector<std::shared_ptr<TileEntity> > tileEntitiesToRemove;
|
||||
EnterCriticalSection(&m_csTileEntities);
|
||||
for (AUTO_VAR(it, tileEntities.begin()); it != tileEntities.end();
|
||||
it++) {
|
||||
// 4J-PB -m 1.7.3 was it->second->setRemoved();
|
||||
level->markForRemoval(it->second);
|
||||
tileEntitiesToRemove.push_back(it->second);
|
||||
}
|
||||
LeaveCriticalSection(&m_csTileEntities);
|
||||
|
||||
AUTO_VAR(itEnd, tileEntitiesToRemove.end());
|
||||
for (AUTO_VAR(it, tileEntitiesToRemove.begin()); it != itEnd; it++) {
|
||||
// 4J-PB -m 1.7.3 was it->second->setRemoved();
|
||||
level->markForRemoval(*it);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _ENTITIES_RW_SECTION
|
||||
|
|
|
|||
Loading…
Reference in a new issue