mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-01 05:47:45 +01:00
Async Operation Catching
Catch and throw an exception when a potentially unsafe operation occurs on a thread other than the main server thread. By: md_5 <git@md-5.net>
This commit is contained in:
parent
973f52a650
commit
5240271410
@ -100,7 +100,23 @@
|
||||
}
|
||||
|
||||
void forEachSpawnCandidateChunk(Consumer<ChunkHolder> callback) {
|
||||
@@ -1424,7 +1458,7 @@
|
||||
@@ -1215,6 +1249,7 @@
|
||||
}
|
||||
|
||||
public void addEntity(Entity entity) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot
|
||||
if (!(entity instanceof EnderDragonPart)) {
|
||||
EntityType<?> entitytypes = entity.getType();
|
||||
int i = entitytypes.clientTrackingRange() * 16;
|
||||
@@ -1250,6 +1285,7 @@
|
||||
}
|
||||
|
||||
protected void removeEntity(Entity entity) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("entity untrack"); // Spigot
|
||||
if (entity instanceof ServerPlayer entityplayer) {
|
||||
this.updatePlayerStatus(entityplayer, false);
|
||||
ObjectIterator objectiterator = this.entityMap.values().iterator();
|
||||
@@ -1424,7 +1460,7 @@
|
||||
public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
|
||||
|
||||
public TrackedEntity(final Entity entity, final int i, final int j, final boolean flag) {
|
||||
@ -109,7 +125,23 @@
|
||||
this.entity = entity;
|
||||
this.range = i;
|
||||
this.lastSectionPos = SectionPos.of((EntityAccess) entity);
|
||||
@@ -1484,6 +1518,11 @@
|
||||
@@ -1469,6 +1505,7 @@
|
||||
}
|
||||
|
||||
public void removePlayer(ServerPlayer player) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot
|
||||
if (this.seenBy.remove(player.connection)) {
|
||||
this.serverEntity.removePairing(player);
|
||||
}
|
||||
@@ -1476,6 +1513,7 @@
|
||||
}
|
||||
|
||||
public void updatePlayer(ServerPlayer player) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot
|
||||
if (player != this.entity) {
|
||||
Vec3 vec3d = player.position().subtract(this.entity.position());
|
||||
int i = ChunkMap.this.getPlayerViewDistance(player);
|
||||
@@ -1484,6 +1522,11 @@
|
||||
double d2 = d0 * d0;
|
||||
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
|
||||
|
||||
|
@ -78,7 +78,7 @@
|
||||
+ // CraftBukkit start
|
||||
+ public final LevelStorageSource.LevelStorageAccess convertable;
|
||||
+ public final UUID uuid;
|
||||
+
|
||||
|
||||
+ public LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
+ return this.chunkSource.getChunk(x, z, false);
|
||||
+ }
|
||||
@ -102,7 +102,7 @@
|
||||
+ ChunkGenerator chunkgenerator = worlddimension.generator();
|
||||
+ // CraftBukkit start
|
||||
+ this.serverLevelData.setWorld(this);
|
||||
|
||||
+
|
||||
+ if (biomeProvider != null) {
|
||||
+ BiomeSource worldChunkManager = new CustomWorldChunkManager(this.getWorld(), biomeProvider, this.server.registryAccess().lookupOrThrow(Registries.BIOME));
|
||||
+ if (chunkgenerator instanceof NoiseBasedChunkGenerator cga) {
|
||||
@ -284,14 +284,14 @@
|
||||
- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel));
|
||||
+ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, this.rainLevel));
|
||||
+ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel));
|
||||
}
|
||||
+ }
|
||||
+ // */
|
||||
+ for (int idx = 0; idx < this.players.size(); ++idx) {
|
||||
+ if (((ServerPlayer) this.players.get(idx)).level() == this) {
|
||||
+ ((ServerPlayer) this.players.get(idx)).tickWeather();
|
||||
+ }
|
||||
+ }
|
||||
|
||||
+
|
||||
+ if (flag != this.isRaining()) {
|
||||
+ // Only send weather packets to those affected
|
||||
+ for (int idx = 0; idx < this.players.size(); ++idx) {
|
||||
@ -299,14 +299,14 @@
|
||||
+ ((ServerPlayer) this.players.get(idx)).setPlayerWeather((!flag ? WeatherType.DOWNFALL : WeatherType.CLEAR), false);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ for (int idx = 0; idx < this.players.size(); ++idx) {
|
||||
+ if (((ServerPlayer) this.players.get(idx)).level() == this) {
|
||||
+ ((ServerPlayer) this.players.get(idx)).updateWeather(this.oRainLevel, this.rainLevel, this.oThunderLevel, this.thunderLevel);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@ -421,13 +421,14 @@
|
||||
}
|
||||
|
||||
}
|
||||
@@ -939,24 +1061,37 @@
|
||||
@@ -939,24 +1061,38 @@
|
||||
this.entityManager.addNewEntity(player);
|
||||
}
|
||||
|
||||
- private boolean addEntity(Entity entity) {
|
||||
+ // CraftBukkit start
|
||||
+ private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
|
||||
if (entity.isRemoved()) {
|
||||
- ServerLevel.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityType.getKey(entity.getType()));
|
||||
+ // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit
|
||||
@ -463,7 +464,7 @@
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -967,13 +1102,35 @@
|
||||
@@ -967,13 +1103,35 @@
|
||||
}
|
||||
|
||||
public void removePlayerImmediately(ServerPlayer player, Entity.RemovalReason reason) {
|
||||
@ -500,7 +501,7 @@
|
||||
while (iterator.hasNext()) {
|
||||
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
|
||||
|
||||
@@ -982,6 +1139,12 @@
|
||||
@@ -982,6 +1140,12 @@
|
||||
double d1 = (double) pos.getY() - entityplayer.getY();
|
||||
double d2 = (double) pos.getZ() - entityplayer.getZ();
|
||||
|
||||
@ -513,7 +514,7 @@
|
||||
if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) {
|
||||
entityplayer.connection.send(new ClientboundBlockDestructionPacket(entityId, pos, progress));
|
||||
}
|
||||
@@ -1060,7 +1223,18 @@
|
||||
@@ -1060,7 +1224,18 @@
|
||||
Iterator iterator = this.navigatingMobs.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
@ -533,7 +534,7 @@
|
||||
PathNavigation navigationabstract = entityinsentient.getNavigation();
|
||||
|
||||
if (navigationabstract.shouldRecomputePath(pos)) {
|
||||
@@ -1126,9 +1300,15 @@
|
||||
@@ -1126,9 +1301,15 @@
|
||||
|
||||
@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) {
|
||||
@ -550,7 +551,7 @@
|
||||
case NONE:
|
||||
explosion_effect = Explosion.BlockInteraction.KEEP;
|
||||
break;
|
||||
@@ -1144,16 +1324,26 @@
|
||||
@@ -1144,16 +1325,26 @@
|
||||
case TRIGGER:
|
||||
explosion_effect = Explosion.BlockInteraction.TRIGGER_BLOCK;
|
||||
break;
|
||||
@ -580,7 +581,7 @@
|
||||
Iterator iterator = this.players.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
@@ -1162,10 +1352,11 @@
|
||||
@@ -1162,10 +1353,11 @@
|
||||
if (entityplayer.distanceToSqr(vec3d) < 4096.0D) {
|
||||
Optional<Vec3> optional = Optional.ofNullable((Vec3) serverexplosion.getHitPlayers().get(entityplayer));
|
||||
|
||||
@ -593,7 +594,7 @@
|
||||
}
|
||||
|
||||
private Explosion.BlockInteraction getDestroyType(GameRules.Key<GameRules.BooleanValue> decayRule) {
|
||||
@@ -1226,17 +1417,24 @@
|
||||
@@ -1226,17 +1418,24 @@
|
||||
}
|
||||
|
||||
public <T extends ParticleOptions> int sendParticles(T parameters, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double speed) {
|
||||
@ -621,7 +622,7 @@
|
||||
++j;
|
||||
}
|
||||
}
|
||||
@@ -1292,7 +1490,7 @@
|
||||
@@ -1292,7 +1491,7 @@
|
||||
|
||||
@Nullable
|
||||
public BlockPos findNearestMapStructure(TagKey<Structure> structureTag, BlockPos pos, int radius, boolean skipReferencedStructures) {
|
||||
@ -630,7 +631,7 @@
|
||||
return null;
|
||||
} else {
|
||||
Optional<HolderSet.Named<Structure>> optional = this.registryAccess().lookupOrThrow(Registries.STRUCTURE).get(structureTag);
|
||||
@@ -1334,11 +1532,22 @@
|
||||
@@ -1334,11 +1533,22 @@
|
||||
@Nullable
|
||||
@Override
|
||||
public MapItemSavedData getMapData(MapId id) {
|
||||
@ -654,7 +655,7 @@
|
||||
this.getServer().overworld().getDataStorage().set(id.key(), state);
|
||||
}
|
||||
|
||||
@@ -1649,6 +1858,11 @@
|
||||
@@ -1649,6 +1859,11 @@
|
||||
@Override
|
||||
public void blockUpdated(BlockPos pos, Block block) {
|
||||
if (!this.isDebug()) {
|
||||
@ -666,7 +667,7 @@
|
||||
this.updateNeighborsAt(pos, block);
|
||||
}
|
||||
|
||||
@@ -1668,12 +1882,12 @@
|
||||
@@ -1668,12 +1883,12 @@
|
||||
}
|
||||
|
||||
public boolean isFlat() {
|
||||
@ -681,7 +682,7 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1696,7 +1910,7 @@
|
||||
@@ -1696,7 +1911,7 @@
|
||||
private static <T> String getTypeCount(Iterable<T> items, Function<T, String> classifier) {
|
||||
try {
|
||||
Object2IntOpenHashMap<String> object2intopenhashmap = new Object2IntOpenHashMap();
|
||||
@ -690,7 +691,7 @@
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
T t0 = iterator.next();
|
||||
@@ -1705,7 +1919,7 @@
|
||||
@@ -1705,7 +1920,7 @@
|
||||
object2intopenhashmap.addTo(s, 1);
|
||||
}
|
||||
|
||||
@ -699,7 +700,23 @@
|
||||
String s1 = (String) entry.getKey();
|
||||
|
||||
return s1 + ":" + entry.getIntValue();
|
||||
@@ -1864,6 +2078,8 @@
|
||||
@@ -1717,6 +1932,7 @@
|
||||
|
||||
@Override
|
||||
public LevelEntityGetter<Entity> getEntities() {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
|
||||
return this.entityManager.getEntityGetter();
|
||||
}
|
||||
|
||||
@@ -1836,6 +2052,7 @@
|
||||
}
|
||||
|
||||
public void onTrackingStart(Entity entity) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
|
||||
ServerLevel.this.getChunkSource().addEntity(entity);
|
||||
if (entity instanceof ServerPlayer entityplayer) {
|
||||
ServerLevel.this.players.add(entityplayer);
|
||||
@@ -1864,9 +2081,12 @@
|
||||
}
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
|
||||
@ -708,7 +725,11 @@
|
||||
}
|
||||
|
||||
public void onTrackingEnd(Entity entity) {
|
||||
@@ -1895,6 +2111,14 @@
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot
|
||||
ServerLevel.this.getChunkSource().removeEntity(entity);
|
||||
if (entity instanceof ServerPlayer entityplayer) {
|
||||
ServerLevel.this.players.remove(entityplayer);
|
||||
@@ -1895,6 +2115,14 @@
|
||||
}
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);
|
||||
|
@ -216,10 +216,13 @@
|
||||
this.activeEffects.clear();
|
||||
}
|
||||
|
||||
@@ -781,6 +841,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -778,8 +838,19 @@
|
||||
if (mobeffect != null) {
|
||||
this.activeEffects.put(mobeffect.getEffect(), mobeffect);
|
||||
}
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ if (nbt.contains("Bukkit.MaxHealth")) {
|
||||
+ Tag nbtbase = nbt.get("Bukkit.MaxHealth");
|
||||
@ -227,13 +230,12 @@
|
||||
+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((FloatTag) nbtbase).getAsDouble());
|
||||
+ } else if (nbtbase.getId() == 3) {
|
||||
+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((IntTag) nbtbase).getAsDouble());
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
|
||||
if (nbt.contains("Health", 99)) {
|
||||
this.setHealth(nbt.getFloat("Health"));
|
||||
}
|
||||
@@ -819,9 +890,32 @@
|
||||
|
||||
}
|
||||
@ -348,7 +350,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,24 +1117,54 @@
|
||||
@@ -987,24 +1117,55 @@
|
||||
return this.addEffect(effect, (Entity) null);
|
||||
}
|
||||
|
||||
@ -363,6 +365,7 @@
|
||||
+ }
|
||||
+
|
||||
+ public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot
|
||||
+ if (this.isTickingEffects) {
|
||||
+ this.effectsToProcess.add(new ProcessableEffect(mobeffect, cause));
|
||||
+ return true;
|
||||
@ -412,7 +415,7 @@
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
@@ -1031,14 +1191,40 @@
|
||||
@@ -1031,14 +1192,40 @@
|
||||
return this.getType().is(EntityTypeTags.INVERTED_HEALING_AND_HARM);
|
||||
}
|
||||
|
||||
@ -455,7 +458,7 @@
|
||||
if (mobeffect != null) {
|
||||
this.onEffectsRemoved(List.of(mobeffect));
|
||||
return true;
|
||||
@@ -1142,20 +1328,55 @@
|
||||
@@ -1142,20 +1329,55 @@
|
||||
|
||||
}
|
||||
|
||||
@ -512,7 +515,7 @@
|
||||
this.entityData.set(LivingEntity.DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth()));
|
||||
}
|
||||
|
||||
@@ -1167,7 +1388,7 @@
|
||||
@@ -1167,7 +1389,7 @@
|
||||
public boolean hurtServer(ServerLevel world, DamageSource source, float amount) {
|
||||
if (this.isInvulnerableTo(world, source)) {
|
||||
return false;
|
||||
@ -521,7 +524,7 @@
|
||||
return false;
|
||||
} else if (source.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) {
|
||||
return false;
|
||||
@@ -1182,10 +1403,11 @@
|
||||
@@ -1182,10 +1404,11 @@
|
||||
}
|
||||
|
||||
float f1 = amount;
|
||||
@ -535,7 +538,7 @@
|
||||
this.hurtCurrentlyUsedShield(amount);
|
||||
f2 = amount;
|
||||
amount = 0.0F;
|
||||
@@ -1202,15 +1424,26 @@
|
||||
@@ -1202,15 +1425,26 @@
|
||||
flag = true;
|
||||
}
|
||||
|
||||
@ -564,7 +567,7 @@
|
||||
this.walkAnimation.setSpeed(1.5F);
|
||||
if (Float.isNaN(amount) || Float.isInfinite(amount)) {
|
||||
amount = Float.MAX_VALUE;
|
||||
@@ -1218,18 +1451,27 @@
|
||||
@@ -1218,18 +1452,27 @@
|
||||
|
||||
boolean flag1 = true;
|
||||
|
||||
@ -596,7 +599,7 @@
|
||||
this.hurtDuration = 10;
|
||||
this.hurtTime = this.hurtDuration;
|
||||
}
|
||||
@@ -1243,7 +1485,7 @@
|
||||
@@ -1243,7 +1486,7 @@
|
||||
world.broadcastDamageEvent(this, source);
|
||||
}
|
||||
|
||||
@ -605,7 +608,7 @@
|
||||
this.markHurt();
|
||||
}
|
||||
|
||||
@@ -1263,7 +1505,7 @@
|
||||
@@ -1263,7 +1506,7 @@
|
||||
d1 = source.getSourcePosition().z() - this.getZ();
|
||||
}
|
||||
|
||||
@ -614,7 +617,7 @@
|
||||
if (!flag) {
|
||||
this.indicateDamage(d0, d1);
|
||||
}
|
||||
@@ -1282,7 +1524,7 @@
|
||||
@@ -1282,7 +1525,7 @@
|
||||
this.playHurtSound(source);
|
||||
}
|
||||
|
||||
@ -623,7 +626,7 @@
|
||||
|
||||
if (flag2) {
|
||||
this.lastDamageSource = source;
|
||||
@@ -1329,10 +1571,10 @@
|
||||
@@ -1329,10 +1572,10 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -636,7 +639,7 @@
|
||||
this.lastHurtByPlayerTime = 100;
|
||||
this.lastHurtByPlayer = entityhuman;
|
||||
return entityhuman;
|
||||
@@ -1342,8 +1584,8 @@
|
||||
@@ -1342,8 +1585,8 @@
|
||||
this.lastHurtByPlayerTime = 100;
|
||||
LivingEntity entityliving = entitywolf.getOwner();
|
||||
|
||||
@ -647,7 +650,7 @@
|
||||
|
||||
this.lastHurtByPlayer = entityhuman1;
|
||||
} else {
|
||||
@@ -1363,7 +1605,7 @@
|
||||
@@ -1363,7 +1606,7 @@
|
||||
}
|
||||
|
||||
protected void blockedByShield(LivingEntity target) {
|
||||
@ -656,7 +659,7 @@
|
||||
}
|
||||
|
||||
private boolean checkTotemDeathProtection(DamageSource source) {
|
||||
@@ -1375,20 +1617,33 @@
|
||||
@@ -1375,20 +1618,33 @@
|
||||
InteractionHand[] aenumhand = InteractionHand.values();
|
||||
int i = aenumhand.length;
|
||||
|
||||
@ -694,7 +697,7 @@
|
||||
ServerPlayer entityplayer = (ServerPlayer) this;
|
||||
|
||||
entityplayer.awardStat(Stats.ITEM_USED.get(itemstack.getItem()));
|
||||
@@ -1512,14 +1767,22 @@
|
||||
@@ -1512,14 +1768,22 @@
|
||||
BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState();
|
||||
|
||||
if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) {
|
||||
@ -719,7 +722,7 @@
|
||||
this.level().addFreshEntity(entityitem);
|
||||
}
|
||||
}
|
||||
@@ -1530,24 +1793,39 @@
|
||||
@@ -1530,22 +1794,37 @@
|
||||
protected void dropAllDeathLoot(ServerLevel world, DamageSource damageSource) {
|
||||
boolean flag = this.lastHurtByPlayerTime > 0;
|
||||
|
||||
@ -749,8 +752,8 @@
|
||||
}
|
||||
|
||||
+ return 0; // CraftBukkit
|
||||
}
|
||||
|
||||
+ }
|
||||
+
|
||||
+ protected void dropExperience(ServerLevel world, @Nullable Entity attacker) {
|
||||
+ // CraftBukkit start - Update getExpReward() above if the removed if() changes!
|
||||
+ if (!(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time
|
||||
@ -758,12 +761,10 @@
|
||||
+ this.expToDrop = 0;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
protected void dropCustomDeathLoot(ServerLevel world, DamageSource source, boolean causedByPlayer) {}
|
||||
}
|
||||
|
||||
public long getLootTableSeed() {
|
||||
@@ -1612,19 +1890,31 @@
|
||||
protected void dropCustomDeathLoot(ServerLevel world, DamageSource source, boolean causedByPlayer) {}
|
||||
@@ -1612,19 +1891,31 @@
|
||||
}
|
||||
|
||||
public void knockback(double strength, double x, double z) {
|
||||
@ -802,7 +803,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1683,6 +1973,20 @@
|
||||
@@ -1683,6 +1974,20 @@
|
||||
return new LivingEntity.Fallsounds(SoundEvents.GENERIC_SMALL_FALL, SoundEvents.GENERIC_BIG_FALL);
|
||||
}
|
||||
|
||||
@ -823,7 +824,7 @@
|
||||
public Optional<BlockPos> getLastClimbablePos() {
|
||||
return this.lastClimbablePos;
|
||||
}
|
||||
@@ -1757,9 +2061,14 @@
|
||||
@@ -1757,9 +2062,14 @@
|
||||
int i = this.calculateFallDamage(fallDistance, damageMultiplier);
|
||||
|
||||
if (i > 0) {
|
||||
@ -839,7 +840,7 @@
|
||||
return true;
|
||||
} else {
|
||||
return flag;
|
||||
@@ -1830,7 +2139,7 @@
|
||||
@@ -1830,7 +2140,7 @@
|
||||
|
||||
protected float getDamageAfterArmorAbsorb(DamageSource source, float amount) {
|
||||
if (!source.is(DamageTypeTags.BYPASSES_ARMOR)) {
|
||||
@ -848,7 +849,7 @@
|
||||
amount = CombatRules.getDamageAfterAbsorb(this, amount, source, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS));
|
||||
}
|
||||
|
||||
@@ -1841,7 +2150,8 @@
|
||||
@@ -1841,7 +2151,8 @@
|
||||
if (source.is(DamageTypeTags.BYPASSES_EFFECTS)) {
|
||||
return amount;
|
||||
} else {
|
||||
@ -858,7 +859,7 @@
|
||||
int i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5;
|
||||
int j = 25 - i;
|
||||
float f1 = amount * (float) j;
|
||||
@@ -1884,18 +2194,144 @@
|
||||
@@ -1884,18 +2195,144 @@
|
||||
}
|
||||
}
|
||||
|
||||
@ -1012,7 +1013,7 @@
|
||||
|
||||
if (entity instanceof ServerPlayer) {
|
||||
ServerPlayer entityplayer = (ServerPlayer) entity;
|
||||
@@ -1904,13 +2340,48 @@
|
||||
@@ -1904,13 +2341,48 @@
|
||||
}
|
||||
}
|
||||
|
||||
@ -1065,7 +1066,7 @@
|
||||
}
|
||||
|
||||
public CombatTracker getCombatTracker() {
|
||||
@@ -1935,9 +2406,19 @@
|
||||
@@ -1935,9 +2407,19 @@
|
||||
}
|
||||
|
||||
public final void setArrowCount(int stuckArrowCount) {
|
||||
@ -1086,7 +1087,7 @@
|
||||
public final int getStingerCount() {
|
||||
return (Integer) this.entityData.get(LivingEntity.DATA_STINGER_COUNT_ID);
|
||||
}
|
||||
@@ -1999,7 +2480,7 @@
|
||||
@@ -1999,7 +2481,7 @@
|
||||
this.playSound(soundeffect, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F);
|
||||
}
|
||||
|
||||
@ -1095,7 +1096,7 @@
|
||||
this.setHealth(0.0F);
|
||||
this.die(this.damageSources().generic());
|
||||
}
|
||||
@@ -2182,6 +2663,12 @@
|
||||
@@ -2182,6 +2664,12 @@
|
||||
|
||||
public abstract ItemStack getItemBySlot(EquipmentSlot slot);
|
||||
|
||||
@ -1108,7 +1109,7 @@
|
||||
public abstract void setItemSlot(EquipmentSlot slot, ItemStack stack);
|
||||
|
||||
public Iterable<ItemStack> getHandSlots() {
|
||||
@@ -2494,7 +2981,7 @@
|
||||
@@ -2494,7 +2982,7 @@
|
||||
|
||||
}
|
||||
|
||||
@ -1117,7 +1118,7 @@
|
||||
Vec3 vec3d1 = this.getRiddenInput(controllingPlayer, movementInput);
|
||||
|
||||
this.tickRidden(controllingPlayer, vec3d1);
|
||||
@@ -2507,13 +2994,13 @@
|
||||
@@ -2507,13 +2995,13 @@
|
||||
|
||||
}
|
||||
|
||||
@ -1134,7 +1135,7 @@
|
||||
return this.getSpeed();
|
||||
}
|
||||
|
||||
@@ -2571,7 +3058,7 @@
|
||||
@@ -2571,7 +3059,7 @@
|
||||
double d1 = Mth.clamp(motion.z, -0.15000000596046448D, 0.15000000596046448D);
|
||||
double d2 = Math.max(motion.y, -0.15000000596046448D);
|
||||
|
||||
@ -1143,7 +1144,7 @@
|
||||
d2 = 0.0D;
|
||||
}
|
||||
|
||||
@@ -2586,7 +3073,7 @@
|
||||
@@ -2586,7 +3074,7 @@
|
||||
}
|
||||
|
||||
protected float getFlyingSpeed() {
|
||||
@ -1152,7 +1153,7 @@
|
||||
}
|
||||
|
||||
public float getSpeed() {
|
||||
@@ -2634,7 +3121,7 @@
|
||||
@@ -2634,7 +3122,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@ -1161,7 +1162,7 @@
|
||||
if (this.tickCount % 20 == 0) {
|
||||
this.getCombatTracker().recheckStatus();
|
||||
}
|
||||
@@ -2741,7 +3228,7 @@
|
||||
@@ -2741,7 +3229,7 @@
|
||||
this.elytraAnimationState.tick();
|
||||
}
|
||||
|
||||
@ -1170,7 +1171,7 @@
|
||||
Map<EquipmentSlot, ItemStack> map = this.collectEquipmentChanges();
|
||||
|
||||
if (map != null) {
|
||||
@@ -3000,7 +3487,7 @@
|
||||
@@ -3000,7 +3488,7 @@
|
||||
{
|
||||
LivingEntity entityliving = this.getControllingPassenger();
|
||||
|
||||
@ -1179,7 +1180,7 @@
|
||||
if (this.isAlive()) {
|
||||
this.travelRidden(entityhuman, vec3d1);
|
||||
break label112;
|
||||
@@ -3063,6 +3550,7 @@
|
||||
@@ -3063,6 +3551,7 @@
|
||||
this.checkSlowFallDistance();
|
||||
if (!this.level().isClientSide) {
|
||||
if (!this.canGlide()) {
|
||||
@ -1187,7 +1188,7 @@
|
||||
this.setSharedFlag(7, false);
|
||||
return;
|
||||
}
|
||||
@@ -3113,7 +3601,7 @@
|
||||
@@ -3113,7 +3602,7 @@
|
||||
Level world = this.level();
|
||||
|
||||
if (!(world instanceof ServerLevel worldserver)) {
|
||||
@ -1196,7 +1197,7 @@
|
||||
} else {
|
||||
List list = this.level().getEntities((Entity) this, this.getBoundingBox(), EntitySelector.pushableBy(this));
|
||||
|
||||
@@ -3305,15 +3793,22 @@
|
||||
@@ -3305,15 +3794,22 @@
|
||||
|
||||
@Override
|
||||
public boolean isPickable() {
|
||||
@ -1221,7 +1222,7 @@
|
||||
public float getYHeadRot() {
|
||||
return this.yHeadRot;
|
||||
}
|
||||
@@ -3483,8 +3978,31 @@
|
||||
@@ -3483,8 +3979,31 @@
|
||||
this.releaseUsingItem();
|
||||
} else {
|
||||
if (!this.useItem.isEmpty() && this.isUsingItem()) {
|
||||
@ -1254,7 +1255,7 @@
|
||||
if (itemstack != this.useItem) {
|
||||
this.setItemInHand(enumhand, itemstack);
|
||||
}
|
||||
@@ -3568,12 +4086,18 @@
|
||||
@@ -3568,12 +4087,18 @@
|
||||
}
|
||||
|
||||
public boolean randomTeleport(double x, double y, double z, boolean particleEffects) {
|
||||
@ -1275,7 +1276,7 @@
|
||||
Level world = this.level();
|
||||
|
||||
if (world.hasChunkAt(blockposition)) {
|
||||
@@ -3592,18 +4116,43 @@
|
||||
@@ -3592,18 +4117,43 @@
|
||||
}
|
||||
|
||||
if (flag2) {
|
||||
@ -1323,7 +1324,7 @@
|
||||
world.broadcastEntityEvent(this, (byte) 46);
|
||||
}
|
||||
|
||||
@@ -3613,7 +4162,7 @@
|
||||
@@ -3613,7 +4163,7 @@
|
||||
entitycreature.getNavigation().stop();
|
||||
}
|
||||
|
||||
@ -1332,7 +1333,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3706,7 +4255,7 @@
|
||||
@@ -3706,7 +4256,7 @@
|
||||
}
|
||||
|
||||
public void stopSleeping() {
|
||||
@ -1341,7 +1342,7 @@
|
||||
Level world = this.level();
|
||||
|
||||
java.util.Objects.requireNonNull(world);
|
||||
@@ -3718,9 +4267,9 @@
|
||||
@@ -3718,9 +4268,9 @@
|
||||
|
||||
this.level().setBlock(blockposition, (BlockState) iblockdata.setValue(BedBlock.OCCUPIED, false), 3);
|
||||
Vec3 vec3d = (Vec3) BedBlock.findStandUpPosition(this.getType(), this.level(), blockposition, enumdirection, this.getYRot()).orElseGet(() -> {
|
||||
@ -1353,7 +1354,7 @@
|
||||
});
|
||||
Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize();
|
||||
float f = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D);
|
||||
@@ -3740,7 +4289,7 @@
|
||||
@@ -3740,7 +4290,7 @@
|
||||
|
||||
@Nullable
|
||||
public Direction getBedOrientation() {
|
||||
@ -1362,7 +1363,7 @@
|
||||
|
||||
return blockposition != null ? BedBlock.getBedOrientation(this.level(), blockposition) : null;
|
||||
}
|
||||
@@ -3905,7 +4454,7 @@
|
||||
@@ -3905,7 +4455,7 @@
|
||||
public float maxUpStep() {
|
||||
float f = (float) this.getAttributeValue(Attributes.STEP_HEIGHT);
|
||||
|
||||
|
@ -29,14 +29,13 @@
|
||||
public class RecipeManager extends SimplePreparableReloadListener<RecipeMap> implements RecipeAccess {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -109,9 +114,27 @@
|
||||
protected void apply(RecipeMap prepared, ResourceManager manager, ProfilerFiller profiler) {
|
||||
this.recipes = prepared;
|
||||
@@ -111,7 +116,26 @@
|
||||
RecipeManager.LOGGER.info("Loaded {} recipes", prepared.values().size());
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public void addRecipe(RecipeHolder<?> irecipe) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("Recipe Add"); // Spigot
|
||||
+ this.recipes.addRecipe(irecipe);
|
||||
+ this.finalizeRecipeLoading();
|
||||
+ }
|
||||
@ -49,15 +48,15 @@
|
||||
+
|
||||
+ MinecraftServer.getServer().getPlayerList().reloadRecipes();
|
||||
+ }
|
||||
}
|
||||
|
||||
+ }
|
||||
+
|
||||
public void finalizeRecipeLoading(FeatureFlagSet features) {
|
||||
+ this.featureflagset = features;
|
||||
+ // CraftBukkit end
|
||||
List<SelectableRecipe.SingleInputEntry<StonecutterRecipe>> list = new ArrayList();
|
||||
List<RecipeManager.IngredientCollector> list1 = RecipeManager.RECIPE_PROPERTY_SETS.entrySet().stream().map((entry) -> {
|
||||
return new RecipeManager.IngredientCollector((ResourceKey) entry.getKey(), (RecipeManager.IngredientExtractor) entry.getValue());
|
||||
@@ -130,7 +153,7 @@
|
||||
@@ -130,7 +154,7 @@
|
||||
StonecutterRecipe recipestonecutting = (StonecutterRecipe) irecipe;
|
||||
|
||||
if (RecipeManager.isIngredientEnabled(features, recipestonecutting.input()) && recipestonecutting.resultDisplay().isEnabled(features)) {
|
||||
@ -66,7 +65,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +195,10 @@
|
||||
@@ -172,7 +196,10 @@
|
||||
}
|
||||
|
||||
public <I extends RecipeInput, T extends Recipe<I>> Optional<RecipeHolder<T>> getRecipeFor(RecipeType<T> type, I input, Level world) {
|
||||
@ -78,7 +77,7 @@
|
||||
}
|
||||
|
||||
public Optional<RecipeHolder<?>> byKey(ResourceKey<Recipe<?>> key) {
|
||||
@@ -183,7 +209,7 @@
|
||||
@@ -183,7 +210,7 @@
|
||||
private <T extends Recipe<?>> RecipeHolder<T> byKeyTyped(RecipeType<T> type, ResourceKey<Recipe<?>> key) {
|
||||
RecipeHolder<?> recipeholder = this.recipes.byKey(key);
|
||||
|
||||
@ -87,7 +86,7 @@
|
||||
}
|
||||
|
||||
public Map<ResourceKey<RecipePropertySet>, RecipePropertySet> getSynchronizedItemProperties() {
|
||||
@@ -231,6 +257,22 @@
|
||||
@@ -231,6 +258,22 @@
|
||||
return new RecipeHolder<>(key, irecipe);
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,14 @@
|
||||
|
||||
public abstract class BlockBehaviour implements FeatureElement {
|
||||
|
||||
@@ -158,6 +161,12 @@
|
||||
@@ -156,9 +159,18 @@
|
||||
|
||||
protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {}
|
||||
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, @Nullable Orientation wireOrientation, boolean notify) {}
|
||||
|
||||
- protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {}
|
||||
+ protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot
|
||||
+ }
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ protected void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, @Nullable UseOnContext context) {
|
||||
@ -28,9 +33,11 @@
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
protected void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("block remove"); // Spigot
|
||||
if (state.hasBlockEntity() && !state.is(newState.getBlock())) {
|
||||
world.removeBlockEntity(pos);
|
||||
@@ -174,8 +183,10 @@
|
||||
}
|
||||
@@ -174,8 +186,10 @@
|
||||
BlockEntity tileentity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
||||
LootParams.Builder lootparams_a = (new LootParams.Builder(world)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, explosion.getDirectSourceEntity());
|
||||
|
||||
@ -43,7 +50,7 @@
|
||||
}
|
||||
|
||||
state.spawnAfterBreak(world, pos, ItemStack.EMPTY, flag);
|
||||
@@ -1125,9 +1136,15 @@
|
||||
@@ -1125,9 +1139,15 @@
|
||||
}
|
||||
|
||||
public void onPlace(Level world, BlockPos pos, BlockState state, boolean notify) {
|
||||
|
@ -898,6 +898,7 @@ public final class CraftServer implements Server {
|
||||
public boolean dispatchCommand(CommandSender sender, String commandLine) {
|
||||
Preconditions.checkArgument(sender != null, "sender cannot be null");
|
||||
Preconditions.checkArgument(commandLine != null, "commandLine cannot be null");
|
||||
org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot
|
||||
|
||||
if (this.commandMap.dispatch(sender, commandLine)) {
|
||||
return true;
|
||||
|
@ -283,6 +283,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public boolean unloadChunkRequest(int x, int z) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot
|
||||
if (this.isChunkLoaded(x, z)) {
|
||||
this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE);
|
||||
}
|
||||
@ -291,6 +292,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
}
|
||||
|
||||
private boolean unloadChunk0(int x, int z, boolean save) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot
|
||||
if (!this.isChunkLoaded(x, z)) {
|
||||
return true;
|
||||
}
|
||||
@ -307,6 +309,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(int x, int z) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("chunk regenerate"); // Spigot
|
||||
throw new UnsupportedOperationException("Not supported in this Minecraft version! Unless you can fix it, this is not a bug :)");
|
||||
/*
|
||||
if (!unloadChunk0(x, z, false)) {
|
||||
@ -384,6 +387,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public boolean loadChunk(int x, int z, boolean generate) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot
|
||||
ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true);
|
||||
|
||||
// If generate = false, but the chunk already exists, we will get this back.
|
||||
@ -919,6 +923,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public Collection<Entity> getNearbyEntities(BoundingBox boundingBox, Predicate<? super Entity> filter) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("getNearbyEntities"); // Spigot
|
||||
Preconditions.checkArgument(boundingBox != null, "BoundingBox cannot be null");
|
||||
|
||||
AABB bb = new AABB(boundingBox.getMinX(), boundingBox.getMinY(), boundingBox.getMinZ(), boundingBox.getMaxX(), boundingBox.getMaxY(), boundingBox.getMaxZ());
|
||||
@ -1073,6 +1078,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot
|
||||
this.server.checkSaveState();
|
||||
boolean oldSave = this.world.noSave;
|
||||
|
||||
|
@ -228,6 +228,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
@Override
|
||||
public List<org.bukkit.entity.Entity> getNearbyEntities(double x, double y, double z) {
|
||||
Preconditions.checkState(!this.entity.generation, "Cannot get nearby entities during world generation");
|
||||
org.spigotmc.AsyncCatcher.catchOp("getNearbyEntities"); // Spigot
|
||||
|
||||
List<Entity> notchEntityList = this.entity.level().getEntities(this.entity, this.entity.getBoundingBox().inflate(x, y, z), Predicates.alwaysTrue());
|
||||
List<org.bukkit.entity.Entity> bukkitEntityList = new java.util.ArrayList<org.bukkit.entity.Entity>(notchEntityList.size());
|
||||
|
@ -492,6 +492,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
|
||||
@Override
|
||||
public void kickPlayer(String message) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot
|
||||
this.getHandle().transferCookieConnection.kickPlayer(CraftChatMessage.fromStringOrEmpty(message, true));
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ public final class CraftScoreboardManager implements ScoreboardManager {
|
||||
|
||||
@Override
|
||||
public CraftScoreboard getNewScoreboard() {
|
||||
org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot
|
||||
CraftScoreboard scoreboard = new CraftScoreboard(new ServerScoreboard(this.server));
|
||||
this.scoreboards.add(scoreboard);
|
||||
return scoreboard;
|
||||
|
@ -12,6 +12,7 @@ public class ServerShutdownThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
org.spigotmc.AsyncCatcher.enabled = false; // Spigot
|
||||
this.server.close();
|
||||
} finally {
|
||||
try {
|
||||
|
17
paper-server/src/main/java/org/spigotmc/AsyncCatcher.java
Normal file
17
paper-server/src/main/java/org/spigotmc/AsyncCatcher.java
Normal file
@ -0,0 +1,17 @@
|
||||
package org.spigotmc;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class AsyncCatcher
|
||||
{
|
||||
|
||||
public static boolean enabled = true;
|
||||
|
||||
public static void catchOp(String reason)
|
||||
{
|
||||
if ( AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread )
|
||||
{
|
||||
throw new IllegalStateException( "Asynchronous " + reason + "!" );
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user