the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 292 lines 8.7 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.entity.h" 3#include "net.minecraft.world.entity.item.h" 4#include "net.minecraft.world.item.enchantment.h" 5#include "net.minecraft.world.level.h" 6#include "net.minecraft.world.level.tile.h" 7#include "net.minecraft.world.phys.h" 8#include "net.minecraft.world.damagesource.h" 9#include "TilePos.h" 10#include "Explosion.h" 11#include "SoundTypes.h" 12 13Explosion::Explosion(Level *level, shared_ptr<Entity> source, double x, double y, double z, float r) 14{ 15 fire = false; 16 random = new Random(); 17 18 this->level = level; 19 this->source = source; 20 this->r = r; 21 this->x = x; 22 this->y = y; 23 this->z = z; 24 25 destroyBlocks = true; 26 size = 16; 27} 28 29Explosion::~Explosion() 30{ 31 delete random; 32 for(AUTO_VAR(it, hitPlayers.begin()); it != hitPlayers.end(); ++it) 33 { 34 delete it->second; 35 } 36} 37 38void Explosion::explode() 39{ 40 float oR = r; 41 42 int size = 16; 43 for (int xx = 0; xx < size; xx++) 44 { 45 for (int yy = 0; yy < size; yy++) 46 { 47 for (int zz = 0; zz < size; zz++) 48 { 49 if ((xx != 0 && xx != size - 1) && (yy != 0 && yy != size - 1) && (zz != 0 && zz != size - 1)) continue; 50 51 double xd = xx / (size - 1.0f) * 2 - 1; 52 double yd = yy / (size - 1.0f) * 2 - 1; 53 double zd = zz / (size - 1.0f) * 2 - 1; 54 double d = sqrt(xd * xd + yd * yd + zd * zd); 55 56 xd /= d; 57 yd /= d; 58 zd /= d; 59 60 float remainingPower = r * (0.7f + level->random->nextFloat() * 0.6f); 61 double xp = x; 62 double yp = y; 63 double zp = z; 64 65 float stepSize = 0.3f; 66 while (remainingPower > 0) 67 { 68 int xt = Mth::floor(xp); 69 int yt = Mth::floor(yp); 70 int zt = Mth::floor(zp); 71 int t = level->getTile(xt, yt, zt); 72 if (t > 0) 73 { 74 Tile *tile = Tile::tiles[t]; 75 float resistance = source != NULL ? source->getTileExplosionResistance(this, level, xt, yt, zt, tile) : tile->getExplosionResistance(source); 76 remainingPower -= (resistance + 0.3f) * stepSize; 77 } 78 if (remainingPower > 0&& (source == NULL || source->shouldTileExplode(this, level, xt, yt, zt, t, remainingPower))) 79 { 80 toBlow.insert(TilePos(xt, yt, zt)); 81 } 82 83 xp += xd * stepSize; 84 yp += yd * stepSize; 85 zp += zd * stepSize; 86 remainingPower -= stepSize * 0.75f; 87 } 88 // if (xd*xd+yd*yd+zd*zd>1) continue; 89 } 90 } 91 } 92 93 r *= 2.0f; 94 int x0 = Mth::floor(x - r - 1); 95 int x1 = Mth::floor(x + r + 1); 96 int y0 = Mth::floor(y - r - 1); 97 int y1 = Mth::floor(y + r + 1); 98 int z0 = Mth::floor(z - r - 1); 99 int z1 = Mth::floor(z + r + 1); 100 101 // Fix for 360 #123866 - [CRASH] TU13: Code: Compliance: Placing the TNT next to Ender Crystals will crash the title after a certain amount of time. 102 // If we explode something next to an EnderCrystal then it creates a new explosion that overwrites the shared vector in the level 103 // So copy it here instead of directly using the shared one 104 vector<shared_ptr<Entity> > *levelEntities = level->getEntities(source, AABB::newTemp(x0, y0, z0, x1, y1, z1)); 105 vector<shared_ptr<Entity> > entities(levelEntities->begin(), levelEntities->end() ); 106 Vec3 *center = Vec3::newTemp(x, y, z); 107 108 AUTO_VAR(itEnd, entities.end()); 109 for (AUTO_VAR(it, entities.begin()); it != itEnd; it++) 110 { 111 shared_ptr<Entity> e = *it; //entities->at(i); 112 113 // 4J Stu - If the entity is not in a block that would be blown up, then they should not be damaged 114 // Fix for #46606 - TU5: Content: Gameplay: The player can be damaged and killed by explosions behind obsidian walls 115 bool canDamage = false; 116 for(AUTO_VAR(it2, toBlow.begin()); it2 != toBlow.end(); ++it2) 117 { 118 if(e->bb->intersects(it2->x,it2->y,it2->z,it2->x + 1,it2->y + 1,it2->z + 1)) 119 { 120 canDamage = true; 121 break; 122 } 123 } 124 125 double dist = e->distanceTo(x, y, z) / r; 126 if (dist <= 1) 127 { 128 double xa = e->x - x; 129 double ya = e->y + e->getHeadHeight() - y; 130 double za = e->z - z; 131 132 double da = sqrt(xa * xa + ya * ya + za * za); 133 134 // 4J Stu - Added this check to remove divide by zero errors (or rather the issues caused by 135 // the values being set to NaN and used in comparisons a bit later on e.g. fireball) 136 if( da == 0 ) 137 { 138 xa = ya = za = 0.0; 139 } 140 else 141 { 142 xa /= da; 143 ya /= da; 144 za /= da; 145 } 146 147 double sp = level->getSeenPercent(center, e->bb); 148 double pow = (1 - dist) * sp; 149 if(canDamage) e->hurt(DamageSource::explosion(this), (int) ((pow * pow + pow) / 2 * 8 * r + 1)); 150 151 double kbPower = ProtectionEnchantment::getExplosionKnockbackAfterDampener(e, pow); 152 e->xd += xa *kbPower; 153 e->yd += ya *kbPower; 154 e->zd += za *kbPower; 155 156 157 if (e->instanceof(eTYPE_PLAYER)) 158 { 159 shared_ptr<Player> player = dynamic_pointer_cast<Player>(e); 160 //app.DebugPrintf("Adding player knockback (%f,%f,%f)\n", xa * pow, ya * pow, za * pow); 161 hitPlayers.insert( playerVec3Map::value_type( player, Vec3::newPermanent(xa * pow, ya * pow, za * pow))); 162 } 163 } 164 } 165 r = oR; 166} 167 168 169void Explosion::finalizeExplosion(bool generateParticles, vector<TilePos> *toBlowDirect/*=NULL*/) // 4J - added toBlowDirect parameter 170{ 171 level->playSound(x, y, z, eSoundType_RANDOM_EXPLODE, 4, (1 + (level->random->nextFloat() - level->random->nextFloat()) * 0.2f) * 0.7f); 172 if (r < 2 || !destroyBlocks) 173 { 174 level->addParticle(eParticleType_largeexplode, x, y, z, 1.0f, 0, 0); 175 } 176 else 177 { 178 level->addParticle(eParticleType_hugeexplosion, x, y, z, 1.0f, 0, 0); 179 } 180 181 // 4J - use pointer to vector directly passed in if this is available - used to speed up calling this from an incoming packet 182 vector<TilePos> *toBlowArray = toBlowDirect ? toBlowDirect : new vector<TilePos>( toBlow.begin(), toBlow.end() ); 183 if (destroyBlocks) 184 { 185 //toBlowArray.addAll(toBlow); 186 // TODO 4J Stu - Reverse iterator 187 PIXBeginNamedEvent(0,"Finalizing explosion size %d",toBlow.size()); 188 app.DebugPrintf("Finalizing explosion size %d\n",toBlow.size()); 189 static const int MAX_EXPLODE_PARTICLES = 50; 190 // 4J - try and make at most MAX_EXPLODE_PARTICLES pairs of particles 191 int fraction = (int)toBlowArray->size() / MAX_EXPLODE_PARTICLES; 192 if( fraction == 0 ) fraction = 1; 193 size_t j = toBlowArray->size() - 1; 194 //for (size_t j = toBlowArray->size() - 1; j >= 0; j--) 195 for(AUTO_VAR(it,toBlowArray->rbegin()); it != toBlowArray->rend(); ++it) 196 { 197 TilePos *tp = &(*it); //&toBlowArray->at(j); 198 int xt = tp->x; 199 int yt = tp->y; 200 int zt = tp->z; 201 // if (xt >= 0 && yt >= 0 && zt >= 0 && xt < width && yt < depth && 202 // zt < height) { 203 int t = level->getTile(xt, yt, zt); 204 205 if (generateParticles) 206 { 207 if( ( j % fraction ) == 0 ) 208 { 209 double xa = xt + level->random->nextFloat(); 210 double ya = yt + level->random->nextFloat(); 211 double za = zt + level->random->nextFloat(); 212 213 double xd = xa - x; 214 double yd = ya - y; 215 double zd = za - z; 216 217 double dd = sqrt(xd * xd + yd * yd + zd * zd); 218 219 xd /= dd; 220 yd /= dd; 221 zd /= dd; 222 223 double speed = 0.5 / (dd / r + 0.1); 224 speed *= (level->random->nextFloat() * level->random->nextFloat() + 0.3f); 225 xd *= speed; 226 yd *= speed; 227 zd *= speed; 228 229 level->addParticle(eParticleType_explode, (xa + x * 1) / 2, (ya + y * 1) / 2, (za + z * 1) / 2, xd, yd, zd); 230 level->addParticle(eParticleType_smoke, xa, ya, za, xd, yd, zd); 231 } 232 } 233 234 if (t > 0) 235 { 236 Tile *tile = Tile::tiles[t]; 237 238 if (tile->dropFromExplosion(this)) 239 { 240 tile->spawnResources(level, xt, yt, zt, level->getData(xt, yt, zt), 1.0f / r, 0); 241 } 242 level->setTileAndData(xt, yt, zt, 0, 0, Tile::UPDATE_ALL); 243 tile->wasExploded(level, xt, yt, zt, this); 244 } 245 246 --j; 247 } 248 } 249 250 if (fire) 251 { 252 //for (size_t j = toBlowArray->size() - 1; j >= 0; j--) 253 for(AUTO_VAR(it,toBlowArray->rbegin()); it != toBlowArray->rend(); ++it) 254 { 255 TilePos *tp = &(*it); //&toBlowArray->at(j); 256 int xt = tp->x; 257 int yt = tp->y; 258 int zt = tp->z; 259 int t = level->getTile(xt, yt, zt); 260 int b = level->getTile(xt, yt - 1, zt); 261 if (t == 0 && Tile::solid[b] && random->nextInt(3) == 0) 262 { 263 level->setTileAndUpdate(xt, yt, zt, Tile::fire_Id); 264 } 265 } 266 } 267 268 PIXEndNamedEvent(); 269 if( toBlowDirect == NULL ) delete toBlowArray; 270} 271 272Explosion::playerVec3Map *Explosion::getHitPlayers() 273{ 274 return &hitPlayers; 275} 276 277Vec3 *Explosion::getHitPlayerKnockback( shared_ptr<Player> player ) 278{ 279 AUTO_VAR(it, hitPlayers.find(player)); 280 281 if(it == hitPlayers.end() ) return Vec3::newTemp(0.0,0.0,0.0); 282 283 return it->second; 284} 285 286shared_ptr<LivingEntity> Explosion::getSourceMob() 287{ 288 if (source == NULL) return nullptr; 289 if (source->instanceof(eTYPE_PRIMEDTNT)) return dynamic_pointer_cast<PrimedTnt>(source)->getOwner(); 290 if (source->instanceof(eTYPE_LIVINGENTITY)) return dynamic_pointer_cast<LivingEntity>(source); 291 return nullptr; 292}