diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch index f5c9852fc9..6027f94fe9 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch @@ -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) { @@ -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 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 holder, java.util.function.Consumer 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 optional = Optional.ofNullable((Vec3) serverexplosion.getHitPlayers().get(entityplayer)); @@ -777,7 +782,7 @@ } private Explosion.BlockInteraction getDestroyType(GameRules.Key decayRule) { -@@ -1226,17 +1537,29 @@ +@@ -1226,17 +1543,29 @@ } public 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 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 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 structureTag, BlockPos pos, int radius, boolean skipReferencedStructures) { @@ -821,7 +827,7 @@ return null; } else { Optional> 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 String getTypeCount(Iterable items, Function classifier) { try { Object2IntOpenHashMap 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 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); diff --git a/paper-server/patches/sources/net/minecraft/world/level/ServerExplosion.java.patch b/paper-server/patches/sources/net/minecraft/world/level/ServerExplosion.java.patch index d289383a99..f008185fe1 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/ServerExplosion.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/ServerExplosion.java.patch @@ -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 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 list = this.level.getEntities(this.source, new AABB((double) i, (double) k, (double) i1, (double) j, (double) l, (double) j1)); -+ List 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.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities ++ List 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.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 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 list = this.calculateExplodedPositions(); -@@ -288,6 +399,7 @@ +@@ -288,6 +400,7 @@ } private static void addOrAppendStack(List droppedItemsOut, ItemStack item, BlockPos pos) { @@ -227,7 +228,7 @@ Iterator iterator = droppedItemsOut.iterator(); do { -@@ -372,4 +484,85 @@ +@@ -372,4 +485,85 @@ } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index a403507c07..32b5fbbaf4 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -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 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) {