fix: particles
This commit is contained in:
@@ -66,6 +66,7 @@
|
||||
#include "FrustumCuller.h"
|
||||
#include "../Minecraft.World/BasicTypeContainers.h"
|
||||
#include "Common/UI/UIScene_SettingsGraphicsMenu.h"
|
||||
#include "ParticleUtils.h"
|
||||
#include <unordered_set>
|
||||
|
||||
//#define DISABLE_SPU_CODE
|
||||
@@ -2853,7 +2854,7 @@ void LevelRenderer::addParticle(ePARTICLE_TYPE eParticleType, double x, double y
|
||||
|
||||
shared_ptr<Particle> LevelRenderer::addParticleInternal(ePARTICLE_TYPE eParticleType, double x, double y, double z, double xa, double ya, double za)
|
||||
{
|
||||
if (mc == nullptr || mc->cameraTargetPlayer == nullptr || mc->particleEngine == nullptr)
|
||||
if (mc == nullptr || mc->cameraTargetPlayer == nullptr || mc->particleEngine == nullptr || mc->options == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@@ -2863,18 +2864,46 @@ shared_ptr<Particle> LevelRenderer::addParticleInternal(ePARTICLE_TYPE eParticle
|
||||
if( Double::isNaN(x) ) return nullptr;
|
||||
if( Double::isNaN(y) ) return nullptr;
|
||||
if( Double::isNaN(z) ) return nullptr;
|
||||
if( Double::isNaN(xa) ) return nullptr;
|
||||
if( Double::isNaN(ya) ) return nullptr;
|
||||
if( Double::isNaN(za) ) return nullptr;
|
||||
|
||||
int particleLevel = mc->options->particles;
|
||||
|
||||
Level *lev;
|
||||
int playerIndex = mc->player->GetXboxPad(); // 4J added
|
||||
lev = level[playerIndex];
|
||||
Level *lev = nullptr;
|
||||
int playerIndex = -1;
|
||||
|
||||
if (particleLevel == 1)
|
||||
shared_ptr<LocalPlayer> sourcePlayer = mc->player;
|
||||
if (sourcePlayer == nullptr && mc->cameraTargetPlayer != nullptr)
|
||||
{
|
||||
sourcePlayer = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
|
||||
}
|
||||
if (sourcePlayer != nullptr)
|
||||
{
|
||||
playerIndex = sourcePlayer->GetXboxPad();
|
||||
if (playerIndex >= 0 && playerIndex < XUSER_MAX_COUNT && isReasonableLevelPointer(level[playerIndex]) && level[playerIndex]->dimension != nullptr)
|
||||
{
|
||||
lev = level[playerIndex];
|
||||
}
|
||||
}
|
||||
|
||||
if (lev == nullptr)
|
||||
{
|
||||
for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
|
||||
{
|
||||
if (mc->localplayers[i] != nullptr && isReasonableLevelPointer(mc->localplayers[i]->level) && mc->localplayers[i]->level->dimension != nullptr)
|
||||
{
|
||||
lev = mc->localplayers[i]->level;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (particleLevel == 1 && lev != nullptr)
|
||||
{
|
||||
// when playing at "decreased" particle level, randomly filter
|
||||
// particles by setting the level to "minimal"
|
||||
if (level[playerIndex]->random->nextInt(3) == 0)
|
||||
if (lev->random->nextInt(3) == 0)
|
||||
{
|
||||
particleLevel = 2;
|
||||
}
|
||||
@@ -2924,6 +2953,39 @@ shared_ptr<Particle> LevelRenderer::addParticleInternal(ePARTICLE_TYPE eParticle
|
||||
if (lev == nullptr)
|
||||
return nullptr;
|
||||
|
||||
if (!isReasonableLevelPointer(lev) || !isReasonableDimensionPointer(lev->dimension))
|
||||
return nullptr;
|
||||
|
||||
bool levIsKnown = false;
|
||||
if (lev == mc->level || lev == mc->animateTickLevel)
|
||||
{
|
||||
levIsKnown = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < XUSER_MAX_COUNT && !levIsKnown; ++i)
|
||||
{
|
||||
if (mc->localplayers[i] != nullptr && mc->localplayers[i]->level == lev && isReasonableLevelPointer(mc->localplayers[i]->level) && mc->localplayers[i]->level->dimension != nullptr)
|
||||
{
|
||||
levIsKnown = true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 4 && !levIsKnown; ++i)
|
||||
{
|
||||
if (this->level[i] == lev && isReasonableLevelPointer(this->level[i]) && this->level[i]->dimension != nullptr)
|
||||
{
|
||||
levIsKnown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!levIsKnown)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (lev->dimension == nullptr)
|
||||
return nullptr;
|
||||
|
||||
if (particleLevel > 1)
|
||||
{
|
||||
// TODO: If any of the particles below are necessary even if
|
||||
|
||||
@@ -1,10 +1,50 @@
|
||||
#include "stdafx.h"
|
||||
#include "Particle.h"
|
||||
#include "Tesselator.h"
|
||||
#include "../Minecraft.Client/Minecraft.h"
|
||||
#include "../Minecraft.Client/MultiPlayerLevel.h"
|
||||
#include "../Minecraft.Client/MultiPlayerLocalPlayer.h"
|
||||
#include "../Minecraft.World/Level.h"
|
||||
#include "../Minecraft.World/net.minecraft.world.level.dimension.h"
|
||||
#include "../Minecraft.World/Random.h"
|
||||
#include "../Minecraft.World/Mth.h"
|
||||
#include "../Minecraft.World/JavaMath.h"
|
||||
#include "../Minecraft.World/net.minecraft.world.h"
|
||||
#include "ParticleUtils.h"
|
||||
|
||||
static bool isKnownParticleLevel(Level *lev, Minecraft *mc)
|
||||
{
|
||||
if (lev == nullptr || mc == nullptr)
|
||||
return false;
|
||||
|
||||
if (lev == mc->level || lev == mc->animateTickLevel || lev == mc->oldLevel)
|
||||
return true;
|
||||
|
||||
for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
|
||||
{
|
||||
if (mc->localplayers[i] != nullptr && mc->localplayers[i]->level == lev)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static Level *safeParticleLevel(Level *level)
|
||||
{
|
||||
Minecraft *mc = Minecraft::GetInstance();
|
||||
|
||||
if (level != nullptr && isReasonableLevelPointer(level) && isKnownParticleLevel(level, mc) && isReasonableDimensionPointer(level->dimension))
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
if (mc != nullptr && mc->level != nullptr && isReasonableLevelPointer(mc->level) && isReasonableDimensionPointer(mc->level->dimension))
|
||||
{
|
||||
return static_cast<Level *>(mc->level);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
protected int tex;
|
||||
@@ -42,15 +82,37 @@ void Particle::_init(Level *level, double x, double y, double z)
|
||||
texY = 0;
|
||||
}
|
||||
|
||||
Particle::Particle(Level *level, double x, double y, double z) : Entity(level, false)
|
||||
Particle::Particle(Level *level, double x, double y, double z) : Entity(nullptr, false)
|
||||
{
|
||||
_init(level,x,y,z);
|
||||
|
||||
Level *safeLevel = safeParticleLevel(level);
|
||||
if (safeLevel != nullptr && isReasonableDimensionPointer(safeLevel->dimension))
|
||||
{
|
||||
this->level = safeLevel;
|
||||
dimension = safeLevel->dimension->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->level = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Particle::Particle(Level *level, double x, double y, double z, double xa, double ya, double za) : Entity(level, false)
|
||||
Particle::Particle(Level *level, double x, double y, double z, double xa, double ya, double za) : Entity(nullptr, false)
|
||||
{
|
||||
_init(level,x,y,z);
|
||||
|
||||
Level *safeLevel = safeParticleLevel(level);
|
||||
if (safeLevel != nullptr && isReasonableDimensionPointer(safeLevel->dimension))
|
||||
{
|
||||
this->level = safeLevel;
|
||||
dimension = safeLevel->dimension->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->level = nullptr;
|
||||
}
|
||||
|
||||
xd = xa + static_cast<float>(Math::random() * 2 - 1) * 0.4f;
|
||||
yd = ya + static_cast<float>(Math::random() * 2 - 1) * 0.4f;
|
||||
zd = za + static_cast<float>(Math::random() * 2 - 1) * 0.4f;
|
||||
|
||||
@@ -34,9 +34,11 @@ ParticleEngine::~ParticleEngine()
|
||||
|
||||
void ParticleEngine::add(shared_ptr<Particle> p)
|
||||
{
|
||||
if (p == nullptr || p->level == nullptr || p->level->dimension == nullptr) return;
|
||||
if (p->level != level) return;
|
||||
|
||||
int t = p->getParticleTexture();
|
||||
if (p->level == nullptr || p->level->dimension == nullptr) return;
|
||||
int l = p->level->dimension->id == 0 ? 0 : ( p->level->dimension->id == -1 ? 1 : 2);
|
||||
int l = p->level->dimension->id == 0 ? 0 : ( p->level->dimension->id == -1 ? 1 : 2);
|
||||
int maxParticles;
|
||||
switch(p->GetType())
|
||||
{
|
||||
@@ -69,6 +71,13 @@ void ParticleEngine::tick()
|
||||
for (unsigned int i = 0; i < particles[l][tt][list].size(); i++)
|
||||
{
|
||||
shared_ptr<Particle> p = particles[l][tt][list][i];
|
||||
if (p == nullptr || p->level == nullptr || p->level != level || p->level->dimension == nullptr)
|
||||
{
|
||||
particles[l][tt][list][i] = particles[l][tt][list].back();
|
||||
particles[l][tt][list].pop_back();
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
p->tick();
|
||||
if (p->removed)
|
||||
{
|
||||
@@ -88,6 +97,10 @@ void ParticleEngine::render(shared_ptr<Entity> player, float a, int list)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (level == nullptr || level->dimension == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 4J - change brought forward from 1.2.3
|
||||
float xa = Camera::xa;
|
||||
@@ -195,19 +208,19 @@ void ParticleEngine::setLevel(Level *level)
|
||||
{
|
||||
this->level = level;
|
||||
// 4J - we've now got a set of particle vectors for each dimension, and only clearing them when its game over & the level is set to nullptr
|
||||
if( level == nullptr )
|
||||
{
|
||||
for( int l = 0; l < 3; l++ )
|
||||
{
|
||||
for (int tt = 0; tt < TEXTURE_COUNT; tt++)
|
||||
{
|
||||
for( int list = 0; list < LIST_COUNT; list++ )
|
||||
{
|
||||
particles[l][tt][list].clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (level == nullptr)
|
||||
{
|
||||
for (int l = 0; l < 3; l++)
|
||||
{
|
||||
for (int tt = 0; tt < TEXTURE_COUNT; tt++)
|
||||
{
|
||||
for (int list = 0; list < LIST_COUNT; list++)
|
||||
{
|
||||
particles[l][tt][list].clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEngine::destroy(int x, int y, int z, int tid, int data)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
class Level;
|
||||
class Dimension;
|
||||
|
||||
inline bool isReasonablePointer(const void *ptr)
|
||||
{
|
||||
if (ptr == nullptr)
|
||||
return false;
|
||||
|
||||
unsigned long long addr = reinterpret_cast<unsigned long long>(ptr);
|
||||
if (addr <= 0x10000ULL || addr > 0x00007FFFFFFFFFFFULL)
|
||||
return false;
|
||||
if ((addr & 0x7ULL) != 0ULL)
|
||||
return false;
|
||||
if ((addr & 0xFFFFFFFFULL) == 0ULL)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool isReasonableLevelPointer(Level *lev)
|
||||
{
|
||||
return isReasonablePointer(lev);
|
||||
}
|
||||
|
||||
inline bool isReasonableDimensionPointer(Dimension *dim)
|
||||
{
|
||||
return isReasonablePointer(dim);
|
||||
}
|
||||
@@ -372,9 +372,13 @@ Entity::Entity(Level *level, bool useSmallId) // 4J - added useSmallId parameter
|
||||
// resetPos();
|
||||
setPos(0, 0, 0);
|
||||
|
||||
if (level != nullptr && level->dimension != nullptr)
|
||||
if (level != nullptr)
|
||||
{
|
||||
dimension = level->dimension->id;
|
||||
auto dimensionPtr = level->dimension;
|
||||
if (dimensionPtr != nullptr)
|
||||
{
|
||||
dimension = dimensionPtr->id;
|
||||
}
|
||||
}
|
||||
|
||||
if( entityData )
|
||||
|
||||
Reference in New Issue
Block a user