Expand Explosions API

Add Entity as a Source capability, and add more API choices, and on Location.

Co-authored-by: Esoteric Enderman <90862990+EsotericEnderman@users.noreply.github.com>
Co-authored-by: Bjarne Koll <git@lynxplay.dev>
This commit is contained in:
Aikar 2018-06-20 23:17:24 -04:00
parent 991875920d
commit dddd41ac34
3 changed files with 59 additions and 41 deletions

View File

@ -79,7 +79,7 @@
+ public final LevelStorageSource.LevelStorageAccess convertable;
+ public final UUID uuid;
+ public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
+
+ public LevelChunk getChunkIfLoaded(int x, int z) {
+ return this.chunkSource.getChunk(x, z, false);
+ }
@ -209,7 +209,7 @@
+ chunkgenerator = new FlatLevelSource(cpf.settings(), worldChunkManager);
+ }
+ }
+
+ if (gen != null) {
+ chunkgenerator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, chunkgenerator, gen);
+ }
@ -543,13 +543,13 @@
- return this.addEntity(entity);
+ // CraftBukkit start
+ return this.addWithUUID(entity, CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
}
+ public boolean addWithUUID(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
+ return this.addEntity(entity, reason);
+ // CraftBukkit end
}
+ }
+
public void addDuringTeleport(Entity entity) {
+ // CraftBukkit start
+ // SPIGOT-6415: Don't call spawn event for entities which travel trough worlds,
@ -716,7 +716,7 @@
this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, (Direction) null, orientation);
}
@@ -1126,9 +1420,15 @@
@@ -1126,9 +1420,20 @@
@Override
public void explode(@Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator behavior, double x, double y, double z, float power, boolean createFire, Level.ExplosionInteraction explosionSourceType, ParticleOptions smallParticle, ParticleOptions largeParticle, Holder<SoundEvent> soundEvent) {
@ -725,6 +725,11 @@
+ }
+
+ public ServerExplosion explode0(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction world_a, ParticleOptions particleparam, ParticleOptions particleparam1, Holder<SoundEvent> holder) {
+ // Paper start - Allow explosions to damage source
+ return this.explode0(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, particleparam, particleparam1, holder, null);
+ }
+ public ServerExplosion explode0(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction world_a, ParticleOptions particleparam, ParticleOptions particleparam1, Holder<SoundEvent> holder, java.util.function.Consumer<ServerExplosion> configurator) {
+ // Paper end - Allow explosions to damage source
+ // CraftBukkit end
Explosion.BlockInteraction explosion_effect;
@ -733,15 +738,14 @@
case NONE:
explosion_effect = Explosion.BlockInteraction.KEEP;
break;
@@ -1143,17 +1443,27 @@
break;
@@ -1144,16 +1449,27 @@
case TRIGGER:
explosion_effect = Explosion.BlockInteraction.TRIGGER_BLOCK;
+ break;
break;
+ // CraftBukkit start - handle custom explosion type
+ case STANDARD:
+ explosion_effect = Explosion.BlockInteraction.DESTROY;
break;
+ break;
+ // CraftBukkit end
default:
throw new MatchException((String) null, (Throwable) null);
@ -752,6 +756,7 @@
- ServerExplosion serverexplosion = new ServerExplosion(this, entity, damageSource, behavior, vec3d, power, createFire, explosion_effect1);
+ Vec3 vec3d = new Vec3(d0, d1, d2);
+ ServerExplosion serverexplosion = new ServerExplosion(this, entity, damagesource, explosiondamagecalculator, vec3d, f, flag, explosion_effect1);
+ if (configurator != null) configurator.accept(serverexplosion);// Paper - Allow explosions to damage source
serverexplosion.explode();
- ParticleOptions particleparam2 = serverexplosion.isSmall() ? smallParticle : largeParticle;
@ -764,7 +769,7 @@
Iterator iterator = this.players.iterator();
while (iterator.hasNext()) {
@@ -1162,10 +1472,11 @@
@@ -1162,10 +1478,11 @@
if (entityplayer.distanceToSqr(vec3d) < 4096.0D) {
Optional<Vec3> optional = Optional.ofNullable((Vec3) serverexplosion.getHitPlayers().get(entityplayer));
@ -777,7 +782,7 @@
}
private Explosion.BlockInteraction getDestroyType(GameRules.Key<GameRules.BooleanValue> decayRule) {
@@ -1226,17 +1537,29 @@
@@ -1226,17 +1543,29 @@
}
public <T extends ParticleOptions> int sendParticles(T parameters, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double speed) {
@ -787,9 +792,12 @@
public <T extends ParticleOptions> int sendParticles(T parameters, boolean force, boolean important, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double speed) {
- ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(parameters, force, important, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) speed, count);
- int j = 0;
+ return this.sendParticlesSource(null, parameters, force, important, x, y, z, count, offsetX, offsetY, offsetZ, speed); // CraftBukkit - visibility api support
+ }
+
- for (int k = 0; k < this.players.size(); ++k) {
- ServerPlayer entityplayer = (ServerPlayer) this.players.get(k);
+ // CraftBukkit start - visibility api support
+ public <T extends ParticleOptions> int sendParticlesSource(ServerPlayer sender, T t0, boolean flag, boolean flag1, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) {
+ // Paper start - Particle API
@ -799,20 +807,18 @@
+ // Paper end - Particle API
+ // CraftBukkit end
+ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, flag, flag1, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i);
int j = 0;
+ int j = 0;
- for (int k = 0; k < this.players.size(); ++k) {
- ServerPlayer entityplayer = (ServerPlayer) this.players.get(k);
- if (this.sendParticles(entityplayer, force, x, y, z, packetplayoutworldparticles)) {
+ for (Player entityhuman : receivers) { // Paper - Particle API
+ ServerPlayer entityplayer = (ServerPlayer) entityhuman; // Paper - Particle API
+ if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit
- if (this.sendParticles(entityplayer, force, x, y, z, packetplayoutworldparticles)) {
+
+ if (this.sendParticles(entityplayer, flag, d0, d1, d2, packetplayoutworldparticles)) {
++j;
}
}
@@ -1292,7 +1615,7 @@
@@ -1292,7 +1621,7 @@
@Nullable
public BlockPos findNearestMapStructure(TagKey<Structure> structureTag, BlockPos pos, int radius, boolean skipReferencedStructures) {
@ -821,7 +827,7 @@
return null;
} else {
Optional<HolderSet.Named<Structure>> optional = this.registryAccess().lookupOrThrow(Registries.STRUCTURE).get(structureTag);
@@ -1334,11 +1657,22 @@
@@ -1334,11 +1663,22 @@
@Nullable
@Override
public MapItemSavedData getMapData(MapId id) {
@ -845,7 +851,7 @@
this.getServer().overworld().getDataStorage().set(id.key(), state);
}
@@ -1649,6 +1983,11 @@
@@ -1649,6 +1989,11 @@
@Override
public void blockUpdated(BlockPos pos, Block block) {
if (!this.isDebug()) {
@ -857,7 +863,7 @@
this.updateNeighborsAt(pos, block);
}
@@ -1668,12 +2007,12 @@
@@ -1668,12 +2013,12 @@
}
public boolean isFlat() {
@ -872,7 +878,7 @@
}
@Nullable
@@ -1696,7 +2035,7 @@
@@ -1696,7 +2041,7 @@
private static <T> String getTypeCount(Iterable<T> items, Function<T, String> classifier) {
try {
Object2IntOpenHashMap<String> object2intopenhashmap = new Object2IntOpenHashMap();
@ -881,7 +887,7 @@
while (iterator.hasNext()) {
T t0 = iterator.next();
@@ -1705,7 +2044,7 @@
@@ -1705,7 +2050,7 @@
object2intopenhashmap.addTo(s, 1);
}
@ -890,7 +896,7 @@
String s1 = (String) entry.getKey();
return s1 + ":" + entry.getIntValue();
@@ -1717,6 +2056,7 @@
@@ -1717,6 +2062,7 @@
@Override
public LevelEntityGetter<Entity> getEntities() {
@ -898,7 +904,7 @@
return this.entityManager.getEntityGetter();
}
@@ -1802,6 +2142,17 @@
@@ -1802,6 +2148,17 @@
return this.serverLevelData.getGameRules();
}
@ -916,7 +922,7 @@
@Override
public CrashReportCategory fillReportDetails(CrashReport report) {
CrashReportCategory crashreportsystemdetails = super.fillReportDetails(report);
@@ -1836,6 +2187,7 @@
@@ -1836,6 +2193,7 @@
}
public void onTrackingStart(Entity entity) {
@ -924,7 +930,7 @@
ServerLevel.this.getChunkSource().addEntity(entity);
if (entity instanceof ServerPlayer entityplayer) {
ServerLevel.this.players.add(entityplayer);
@@ -1864,9 +2216,52 @@
@@ -1864,9 +2222,52 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
@ -977,7 +983,7 @@
ServerLevel.this.getChunkSource().removeEntity(entity);
if (entity instanceof ServerPlayer entityplayer) {
ServerLevel.this.players.remove(entityplayer);
@@ -1895,6 +2290,15 @@
@@ -1895,6 +2296,15 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);

View File

@ -29,7 +29,7 @@
public class ServerExplosion implements Explosion {
@@ -50,16 +59,21 @@
@@ -50,16 +59,22 @@
private final DamageSource damageSource;
private final ExplosionDamageCalculator damageCalculator;
private final Map<Player, Vec3> hitPlayers = new HashMap();
@ -37,6 +37,7 @@
+ public boolean wasCanceled = false;
+ public float yield;
+ // CraftBukkit end
+ public boolean excludeSourceFromDamage = true; // Paper - Allow explosions to damage source
public ServerExplosion(ServerLevel world, @Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator behavior, Vec3 pos, float power, boolean createFire, Explosion.BlockInteraction destructionType) {
this.level = world;
@ -52,16 +53,16 @@
}
private ExplosionDamageCalculator makeDamageCalculator(@Nullable Entity entity) {
@@ -171,7 +185,7 @@
@@ -171,7 +186,7 @@
int l = Mth.floor(this.center.y + (double) f + 1.0D);
int i1 = Mth.floor(this.center.z - (double) f - 1.0D);
int j1 = Mth.floor(this.center.z + (double) f + 1.0D);
- List<Entity> list = this.level.getEntities(this.source, new AABB((double) i, (double) k, (double) i1, (double) j, (double) l, (double) j1));
+ List<Entity> list = this.level.getEntities(this.source, new AABB((double) i, (double) k, (double) i1, (double) j, (double) l, (double) j1), (com.google.common.base.Predicate<Entity>) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities
+ List<Entity> list = this.level.getEntities(excludeSourceFromDamage ? this.source : null, new AABB((double) i, (double) k, (double) i1, (double) j, (double) l, (double) j1), (com.google.common.base.Predicate<Entity>) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities, Allow explosions to damage source
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
@@ -192,10 +206,38 @@
@@ -192,10 +207,38 @@
d3 /= d4;
boolean flag = this.damageCalculator.shouldDamageEntity(this, entity);
float f1 = this.damageCalculator.getKnockbackMultiplier(entity);
@ -102,7 +103,7 @@
}
double d5 = (1.0D - d0) * (double) f2 * (double) f1;
@@ -204,7 +246,7 @@
@@ -204,7 +247,7 @@
if (entity instanceof LivingEntity) {
LivingEntity entityliving = (LivingEntity) entity;
@ -111,7 +112,7 @@
} else {
d6 = d5;
}
@@ -214,11 +256,19 @@
@@ -214,11 +257,19 @@
d3 *= d6;
Vec3 vec3d = new Vec3(d1, d2, d3);
@ -132,7 +133,7 @@
this.hitPlayers.put(entityhuman, vec3d);
}
}
@@ -235,10 +285,62 @@
@@ -235,10 +286,62 @@
List<ServerExplosion.StackCollector> list1 = new ArrayList();
Util.shuffle(positions, this.level.random);
@ -195,7 +196,7 @@
this.level.getBlockState(blockposition).onExplosionHit(this.level, blockposition, this, (itemstack, blockposition1) -> {
ServerExplosion.addOrAppendStack(list1, itemstack, blockposition1);
@@ -262,13 +364,22 @@
@@ -262,13 +365,22 @@
BlockPos blockposition = (BlockPos) iterator.next();
if (this.level.random.nextInt(3) == 0 && this.level.getBlockState(blockposition).isAir() && this.level.getBlockState(blockposition.below()).isSolidRender()) {
@ -219,7 +220,7 @@
this.level.gameEvent(this.source, (Holder) GameEvent.EXPLODE, this.center);
List<BlockPos> list = this.calculateExplodedPositions();
@@ -288,6 +399,7 @@
@@ -288,6 +400,7 @@
}
private static void addOrAppendStack(List<ServerExplosion.StackCollector> droppedItemsOut, ItemStack item, BlockPos pos) {
@ -227,7 +228,7 @@
Iterator iterator = droppedItemsOut.iterator();
do {
@@ -372,4 +484,85 @@
@@ -372,4 +485,85 @@
}
}

View File

@ -777,6 +777,11 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) {
// Paper start - expand explosion API
return this.createExplosion(x, y, z, power, setFire, breakBlocks, source, null);
}
public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source, Consumer<net.minecraft.world.level.ServerExplosion> configurator) {
// Paper end - expand explosion API
net.minecraft.world.level.Level.ExplosionInteraction explosionType;
if (!breakBlocks) {
explosionType = net.minecraft.world.level.Level.ExplosionInteraction.NONE; // Don't break blocks
@ -787,8 +792,14 @@ public class CraftWorld extends CraftRegionAccessor implements World {
}
net.minecraft.world.entity.Entity entity = (source == null) ? null : ((CraftEntity) source).getHandle();
return !this.world.explode0(entity, Explosion.getDefaultDamageSource(this.world, entity), null, x, y, z, power, setFire, explosionType, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE).wasCanceled;
return !this.world.explode0(entity, Explosion.getDefaultDamageSource(this.world, entity), null, x, y, z, power, setFire, explosionType, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE, configurator).wasCanceled; // Paper - expand explosion API
}
// Paper start
@Override
public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks, boolean excludeSourceFromDamage) {
return this.createExplosion(loc.x(), loc.getY(), loc.getZ(), power, setFire, breakBlocks, source, e -> e.excludeSourceFromDamage = excludeSourceFromDamage);
}
// Paper end
@Override
public boolean createExplosion(Location loc, float power) {