/******************************************************************** Minecraft: Pocket Edition - Decompilation Project Copyright (C) 2023 iProgramInCpp The following code is licensed under the BSD 1 clause license. SPDX-License-Identifier: BSD-1-Clause ********************************************************************/ #include #include "ParticleEngine.hpp" ParticleEngine::ParticleEngine(Level* level, Textures* textures) { m_pLevel = level; m_pTextures = textures; m_pTextures->loadTexture("particles.png", true); } void ParticleEngine::setLevel(Level* level) { #ifdef ORIGINAL_CODE m_pLevel = level; #endif for (int i = 0; i < 4; i++) { #ifndef ORIGINAL_CODE for (std::vector::iterator it = m_particles[i].begin(); it != m_particles[i].end(); it++) { Particle* pParticle = *it; delete pParticle; } #endif // @BUG: memory leak? m_particles[i].clear(); } #ifndef ORIGINAL_CODE m_pLevel = level; #endif } void ParticleEngine::add(Particle* particle) { m_particles[particle->getParticleTexture()].push_back(particle); } std::string ParticleEngine::countParticles() { // @NOTE: For whatever reason this returns a string?? std::stringstream ss; ss << (m_particles[0].size() + m_particles[1].size() + m_particles[2].size() + m_particles[3].size()); return ss.str(); } void ParticleEngine::crack(int x, int y, int z, int dir) { TileID tileID = m_pLevel->getTile(x, y, z); if (!tileID) return; Tile* pTile = Tile::tiles[tileID]; float posX, posY, posZ; switch (dir) { case DIR_YNEG: posX = float(x) + Lerp(pTile->m_aabb.min.x, pTile->m_aabb.max.x - 0.2f, m_random.nextFloat()) + 0.1f; posZ = float(z) + Lerp(pTile->m_aabb.min.z, pTile->m_aabb.max.z - 0.2f, m_random.nextFloat()) + 0.1f; posY = float(y) + pTile->m_aabb.min.y - 0.1f; break; case DIR_YPOS: posX = float(x) + Lerp(pTile->m_aabb.min.x, pTile->m_aabb.max.x - 0.2f, m_random.nextFloat()) + 0.1f; posZ = float(z) + Lerp(pTile->m_aabb.min.z, pTile->m_aabb.max.z - 0.2f, m_random.nextFloat()) + 0.1f; posY = float(y) + pTile->m_aabb.max.y + 0.1f; break; case DIR_ZNEG: posX = float(x) + Lerp(pTile->m_aabb.min.x, pTile->m_aabb.max.x - 0.2f, m_random.nextFloat()) + 0.1f; posY = float(y) + Lerp(pTile->m_aabb.min.y, pTile->m_aabb.max.y - 0.2f, m_random.nextFloat()) + 0.1f; posZ = float(z) + pTile->m_aabb.min.z - 0.1f; break; case DIR_ZPOS: posX = float(x) + Lerp(pTile->m_aabb.min.x, pTile->m_aabb.max.x - 0.2f, m_random.nextFloat()) + 0.1f; posY = float(y) + Lerp(pTile->m_aabb.min.y, pTile->m_aabb.max.y - 0.2f, m_random.nextFloat()) + 0.1f; posZ = float(z) + pTile->m_aabb.max.z + 0.1f; break; case DIR_XNEG: posY = float(y) + Lerp(pTile->m_aabb.min.y, pTile->m_aabb.max.y - 0.2f, m_random.nextFloat()) + 0.1f; posZ = float(z) + Lerp(pTile->m_aabb.min.z, pTile->m_aabb.max.z - 0.2f, m_random.nextFloat()) + 0.1f; posX = float(x) + pTile->m_aabb.min.x - 0.1f; break; case DIR_XPOS: posY = float(y) + Lerp(pTile->m_aabb.min.y, pTile->m_aabb.max.y - 0.2f, m_random.nextFloat()) + 0.1f; posZ = float(z) + Lerp(pTile->m_aabb.min.z, pTile->m_aabb.max.z - 0.2f, m_random.nextFloat()) + 0.1f; posX = float(x) + pTile->m_aabb.max.x + 0.1f; break; default: // @TODO: dont know what they do for the undefined case posX = float(x); posY = float(y); posZ = float(z); break; } add((new TerrainParticle(m_pLevel, posX, posY, posZ, pTile))->setPower(0.2f)->scale(0.6f)); } void ParticleEngine::destroy(int x, int y, int z) { TileID tileID = m_pLevel->getTile(x, y, z); if (!tileID) return; float timeS = getTimeS(); Tile* pTile = Tile::tiles[tileID]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { float posX = float(x) + (float(i) + 0.5f) / 3.0f; float posY = float(y) + (float(j) + 0.5f) / 3.0f; float posZ = float(z) + (float(k) + 0.5f) / 3.0f; add((new TerrainParticle(m_pLevel, posX, posY, posZ, posX - float(x) - 0.5f, posY - float(y) - 0.5f, posZ - float(z) - 0.5f, pTile))->init(x, y, z)); } } } if (timeS != -1.0) getTimeS(); // @NOTE: Useless string creation #ifdef ORIGINAL_CODE std::string("gen destroy particles: "); #endif } #ifdef ENH_CAMERA_NO_PARTICLES bool g_bDisableParticles; #endif void ParticleEngine::render(Entity* ent, float f) { #ifdef ENH_CAMERA_NO_PARTICLES if (g_bDisableParticles) return; #endif float x1 = Mth::cos(float(M_PI) * ent->m_yaw / 180.0f); float x3 = Mth::sin(float(M_PI) * ent->m_yaw / 180.0f); float x4 = -(x3 * Mth::sin(float(M_PI) * ent->m_pitch / 180.0f)); float x5 = x1 * Mth::sin(float(M_PI) * ent->m_pitch / 180.0f); float x2 = Mth::cos(float(M_PI) * ent->m_pitch / 180.0f); Particle::xOff = Lerp(ent->field_98.x, ent->m_pos.x, f); Particle::yOff = Lerp(ent->field_98.y, ent->m_pos.y, f); Particle::zOff = Lerp(ent->field_98.z, ent->m_pos.z, f); // @BUG: Ignoring the last particle array. Invisible? Tesselator& t = Tesselator::instance; for (int i = 0; i < 3; i++) { if (i == PT_TERRAIN) m_pTextures->loadAndBindTexture(C_TERRAIN_NAME); else m_pTextures->loadAndBindTexture("particles.png"); t.begin(); for (std::vector::iterator it = m_particles[i].begin(); it != m_particles[i].end(); it++) { Particle* pParticle = *it; pParticle->render(t, f, x1, x2, x3, x4, x5); } t.draw(); } } void ParticleEngine::renderLit() { } void ParticleEngine::tick() { for (int p = 0; p < 4; p++) { for (size_t i = 0; i < m_particles[p].size(); i++) { Particle* particle = m_particles[p][i]; particle->tick(); if (particle->m_bRemoved) { // remove it m_particles[p].erase(m_particles[p].begin() + i); i--; delete particle; continue; } } } }