the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
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}