253
This commit is contained in:
parent
8244815161
commit
309ebc13fc
33 changed files with 205 additions and 207 deletions
60
patches/server/0222-Improve-BlockPosition-inlining.patch
Normal file
60
patches/server/0222-Improve-BlockPosition-inlining.patch
Normal file
|
@ -0,0 +1,60 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Techcable <Techcable@outlook.com>
|
||||
Date: Wed, 30 Nov 2016 20:56:58 -0600
|
||||
Subject: [PATCH] Improve BlockPosition inlining
|
||||
|
||||
Normally the JVM can inline virtual getters by having two sets of code, one is the 'optimized' code and the other is the 'deoptimized' code.
|
||||
If a single type is used 99% of the time, then its worth it to inline, and to revert to 'deoptimized' the 1% of the time we encounter other types.
|
||||
But if two types are encountered commonly, then the JVM can't inline them both, and the call overhead remains.
|
||||
|
||||
This scenario also occurs with BlockPos and MutableBlockPos.
|
||||
The variables in BlockPos are final, so MutableBlockPos can't modify them.
|
||||
MutableBlockPos fixes this by adding custom mutable variables, and overriding the getters to access them.
|
||||
|
||||
This approach with utility methods that operate on MutableBlockPos and BlockPos.
|
||||
Specific examples are BlockPosition.up(), and World.isValidLocation().
|
||||
It makes these simple methods much slower than they need to be.
|
||||
|
||||
This should result in an across the board speedup in anything that accesses blocks or does logic with positions.
|
||||
|
||||
This is based upon conclusions drawn from inspecting the assenmbly generated bythe JIT compiler on my microbenchmarks.
|
||||
They had 'callq' (invoke) instead of 'mov' (get from memory) instructions.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java
|
||||
index ea4660fe600db94e97a5dd335135f76dd5951468..df4c9b275752ad97a4efe9380ae0d511ee760695 100644
|
||||
--- a/src/main/java/net/minecraft/core/Vec3i.java
|
||||
+++ b/src/main/java/net/minecraft/core/Vec3i.java
|
||||
@@ -35,12 +35,12 @@ public class Vec3i implements Comparable<Vec3i> {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public boolean equals(Object object) {
|
||||
+ public final boolean equals(Object object) { // Paper - Perf: Final for inline
|
||||
return this == object || object instanceof Vec3i vec3i && this.getX() == vec3i.getX() && this.getY() == vec3i.getY() && this.getZ() == vec3i.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
- public int hashCode() {
|
||||
+ public final int hashCode() { // Paper - Perf: Final for inline
|
||||
return (this.getY() + this.getZ() * 31) * 31 + this.getX();
|
||||
}
|
||||
|
||||
@@ -53,15 +53,15 @@ public class Vec3i implements Comparable<Vec3i> {
|
||||
}
|
||||
}
|
||||
|
||||
- public int getX() {
|
||||
+ public final int getX() { // Paper - Perf: Final for inline
|
||||
return this.x;
|
||||
}
|
||||
|
||||
- public int getY() {
|
||||
+ public final int getY() { // Paper - Perf: Final for inline
|
||||
return this.y;
|
||||
}
|
||||
|
||||
- public int getZ() {
|
||||
+ public final int getZ() { // Paper - Perf: Final for inline
|
||||
return this.z;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hugo Manrique <hugmanrique@gmail.com>
|
||||
Date: Mon, 23 Jul 2018 12:57:39 +0200
|
||||
Subject: [PATCH] Option to prevent armor stands from doing entity lookups
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
index d33c49c4a4b87a5203f9b4592deff9389e6e870d..62d63883f6a9f4da099491f697b309d4194b6082 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -344,6 +344,7 @@ public class ArmorStand extends LivingEntity {
|
||||
|
||||
@Override
|
||||
protected void pushEntities() {
|
||||
+ if (!this.level().paperConfig().entities.armorStands.doCollisionEntityLookups) return; // Paper - Option to prevent armor stands from doing entity lookups
|
||||
List<Entity> list = this.level().getEntities((Entity) this, this.getBoundingBox(), ArmorStand.RIDABLE_MINECARTS);
|
||||
Iterator iterator = list.iterator();
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index ce2957c8955b95865c07eb3f3d7d9fcca2438e5e..9e717a360dd50a2b4a5344011ae77811a3e182c1 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -760,6 +760,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
// Paper end - Prevent block entity and entity crashes
|
||||
}
|
||||
}
|
||||
+ // Paper start - Option to prevent armor stands from doing entity lookups
|
||||
+ @Override
|
||||
+ public boolean noCollision(@Nullable Entity entity, AABB box) {
|
||||
+ if (entity instanceof net.minecraft.world.entity.decoration.ArmorStand && !entity.level().paperConfig().entities.armorStands.doCollisionEntityLookups) return false;
|
||||
+ return LevelAccessor.super.noCollision(entity, box);
|
||||
+ }
|
||||
+ // Paper end - Option to prevent armor stands from doing entity lookups
|
||||
|
||||
public boolean shouldTickDeath(Entity entity) {
|
||||
return true;
|
109
patches/server/0224-Vanished-players-don-t-have-rights.patch
Normal file
109
patches/server/0224-Vanished-players-don-t-have-rights.patch
Normal file
|
@ -0,0 +1,109 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hugo Manrique <hugmanrique@gmail.com>
|
||||
Date: Mon, 23 Jul 2018 14:22:26 +0200
|
||||
Subject: [PATCH] Vanished players don't have rights
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
index 5e9ef75a14a91f01a1ae5b3fb591d7258740a75d..516999dc425d23c570dabfe4f3c829650a6d205d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
|
||||
@@ -276,6 +276,15 @@ public abstract class Projectile extends Entity implements TraceableEntity {
|
||||
} else {
|
||||
Entity entity1 = this.getOwner();
|
||||
|
||||
+ // Paper start - Cancel hit for vanished players
|
||||
+ if (entity1 instanceof net.minecraft.server.level.ServerPlayer && entity instanceof net.minecraft.server.level.ServerPlayer) {
|
||||
+ org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity();
|
||||
+ org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity();
|
||||
+ if (!shooter.canSee(collided)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Cancel hit for vanished players
|
||||
return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(entity);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
index 6ca74a5cf691ee92c84bd031e875f72440df6b32..cee3f1200af602b5dfd0b27d05eb01826c5bbb1d 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
@@ -174,7 +174,8 @@ public class BlockItem extends Item {
|
||||
Player entityhuman = context.getPlayer();
|
||||
CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of(entityhuman);
|
||||
// CraftBukkit start - store default return
|
||||
- boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision);
|
||||
+ Level world = context.getLevel(); // Paper - Cancel hit for vanished players
|
||||
+ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && world.checkEntityCollision(state, entityhuman, voxelshapecollision, context.getClickedPos(), true); // Paper - Cancel hit for vanished players
|
||||
org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null;
|
||||
|
||||
BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 9e717a360dd50a2b4a5344011ae77811a3e182c1..d050d72eb87a2d1b4723ab831dfef5e25c6a65b2 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -265,6 +265,45 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime);
|
||||
}
|
||||
|
||||
+ // Paper start - Cancel hit for vanished players
|
||||
+ // ret true if no collision
|
||||
+ public final boolean checkEntityCollision(BlockState data, Entity source, net.minecraft.world.phys.shapes.CollisionContext voxelshapedcollision,
|
||||
+ BlockPos position, boolean checkCanSee) {
|
||||
+ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape)
|
||||
+ net.minecraft.world.phys.shapes.VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision);
|
||||
+ if (voxelshape.isEmpty()) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ voxelshape = voxelshape.move((double) position.getX(), (double) position.getY(), (double) position.getZ());
|
||||
+ if (voxelshape.isEmpty()) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ List<Entity> entities = this.getEntities(null, voxelshape.bounds());
|
||||
+ for (int i = 0, len = entities.size(); i < len; ++i) {
|
||||
+ Entity entity = entities.get(i);
|
||||
+
|
||||
+ if (checkCanSee && source instanceof net.minecraft.server.level.ServerPlayer && entity instanceof net.minecraft.server.level.ServerPlayer
|
||||
+ && !((net.minecraft.server.level.ServerPlayer) source).getBukkitEntity().canSee(((net.minecraft.server.level.ServerPlayer) entity).getBukkitEntity())) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity));
|
||||
+ // elide the last check since vanilla calls with entity = null
|
||||
+ // only we care about the source for the canSee check
|
||||
+ if (entity.isRemoved() || !entity.blocksBuilding) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (net.minecraft.world.phys.shapes.Shapes.joinIsNotEmpty(voxelshape, net.minecraft.world.phys.shapes.Shapes.create(entity.getBoundingBox()), net.minecraft.world.phys.shapes.BooleanOp.AND)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - Cancel hit for vanished players
|
||||
@Override
|
||||
public boolean isClientSide() {
|
||||
return this.isClientSide;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 63fec320871781d92f5ec552aac7fc08b2009f59..cecadd303f40a0e4a3e8315aa58226b6eb3ff7c3 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1296,6 +1296,14 @@ public class CraftEventFactory {
|
||||
Projectile projectile = (Projectile) entity.getBukkitEntity();
|
||||
org.bukkit.entity.Entity collided = position.getEntity().getBukkitEntity();
|
||||
com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = new com.destroystokyo.paper.event.entity.ProjectileCollideEvent(projectile, collided);
|
||||
+
|
||||
+ if (projectile.getShooter() instanceof Player && collided instanceof Player) {
|
||||
+ if (!((Player) projectile.getShooter()).canSee((Player) collided)) {
|
||||
+ event.setCancelled(true);
|
||||
+ return event;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
return event;
|
||||
}
|
145
patches/server/0225-Allow-disabling-armor-stand-ticking.patch
Normal file
145
patches/server/0225-Allow-disabling-armor-stand-ticking.patch
Normal file
|
@ -0,0 +1,145 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Wed, 15 Aug 2018 01:26:09 -0700
|
||||
Subject: [PATCH] Allow disabling armor stand ticking
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
index 62d63883f6a9f4da099491f697b309d4194b6082..042968ff848da74be0c9fcf9bac3d0adfb135802 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -97,9 +97,16 @@ public class ArmorStand extends LivingEntity {
|
||||
public Rotations leftLegPose;
|
||||
public Rotations rightLegPose;
|
||||
public boolean canMove = true; // Paper
|
||||
+ // Paper start - Allow ArmorStands not to tick
|
||||
+ public boolean canTick = true;
|
||||
+ public boolean canTickSetByAPI = false;
|
||||
+ private boolean noTickPoseDirty = false;
|
||||
+ private boolean noTickEquipmentDirty = false;
|
||||
+ // Paper end - Allow ArmorStands not to tick
|
||||
|
||||
public ArmorStand(EntityType<? extends ArmorStand> type, Level world) {
|
||||
super(type, world);
|
||||
+ if (world != null) this.canTick = world.paperConfig().entities.armorStands.tick; // Paper - Allow ArmorStands not to tick
|
||||
this.handItems = NonNullList.withSize(2, ItemStack.EMPTY);
|
||||
this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY);
|
||||
this.headPose = ArmorStand.DEFAULT_HEAD_POSE;
|
||||
@@ -202,6 +209,7 @@ public class ArmorStand extends LivingEntity {
|
||||
this.onEquipItem(enumitemslot, (ItemStack) this.armorItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit
|
||||
}
|
||||
|
||||
+ this.noTickEquipmentDirty = true; // Paper - Allow ArmorStands not to tick; Still update equipment
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -244,6 +252,7 @@ public class ArmorStand extends LivingEntity {
|
||||
}
|
||||
|
||||
nbt.put("Pose", this.writePose());
|
||||
+ if (this.canTickSetByAPI) nbt.putBoolean("Paper.CanTickOverride", this.canTick); // Paper - Allow ArmorStands not to tick
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -278,6 +287,12 @@ public class ArmorStand extends LivingEntity {
|
||||
this.setNoBasePlate(nbt.getBoolean("NoBasePlate"));
|
||||
this.setMarker(nbt.getBoolean("Marker"));
|
||||
this.noPhysics = !this.hasPhysics();
|
||||
+ // Paper start - Allow ArmorStands not to tick
|
||||
+ if (nbt.contains("Paper.CanTickOverride")) {
|
||||
+ this.canTick = nbt.getBoolean("Paper.CanTickOverride");
|
||||
+ this.canTickSetByAPI = true;
|
||||
+ }
|
||||
+ // Paper end - Allow ArmorStands not to tick
|
||||
CompoundTag nbttagcompound2 = nbt.getCompound("Pose");
|
||||
|
||||
this.readPose(nbttagcompound2);
|
||||
@@ -657,7 +672,29 @@ public class ArmorStand extends LivingEntity {
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
+ // Paper start - Allow ArmorStands not to tick
|
||||
+ if (!this.canTick) {
|
||||
+ if (this.noTickPoseDirty) {
|
||||
+ this.noTickPoseDirty = false;
|
||||
+ this.updatePose();
|
||||
+ }
|
||||
+
|
||||
+ if (this.noTickEquipmentDirty) {
|
||||
+ this.noTickEquipmentDirty = false;
|
||||
+ this.detectEquipmentUpdatesPublic();
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Allow ArmorStands not to tick
|
||||
+
|
||||
super.tick();
|
||||
+ // Paper start - Allow ArmorStands not to tick
|
||||
+ updatePose();
|
||||
+ }
|
||||
+
|
||||
+ public void updatePose() {
|
||||
+ // Paper end - Allow ArmorStands not to tick
|
||||
Rotations vector3f = (Rotations) this.entityData.get(ArmorStand.DATA_HEAD_POSE);
|
||||
|
||||
if (!this.headPose.equals(vector3f)) {
|
||||
@@ -786,31 +823,37 @@ public class ArmorStand extends LivingEntity {
|
||||
public void setHeadPose(Rotations angle) {
|
||||
this.headPose = angle;
|
||||
this.entityData.set(ArmorStand.DATA_HEAD_POSE, angle);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public void setBodyPose(Rotations angle) {
|
||||
this.bodyPose = angle;
|
||||
this.entityData.set(ArmorStand.DATA_BODY_POSE, angle);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public void setLeftArmPose(Rotations angle) {
|
||||
this.leftArmPose = angle;
|
||||
this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, angle);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public void setRightArmPose(Rotations angle) {
|
||||
this.rightArmPose = angle;
|
||||
this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, angle);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public void setLeftLegPose(Rotations angle) {
|
||||
this.leftLegPose = angle;
|
||||
this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, angle);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public void setRightLegPose(Rotations angle) {
|
||||
this.rightLegPose = angle;
|
||||
this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, angle);
|
||||
+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
|
||||
}
|
||||
|
||||
public Rotations getHeadPose() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
index 52ffc401bbb9fa768534a4b871f9cc7dbebb8b20..9923cea74ba39a774d6b16a225bc3e455e54c418 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
@@ -232,5 +232,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
|
||||
public void setCanMove(boolean move) {
|
||||
getHandle().canMove = move;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canTick() {
|
||||
+ return this.getHandle().canTick;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanTick(final boolean tick) {
|
||||
+ this.getHandle().canTick = tick;
|
||||
+ this.getHandle().canTickSetByAPI = true;
|
||||
+ }
|
||||
// Paper end
|
||||
}
|
87
patches/server/0226-SkeletonHorse-Additions.patch
Normal file
87
patches/server/0226-SkeletonHorse-Additions.patch
Normal file
|
@ -0,0 +1,87 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 27 Jul 2018 22:36:31 -0500
|
||||
Subject: [PATCH] SkeletonHorse Additions
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java
|
||||
index f3a02925833733ae50d706ffc681dd05344a7687..69714e0558419b1577c95cf8e75c1d67177ccb89 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java
|
||||
@@ -20,6 +20,7 @@ import net.minecraft.world.item.enchantment.ItemEnchantments;
|
||||
public class SkeletonTrapGoal extends Goal {
|
||||
|
||||
private final SkeletonHorse horse;
|
||||
+ private java.util.List<org.bukkit.entity.HumanEntity> eligiblePlayers; // Paper
|
||||
|
||||
public SkeletonTrapGoal(SkeletonHorse skeletonHorse) {
|
||||
this.horse = skeletonHorse;
|
||||
@@ -27,12 +28,13 @@ public class SkeletonTrapGoal extends Goal {
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
- return this.horse.level().hasNearbyAlivePlayerThatAffectsSpawning(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D); // Paper - Affects Spawning API
|
||||
+ return !(eligiblePlayers = this.horse.level().findNearbyBukkitPlayers(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D, net.minecraft.world.entity.EntitySelector.PLAYER_AFFECTS_SPAWNING)).isEmpty(); // Paper - Affects Spawning API & SkeletonHorseTrapEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
ServerLevel worldserver = (ServerLevel) this.horse.level();
|
||||
+ if (!new com.destroystokyo.paper.event.entity.SkeletonHorseTrapEvent((org.bukkit.entity.SkeletonHorse) this.horse.getBukkitEntity(), eligiblePlayers).callEvent()) return; // Paper
|
||||
DifficultyInstance difficultydamagescaler = worldserver.getCurrentDifficultyAt(this.horse.blockPosition());
|
||||
|
||||
this.horse.setTrap(false);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
|
||||
index 77ae7882a08441d9a80b50492be5e48487a2fdab..d465fb01af4c8610f83ecb9c68b83127cf7e95ae 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
|
||||
@@ -97,6 +97,28 @@ public interface EntityGetter {
|
||||
return player;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ default List<org.bukkit.entity.HumanEntity> findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) {
|
||||
+ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? EntitySelector.NO_SPECTATORS : net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR);
|
||||
+ }
|
||||
+
|
||||
+ default List<org.bukkit.entity.HumanEntity> findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate<Entity> predicate) {
|
||||
+ com.google.common.collect.ImmutableList.Builder<org.bukkit.entity.HumanEntity> builder = com.google.common.collect.ImmutableList.builder();
|
||||
+
|
||||
+ for (Player human : this.players()) {
|
||||
+ if (predicate == null || predicate.test(human)) {
|
||||
+ double distanceSquared = human.distanceToSqr(x, y, z);
|
||||
+
|
||||
+ if (radius < 0.0D || distanceSquared < radius * radius) {
|
||||
+ builder.add(human.getBukkitEntity());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return builder.build();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Nullable
|
||||
default Player getNearestPlayer(Entity entity, double maxDistance) {
|
||||
return this.getNearestPlayer(entity.getX(), entity.getY(), entity.getZ(), maxDistance, false);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java
|
||||
index 248e4febbe8fe225920b6504d2c29d295cf09ec6..fbb47491dcc75f8247dee9f123f946f99ef1467f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java
|
||||
@@ -44,4 +44,16 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo
|
||||
public void setTrapTime(int trapTime) {
|
||||
this.getHandle().trapTime = trapTime;
|
||||
}
|
||||
+
|
||||
+ // Paper start - replaced by above methods
|
||||
+ @Override
|
||||
+ public boolean isTrap() {
|
||||
+ return getHandle().isTrap();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTrap(boolean trap) {
|
||||
+ getHandle().setTrap(trap);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hugo Manrique <hugmanrique@gmail.com>
|
||||
Date: Thu, 26 Jul 2018 14:10:23 +0200
|
||||
Subject: [PATCH] Don't call getItemMeta on hasItemMeta
|
||||
|
||||
Spigot 1.13 checks if any field (which are manually copied from the ItemStack's "tag" NBT tag) on the ItemMeta class of an ItemStack is set.
|
||||
|
||||
We could just check if the "tag" NBT tag is empty, albeit that would break some plugins. The only general tag added on 1.13 is "Damage", and we can just check if the "tag" NBT tag contains any other tag that's not "Damage" (https://minecraft.wiki/wiki/Player.dat_format#Item_structure) making the `hasItemStack` method behave as before.
|
||||
|
||||
Returns true if getDamage() == 0 or has damage tag or other tag is set.
|
||||
Check the `ItemMetaTest#testTaggedButNotMeta` method to see how this method behaves.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
index a58e865a047550cc4508d0515cc6f2fc639f9b3d..13e6fc9f42d63fdbd659462070dc7f0767fbb1d9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
||||
@@ -681,7 +681,7 @@ public final class CraftItemStack extends ItemStack {
|
||||
|
||||
@Override
|
||||
public boolean hasItemMeta() {
|
||||
- return CraftItemStack.hasItemMeta(this.handle) && !CraftItemFactory.instance().equals(this.getItemMeta(), null);
|
||||
+ return CraftItemStack.hasItemMeta(this.handle) && (this.handle.getDamageValue() != 0 || (this.handle.getTag() != null && this.handle.getTag().tags.size() >= (this.handle.getTag().contains(CraftMetaItem.DAMAGE.NBT) ? 2 : 1))); // Paper - keep 1.12 CraftBukkit behavior without calling getItemMeta
|
||||
}
|
||||
|
||||
static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) {
|
||||
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
|
||||
index cf436c9e62a11b8c6cbf7638de0e5635c67459ac..7237e24686885c754c87e7eec53c6400fd0b47bf 100644
|
||||
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
|
||||
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
|
||||
@@ -106,6 +106,34 @@ public class ItemMetaTest extends AbstractTestingBase {
|
||||
assertThat(itemMeta.hasConflictingEnchant(null), is(false));
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private void testItemMeta(ItemStack stack) {
|
||||
+ assertThat(stack.hasItemMeta(), is(false), "Should not have ItemMeta");
|
||||
+
|
||||
+ stack.setDurability((short) 0);
|
||||
+ assertThat(stack.hasItemMeta(), is(false), "ItemStack with zero durability should not have ItemMeta");
|
||||
+
|
||||
+ stack.setDurability((short) 2);
|
||||
+ assertThat(stack.hasItemMeta(), is(true), "ItemStack with non-zero durability should have ItemMeta");
|
||||
+
|
||||
+ stack.setLore(java.util.Collections.singletonList("Lore"));
|
||||
+ assertThat(stack.hasItemMeta(), is(true), "ItemStack with lore and durability should have ItemMeta");
|
||||
+
|
||||
+ stack.setDurability((short) 0);
|
||||
+ assertThat(stack.hasItemMeta(), is(true), "ItemStack with lore should have ItemMeta");
|
||||
+
|
||||
+ stack.setLore(null);
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testHasItemMeta() {
|
||||
+ ItemStack itemStack = new ItemStack(Material.SHEARS);
|
||||
+
|
||||
+ testItemMeta(itemStack);
|
||||
+ testItemMeta(CraftItemStack.asCraftCopy(itemStack));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Test
|
||||
public void testConflictingStoredEnchantment() {
|
||||
EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) Bukkit.getItemFactory().getItemMeta(Material.ENCHANTED_BOOK);
|
167
patches/server/0228-Expand-ArmorStand-API.patch
Normal file
167
patches/server/0228-Expand-ArmorStand-API.patch
Normal file
|
@ -0,0 +1,167 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: willies952002 <admin@domnian.com>
|
||||
Date: Thu, 26 Jul 2018 02:25:46 -0400
|
||||
Subject: [PATCH] Expand ArmorStand API
|
||||
|
||||
Adds the following:
|
||||
- Add proper methods for getting and setting items in both hands. Deprecates old methods
|
||||
- Enable/Disable slot interactions
|
||||
- Allow using degrees for ArmorStand rotations (via new Rotations class)
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.decoration.ArmorStand isDisabled(Lnet/minecraft/world/entity/EquipmentSlot;)Z
|
||||
|
||||
Co-authored-by: SoSeDiK <mrsosedik@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
index 9923cea74ba39a774d6b16a225bc3e455e54c418..2c16cedf8cb2e4047415e056c419ed9c33c80e93 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
|
||||
@@ -233,6 +233,147 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
|
||||
getHandle().canMove = move;
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) {
|
||||
+ com.google.common.base.Preconditions.checkNotNull(slot, "slot");
|
||||
+ return getHandle().getItemBySlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)).asBukkitMirror();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack item) {
|
||||
+ com.google.common.base.Preconditions.checkNotNull(slot, "slot");
|
||||
+ switch (slot) {
|
||||
+ case HAND:
|
||||
+ getEquipment().setItemInMainHand(item);
|
||||
+ return;
|
||||
+ case OFF_HAND:
|
||||
+ getEquipment().setItemInOffHand(item);
|
||||
+ return;
|
||||
+ case FEET:
|
||||
+ setBoots(item);
|
||||
+ return;
|
||||
+ case LEGS:
|
||||
+ setLeggings(item);
|
||||
+ return;
|
||||
+ case CHEST:
|
||||
+ setChestplate(item);
|
||||
+ return;
|
||||
+ case HEAD:
|
||||
+ setHelmet(item);
|
||||
+ return;
|
||||
+ }
|
||||
+ throw new UnsupportedOperationException(slot.name());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.Set<org.bukkit.inventory.EquipmentSlot> getDisabledSlots() {
|
||||
+ java.util.Set<org.bukkit.inventory.EquipmentSlot> disabled = new java.util.HashSet<>();
|
||||
+ for (org.bukkit.inventory.EquipmentSlot slot : org.bukkit.inventory.EquipmentSlot.values()) {
|
||||
+ if (this.isSlotDisabled(slot)) {
|
||||
+ disabled.add(slot);
|
||||
+ }
|
||||
+ }
|
||||
+ return disabled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) {
|
||||
+ int disabled = 0;
|
||||
+ for (org.bukkit.inventory.EquipmentSlot slot : slots) {
|
||||
+ if (slot == org.bukkit.inventory.EquipmentSlot.OFF_HAND) continue;
|
||||
+ net.minecraft.world.entity.EquipmentSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot);
|
||||
+ disabled += (1 << nmsSlot.getFilterFlag()) + (1 << (nmsSlot.getFilterFlag() + 8)) + (1 << (nmsSlot.getFilterFlag() + 16));
|
||||
+ }
|
||||
+ getHandle().disabledSlots = disabled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void addDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) {
|
||||
+ java.util.Set<org.bukkit.inventory.EquipmentSlot> disabled = getDisabledSlots();
|
||||
+ java.util.Collections.addAll(disabled, slots);
|
||||
+ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0]));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void removeDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) {
|
||||
+ java.util.Set<org.bukkit.inventory.EquipmentSlot> disabled = getDisabledSlots();
|
||||
+ for (final org.bukkit.inventory.EquipmentSlot slot : slots) disabled.remove(slot);
|
||||
+ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0]));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) {
|
||||
+ return getHandle().isDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public io.papermc.paper.math.Rotations getBodyRotations() {
|
||||
+ return fromNMSRotations(getHandle().bodyPose);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setBodyRotations(io.papermc.paper.math.Rotations rotations) {
|
||||
+ getHandle().setBodyPose(toNMSRotations(rotations));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public io.papermc.paper.math.Rotations getLeftArmRotations() {
|
||||
+ return fromNMSRotations(getHandle().leftArmPose);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLeftArmRotations(io.papermc.paper.math.Rotations rotations) {
|
||||
+ getHandle().setLeftArmPose(toNMSRotations(rotations));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public io.papermc.paper.math.Rotations getRightArmRotations() {
|
||||
+ return fromNMSRotations(getHandle().rightArmPose);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setRightArmRotations(io.papermc.paper.math.Rotations rotations) {
|
||||
+ getHandle().setRightArmPose(toNMSRotations(rotations));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public io.papermc.paper.math.Rotations getLeftLegRotations() {
|
||||
+ return fromNMSRotations(getHandle().leftLegPose);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setLeftLegRotations(io.papermc.paper.math.Rotations rotations) {
|
||||
+ getHandle().setLeftLegPose(toNMSRotations(rotations));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public io.papermc.paper.math.Rotations getRightLegRotations() {
|
||||
+ return fromNMSRotations(getHandle().rightLegPose);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setRightLegRotations(io.papermc.paper.math.Rotations rotations) {
|
||||
+ getHandle().setRightLegPose(toNMSRotations(rotations));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public io.papermc.paper.math.Rotations getHeadRotations() {
|
||||
+ return fromNMSRotations(getHandle().headPose);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setHeadRotations(io.papermc.paper.math.Rotations rotations) {
|
||||
+ getHandle().setHeadPose(toNMSRotations(rotations));
|
||||
+ }
|
||||
+
|
||||
+ private static io.papermc.paper.math.Rotations fromNMSRotations(Rotations old) {
|
||||
+ return io.papermc.paper.math.Rotations.ofDegrees(old.getX(), old.getY(), old.getZ());
|
||||
+ }
|
||||
+
|
||||
+ private static Rotations toNMSRotations(io.papermc.paper.math.Rotations old) {
|
||||
+ return new Rotations((float) old.x(), (float) old.y(), (float) old.z());
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public boolean canTick() {
|
||||
return this.getHandle().canTick;
|
27
patches/server/0229-AnvilDamageEvent.patch
Normal file
27
patches/server/0229-AnvilDamageEvent.patch
Normal file
|
@ -0,0 +1,27 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 20 Jul 2018 23:37:03 -0500
|
||||
Subject: [PATCH] AnvilDamageEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
|
||||
index 37cc70f46d85cef1d678ab9df4fb1a73a57ed877..4c766b879f935298ffa4249e9ce4045601cedb20 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
|
||||
@@ -110,6 +110,16 @@ public class AnvilMenu extends ItemCombinerMenu {
|
||||
if (!player.hasInfiniteMaterials() && iblockdata.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) {
|
||||
BlockState iblockdata1 = AnvilBlock.damage(iblockdata);
|
||||
|
||||
+ // Paper start - AnvilDamageEvent
|
||||
+ com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), iblockdata1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(iblockdata1) : null);
|
||||
+ if (!event.callEvent()) {
|
||||
+ return;
|
||||
+ } else if (event.getDamageState() == com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.BROKEN) {
|
||||
+ iblockdata1 = null;
|
||||
+ } else {
|
||||
+ iblockdata1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().setValue(AnvilBlock.FACING, iblockdata.getValue(AnvilBlock.FACING));
|
||||
+ }
|
||||
+ // Paper end - AnvilDamageEvent
|
||||
if (iblockdata1 == null) {
|
||||
world.removeBlock(blockposition, false);
|
||||
world.levelEvent(1029, blockposition, 0);
|
117
patches/server/0230-Add-TNTPrimeEvent.patch
Normal file
117
patches/server/0230-Add-TNTPrimeEvent.patch
Normal file
|
@ -0,0 +1,117 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
|
||||
Date: Mon, 16 Jul 2018 00:05:05 +0300
|
||||
Subject: [PATCH] Add TNTPrimeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
index 3e2f83e2c695b024bdec2c5e11ab38596730ed4a..789823dbaaf2e23942749145dbb64071539624aa 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
@@ -557,6 +557,11 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
});
|
||||
craftBlock.getNMS().spawnAfterBreak((ServerLevel) this.level(), blockposition, ItemStack.EMPTY, false);
|
||||
}
|
||||
+ // Paper start - TNTPrimeEvent
|
||||
+ org.bukkit.block.Block tntBlock = CraftBlock.at(this.level(), blockposition);
|
||||
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getIndirectSourceEntity().getBukkitEntity()).callEvent())
|
||||
+ continue;
|
||||
+ // Paper end - TNTPrimeEvent
|
||||
nmsBlock.wasExploded(this.level(), blockposition, this.explosionSource);
|
||||
|
||||
this.level().removeBlock(blockposition, false);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java
|
||||
index c7c4b04dede992991229b149b96ff6a81f499ae3..886b8d2284e3ae85184c842b24869029b9ee4ebe 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java
|
||||
@@ -302,12 +302,19 @@ public class FireBlock extends BaseFireBlock {
|
||||
|
||||
world.setBlock(blockposition, this.getStateWithAge(world, blockposition, l), 3);
|
||||
} else {
|
||||
- world.removeBlock(blockposition, false);
|
||||
+ if(iblockdata.getBlock() != Blocks.TNT) world.removeBlock(blockposition, false); // Paper - TNTPrimeEvent; We might be cancelling it below, move the setAir down
|
||||
}
|
||||
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
if (block instanceof TntBlock) {
|
||||
+ // Paper start - TNTPrimeEvent
|
||||
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition);
|
||||
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ world.removeBlock(blockposition, false);
|
||||
+ // Paper end - TNTPrimeEvent
|
||||
TntBlock.explode(world, blockposition);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/TntBlock.java b/src/main/java/net/minecraft/world/level/block/TntBlock.java
|
||||
index 21b83d4d5b58da22ba1fadb0ca376a0076f2e23c..58b8c3cc579a1d34af26c44d6a7413bd5cc9e4e7 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/TntBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/TntBlock.java
|
||||
@@ -50,6 +50,12 @@ public class TntBlock extends Block {
|
||||
protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
|
||||
if (!oldState.is(state.getBlock())) {
|
||||
if (world.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(world, pos, PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent
|
||||
+ // Paper start - TNTPrimeEvent
|
||||
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
|
||||
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - TNTPrimeEvent
|
||||
TntBlock.explode(world, pos);
|
||||
world.removeBlock(pos, false);
|
||||
}
|
||||
@@ -60,6 +66,12 @@ public class TntBlock extends Block {
|
||||
@Override
|
||||
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
|
||||
if (world.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(world, pos, PrimeCause.REDSTONE, null, sourcePos)) { // CraftBukkit - TNTPrimeEvent
|
||||
+ // Paper start - TNTPrimeEvent
|
||||
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
|
||||
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - TNTPrimeEvent
|
||||
TntBlock.explode(world, pos);
|
||||
world.removeBlock(pos, false);
|
||||
}
|
||||
@@ -78,6 +90,13 @@ public class TntBlock extends Block {
|
||||
@Override
|
||||
public void wasExploded(Level world, BlockPos pos, Explosion explosion) {
|
||||
if (!world.isClientSide) {
|
||||
+ // Paper start - TNTPrimeEvent
|
||||
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
|
||||
+ org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null;
|
||||
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - TNTPrimeEvent
|
||||
PrimedTnt entitytntprimed = new PrimedTnt(world, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, explosion.getIndirectSourceEntity());
|
||||
int i = entitytntprimed.getFuse();
|
||||
|
||||
@@ -110,6 +129,12 @@ public class TntBlock extends Block {
|
||||
return ItemInteractionResult.CONSUME;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - TNTPrimeEvent
|
||||
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
|
||||
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.ITEM, player.getBukkitEntity()).callEvent()) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ // Paper end - TNTPrimeEvent
|
||||
TntBlock.explode(world, pos, player);
|
||||
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11);
|
||||
Item item = stack.getItem();
|
||||
@@ -139,6 +164,12 @@ public class TntBlock extends Block {
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - TNTPrimeEvent
|
||||
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition);
|
||||
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.PROJECTILE, projectile.getBukkitEntity()).callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - TNTPrimeEvent
|
||||
TntBlock.explode(world, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null);
|
||||
world.removeBlock(blockposition, false);
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 29 Jul 2018 05:02:15 +0100
|
||||
Subject: [PATCH] Break up and make tab spam limits configurable
|
||||
|
||||
Due to the changes in 1.13, clients will send a tab completion request
|
||||
for all bukkit commands in order to factor in the lack of support for
|
||||
brigadier and provide backwards support in the API.
|
||||
|
||||
Craftbukkit, however; has moved the chat spam limiter to also interact
|
||||
with the tab completion request, which while good for avoiding abuse,
|
||||
causes 1.13 clients to easilly be kicked from a server in bukkit due
|
||||
to this. Removing the spam limit could cause issues for servers, however,
|
||||
there is no way for servers to manipulate this without blindly cancelling
|
||||
kick events, which only causes additional complications. This also causes
|
||||
issues in that the tab spam limit and chat share the same field but different
|
||||
limits, meaning that a player having typed a long command may be kicked from
|
||||
the server.
|
||||
|
||||
Splitting the field up and making it configurable allows for server owners
|
||||
to take the burden of this into their own hand without having to rely on
|
||||
plugins doing unsafe things.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index b9fb2472405c19afb9888720a9abd86687e9bf12..f49f412781a8f341eda02de323f7298d5f0b25ee 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -266,6 +266,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
private int ackBlockChangesUpTo = -1;
|
||||
// CraftBukkit start - multithreaded fields
|
||||
private final AtomicInteger chatSpamTickCount = new AtomicInteger();
|
||||
+ private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits
|
||||
// CraftBukkit end
|
||||
private int dropSpamTickCount;
|
||||
private double firstGoodX;
|
||||
@@ -387,6 +388,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
this.keepConnectionAlive();
|
||||
// CraftBukkit start
|
||||
for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !this.chatSpamTickCount.compareAndSet(spam, spam - 1); ) ;
|
||||
+ if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - configurable tab spam limits
|
||||
/* Use thread-safe field access instead
|
||||
if (this.chatSpamTickCount > 0) {
|
||||
--this.chatSpamTickCount;
|
||||
@@ -722,7 +724,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) {
|
||||
// PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async
|
||||
// CraftBukkit start
|
||||
- if (this.chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
|
||||
+ if (this.chatSpamTickCount.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper - configurable tab spam limits
|
||||
this.disconnect(Component.translatable("disconnect.spam"));
|
||||
return;
|
||||
}
|
44
patches/server/0232-Fix-NBT-type-issues.patch
Normal file
44
patches/server/0232-Fix-NBT-type-issues.patch
Normal file
|
@ -0,0 +1,44 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 3 Aug 2018 00:04:54 -0400
|
||||
Subject: [PATCH] Fix NBT type issues
|
||||
|
||||
Addresses two issues:
|
||||
- MC-135506: Experience should save as Integers
|
||||
- Allay duplication cooldown is saved and exposed as a long, but loaded as an int
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
index 105b07cb8efd6a4304c4cf6650affa46a7852941..adc3e6298a1946fdea029c82a9954fb5b6e24497 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
|
||||
@@ -302,7 +302,7 @@ public class ExperienceOrb extends Entity {
|
||||
public void addAdditionalSaveData(CompoundTag nbt) {
|
||||
nbt.putShort("Health", (short) this.health);
|
||||
nbt.putShort("Age", (short) this.age);
|
||||
- nbt.putShort("Value", (short) this.value);
|
||||
+ nbt.putInt("Value", this.value); // Paper - save as Integer
|
||||
nbt.putInt("Count", this.count);
|
||||
this.savePaperNBT(nbt); // Paper
|
||||
}
|
||||
@@ -311,7 +311,7 @@ public class ExperienceOrb extends Entity {
|
||||
public void readAdditionalSaveData(CompoundTag nbt) {
|
||||
this.health = nbt.getShort("Health");
|
||||
this.age = nbt.getShort("Age");
|
||||
- this.value = nbt.getShort("Value");
|
||||
+ this.value = nbt.getInt("Value"); // Paper - load as Integer
|
||||
this.count = Math.max(nbt.getInt("Count"), 1);
|
||||
this.loadPaperNBT(nbt); // Paper
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
|
||||
index 296a25deae065425ef9384b7ec15d5aeb76dbd66..991e3274091c4e25eebc6debd44653e5b566eedb 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
|
||||
@@ -487,7 +487,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS
|
||||
});
|
||||
}
|
||||
|
||||
- this.duplicationCooldown = (long) nbt.getInt("DuplicationCooldown");
|
||||
+ this.duplicationCooldown = nbt.getLong("DuplicationCooldown"); // Paper - Load as long
|
||||
this.entityData.set(Allay.DATA_CAN_DUPLICATE, nbt.getBoolean("CanDuplicate"));
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 22 Nov 2016 00:40:42 -0500
|
||||
Subject: [PATCH] Remove unnecessary itemmeta handling
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
index 2535cbf50087a4631c4d1027a61b173121d729bc..6f1ff953e6311ff859d3ddc5734d33146237992b 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -168,7 +168,7 @@ public final class ItemStack implements DataComponentHolder {
|
||||
|
||||
// CraftBukkit start
|
||||
ItemStack itemstack = new ItemStack(holder, i, datacomponentpatch);
|
||||
- if (!datacomponentpatch.isEmpty()) {
|
||||
+ if (false && !datacomponentpatch.isEmpty()) { // Paper - This is no longer needed with raw NBT being handled in metadata
|
||||
CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack));
|
||||
}
|
||||
return itemstack;
|
||||
@@ -183,7 +183,7 @@ public final class ItemStack implements DataComponentHolder {
|
||||
registryfriendlybytebuf.writeVarInt(itemstack.getCount());
|
||||
// Spigot start - filter
|
||||
itemstack = itemstack.copy();
|
||||
- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack));
|
||||
+ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer with raw NBT being handled in metadata
|
||||
// Spigot end
|
||||
ITEM_STREAM_CODEC.encode(registryfriendlybytebuf, itemstack.getItemHolder()); // CraftBukkit - decompile error
|
||||
DataComponentPatch.STREAM_CODEC.encode(registryfriendlybytebuf, itemstack.components.asPatch());
|
|
@ -0,0 +1,75 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 21 Jul 2018 08:25:40 -0400
|
||||
Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 46da628073e2bfb77b3deab623dba46228d92618..1c508d1f122d287cd8dc0a905de96436c343327a 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1441,6 +1441,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
} else {
|
||||
ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas());
|
||||
|
||||
+ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker
|
||||
this.entityMap.put(entity.getId(), playerchunkmap_entitytracker);
|
||||
playerchunkmap_entitytracker.updatePlayers(this.level.players());
|
||||
if (entity instanceof ServerPlayer) {
|
||||
@@ -1481,7 +1482,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
if (playerchunkmap_entitytracker1 != null) {
|
||||
playerchunkmap_entitytracker1.broadcastRemoved();
|
||||
}
|
||||
-
|
||||
+ entity.tracker = null; // Paper - We're no longer tracked
|
||||
}
|
||||
|
||||
protected void tick() {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 75213d34740e512763a8eb4411ef2b48c6204434..ce89f04b74e579dedae05cfdf681827a92626f9a 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1203,6 +1203,12 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
// CraftBukkit start
|
||||
private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
|
||||
+ // Paper start - extra debug info
|
||||
+ if (entity.valid) {
|
||||
+ MinecraftServer.LOGGER.error("Attempted Double World add on {}", entity, new Throwable());
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - extra debug info
|
||||
if (entity.isRemoved()) {
|
||||
// WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit
|
||||
return false;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index c2dd3767fbeb7215c9b2703054c9068252828355..d39aec1b3233e91aa5b953396d876e7466a9a5bc 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -245,6 +245,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper
|
||||
private CraftEntity bukkitEntity;
|
||||
|
||||
+ public @org.jetbrains.annotations.Nullable net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper
|
||||
public CraftEntity getBukkitEntity() {
|
||||
if (this.bukkitEntity == null) {
|
||||
this.bukkitEntity = CraftEntity.getEntity(this.level.getCraftServer(), this);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
|
||||
index 38df704dca30ef08f4d0831dc1cc48c6d6f71a4d..ed6aea7a38ef6e80c300ff9b012dcdbc390ad2c7 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
|
||||
@@ -33,6 +33,14 @@ public class EntityLookup<T extends EntityAccess> {
|
||||
UUID uUID = entity.getUUID();
|
||||
if (this.byUuid.containsKey(uUID)) {
|
||||
LOGGER.warn("Duplicate entity UUID {}: {}", uUID, entity);
|
||||
+ // Paper start - extra debug info
|
||||
+ if (entity instanceof net.minecraft.world.entity.Entity) {
|
||||
+ final T old = this.byUuid.get(entity.getUUID());
|
||||
+ if (old instanceof net.minecraft.world.entity.Entity oldCast && oldCast.getId() != entity.getId() && oldCast.valid) {
|
||||
+ LOGGER.error("Overwrote an existing entity {} with {}", oldCast, entity);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - extra debug info
|
||||
} else {
|
||||
this.byUuid.put(uUID, entity);
|
||||
this.byId.put(entity.getId(), entity);
|
159
patches/server/0235-Add-Early-Warning-Feature-to-WatchDog.patch
Normal file
159
patches/server/0235-Add-Early-Warning-Feature-to-WatchDog.patch
Normal file
|
@ -0,0 +1,159 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: miclebrick <miclebrick@outlook.com>
|
||||
Date: Wed, 8 Aug 2018 15:30:52 -0400
|
||||
Subject: [PATCH] Add Early Warning Feature to WatchDog
|
||||
|
||||
Detect when the server has been hung for a long duration, and start printing
|
||||
thread dumps at an interval until the point of crash.
|
||||
|
||||
This will help diagnose what was going on in that time before the crash.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 875591131576cb3760193651fac22698e1eb9099..23a5358a5fe4784e75b327741e6fcb174c04d287 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1104,6 +1104,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.status = this.buildServerStatus();
|
||||
|
||||
// Spigot start
|
||||
+ org.spigotmc.WatchdogThread.hasStarted = true; // Paper
|
||||
Arrays.fill( this.recentTps, 20 );
|
||||
// Paper start - further improve server tick loop
|
||||
long tickSection = Util.getNanos();
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 0ffa25a6e41cc56e78c79e0cee45e3b811794129..1b47e228ad7365b31d6ddd8c572d3bc5de90a591 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -212,6 +212,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
this.paperConfigurations.initializeGlobalConfiguration(this.registryAccess());
|
||||
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
|
||||
// Paper end - initialize global and world-defaults configuration
|
||||
+ org.spigotmc.WatchdogThread.doStart(org.spigotmc.SpigotConfig.timeoutTime, org.spigotmc.SpigotConfig.restartOnCrash); // Paper - start watchdog thread
|
||||
io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command
|
||||
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics
|
||||
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 9d65bce391b00b78efed1e40a01fa2865c05e6fd..af9140513970fc5c3797a170eab02de40048543c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -927,6 +927,7 @@ public final class CraftServer implements Server {
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
+ org.spigotmc.WatchdogThread.hasStarted = false; // Paper - Disable watchdog early timeout on reload
|
||||
this.reloadCount++;
|
||||
this.configuration = YamlConfiguration.loadConfiguration(this.getConfigFile());
|
||||
this.commandsConfiguration = YamlConfiguration.loadConfiguration(this.getCommandsConfigFile());
|
||||
@@ -1017,6 +1018,7 @@ public final class CraftServer implements Server {
|
||||
this.enablePlugins(PluginLoadOrder.POSTWORLD);
|
||||
this.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.RELOAD));
|
||||
if (io.papermc.paper.plugin.PluginInitializerManager.instance().pluginRemapper != null) io.papermc.paper.plugin.PluginInitializerManager.instance().pluginRemapper.pluginsEnabled(); // Paper - Remap plugins
|
||||
+ org.spigotmc.WatchdogThread.hasStarted = true; // Paper - Disable watchdog early timeout on reload
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
index 7cd1f375b9ad9e6d6f2d26661519f12be064a9d2..9572177323f29ea8315a3dfb943dfe10463f32ae 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
@@ -229,7 +229,7 @@ public class SpigotConfig
|
||||
SpigotConfig.restartScript = SpigotConfig.getString( "settings.restart-script", SpigotConfig.restartScript );
|
||||
SpigotConfig.restartMessage = SpigotConfig.transform( SpigotConfig.getString( "messages.restart", "Server is restarting" ) );
|
||||
SpigotConfig.commands.put( "restart", new RestartCommand( "restart" ) );
|
||||
- WatchdogThread.doStart( SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash );
|
||||
+ // WatchdogThread.doStart( SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); // Paper - moved to after paper config initialization
|
||||
}
|
||||
|
||||
public static boolean bungee;
|
||||
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
index 81ccbe2533e6fc5899d6c068e421e0d7f1351d34..ad282d34919716b75acd10426cd071da9d064a51 100644
|
||||
--- a/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
@@ -14,6 +14,10 @@ public class WatchdogThread extends Thread
|
||||
private static WatchdogThread instance;
|
||||
private long timeoutTime;
|
||||
private boolean restart;
|
||||
+ private final long earlyWarningEvery; // Paper - Timeout time for just printing a dump but not restarting
|
||||
+ private final long earlyWarningDelay; // Paper
|
||||
+ public static volatile boolean hasStarted; // Paper
|
||||
+ private long lastEarlyWarning; // Paper - Keep track of short dump times to avoid spamming console with short dumps
|
||||
private volatile long lastTick;
|
||||
private volatile boolean stopping;
|
||||
|
||||
@@ -22,6 +26,8 @@ public class WatchdogThread extends Thread
|
||||
super( "Paper Watchdog Thread" );
|
||||
this.timeoutTime = timeoutTime;
|
||||
this.restart = restart;
|
||||
+ earlyWarningEvery = Math.min(io.papermc.paper.configuration.GlobalConfiguration.get().watchdog.earlyWarningEvery, timeoutTime); // Paper
|
||||
+ earlyWarningDelay = Math.min(io.papermc.paper.configuration.GlobalConfiguration.get().watchdog.earlyWarningDelay, timeoutTime); // Paper
|
||||
}
|
||||
|
||||
private static long monotonicMillis()
|
||||
@@ -61,9 +67,18 @@ public class WatchdogThread extends Thread
|
||||
while ( !this.stopping )
|
||||
{
|
||||
//
|
||||
- if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.monotonicMillis() > this.lastTick + this.timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable
|
||||
+ // Paper start
|
||||
+ Logger log = Bukkit.getServer().getLogger();
|
||||
+ long currentTime = WatchdogThread.monotonicMillis();
|
||||
+ if ( this.lastTick != 0 && this.timeoutTime > 0 && currentTime > this.lastTick + this.earlyWarningEvery && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable
|
||||
{
|
||||
- Logger log = Bukkit.getServer().getLogger();
|
||||
+ boolean isLongTimeout = currentTime > lastTick + timeoutTime;
|
||||
+ // Don't spam early warning dumps
|
||||
+ if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue;
|
||||
+ if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this...
|
||||
+ lastEarlyWarning = currentTime;
|
||||
+ if (isLongTimeout) {
|
||||
+ // Paper end
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper
|
||||
log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" );
|
||||
@@ -92,29 +107,45 @@ public class WatchdogThread extends Thread
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
+ } else
|
||||
+ {
|
||||
+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---");
|
||||
+ log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump");
|
||||
+ }
|
||||
+ // Paper end - Different message for short timeout
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
|
||||
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
//
|
||||
+ // Paper start - Only print full dump on long timeouts
|
||||
+ if ( isLongTimeout )
|
||||
+ {
|
||||
log.log( Level.SEVERE, "Entire Thread Dump:" );
|
||||
ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true );
|
||||
for ( ThreadInfo thread : threads )
|
||||
{
|
||||
WatchdogThread.dumpThread( thread, log );
|
||||
}
|
||||
+ } else {
|
||||
+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---");
|
||||
+ }
|
||||
+
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
|
||||
+ if ( isLongTimeout )
|
||||
+ {
|
||||
if ( this.restart && !MinecraftServer.getServer().hasStopped() )
|
||||
{
|
||||
RestartCommand.restart();
|
||||
}
|
||||
break;
|
||||
+ } // Paper end
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
- sleep( 10000 );
|
||||
+ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout
|
||||
} catch ( InterruptedException ex )
|
||||
{
|
||||
this.interrupt();
|
108
patches/server/0236-Use-ConcurrentHashMap-in-JsonList.patch
Normal file
108
patches/server/0236-Use-ConcurrentHashMap-in-JsonList.patch
Normal file
|
@ -0,0 +1,108 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: egg82 <phantom_zero@ymail.com>
|
||||
Date: Tue, 7 Aug 2018 01:24:23 -0600
|
||||
Subject: [PATCH] Use ConcurrentHashMap in JsonList
|
||||
|
||||
This is specifically aimed at fixing #471
|
||||
|
||||
Using a ConcurrentHashMap because thread safety
|
||||
The performance benefit of Map over ConcurrentMap is negligabe at best in this scenaio, as most operations will be get and not add or remove
|
||||
Even without considering the use-case the benefits are still negligable
|
||||
|
||||
Original ideas for the system included an expiration policy and/or handler
|
||||
The simpler solution was to use a computeIfPresent in the get method
|
||||
This will simultaneously have an O(1) lookup time and automatically expire any values
|
||||
Since the get method (nor other similar methods) don't seem to have a critical need to flush the map to disk at any of these points further processing is simply wasteful
|
||||
Meaning the original function expired values unrelated to the current value without actually having any explicit need to
|
||||
|
||||
The h method was heavily modified to be much more efficient in its processing
|
||||
Also instead of being called on every get, it's now called just before a save
|
||||
This will eliminate stale values being flushed to disk
|
||||
|
||||
Modified isEmpty to use the isEmpty() method instead of the slightly confusing size() < 1
|
||||
The point of this is readability, but does have a side-benefit of a small microptimization
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 43fc4e945c6a3cd94522d667055ab3dd80f961f6..4dea09aa0f5f45d449ba12d8a9db3e0a3b708757 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -634,7 +634,7 @@ public abstract class PlayerList {
|
||||
} else if (!this.isWhiteListed(gameprofile, event)) { // Paper - ProfileWhitelistVerifyEvent
|
||||
//ichatmutablecomponent = Component.translatable("multiplayer.disconnect.not_whitelisted"); // Paper
|
||||
//event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure - moved to isWhitelisted
|
||||
- } else if (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) {
|
||||
+ } else if (this.getIpBans().isBanned(socketaddress) && getIpBans().get(socketaddress) != null && !this.getIpBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans
|
||||
IpBanListEntry ipbanentry = this.ipBans.get(socketaddress);
|
||||
|
||||
ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason());
|
||||
diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java
|
||||
index 7e81907bfdca225413e8191e37969990e6f4cf2c..c038da20b76c0b7b1c18471b20be01e849d29f3a 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/StoredUserList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/StoredUserList.java
|
||||
@@ -30,7 +30,7 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
|
||||
private final File file;
|
||||
- private final Map<String, V> map = Maps.newHashMap();
|
||||
+ private final Map<String, V> map = Maps.newConcurrentMap(); // Paper - Use ConcurrentHashMap in JsonList
|
||||
|
||||
public StoredUserList(File file) {
|
||||
this.file = file;
|
||||
@@ -53,8 +53,11 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> {
|
||||
|
||||
@Nullable
|
||||
public V get(K key) {
|
||||
- this.removeExpired();
|
||||
- return (V) this.map.get(this.getKeyForUser(key)); // CraftBukkit - fix decompile error
|
||||
+ // Paper start - Use ConcurrentHashMap in JsonList
|
||||
+ return (V) this.map.computeIfPresent(this.getKeyForUser(key), (k, v) -> {
|
||||
+ return v.hasExpired() ? null : v;
|
||||
+ });
|
||||
+ // Paper end - Use ConcurrentHashMap in JsonList
|
||||
}
|
||||
|
||||
public void remove(K key) {
|
||||
@@ -77,7 +80,7 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> {
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
- return this.map.size() < 1;
|
||||
+ return this.map.isEmpty(); // Paper - Use ConcurrentHashMap in JsonList
|
||||
}
|
||||
|
||||
protected String getKeyForUser(K profile) {
|
||||
@@ -90,25 +93,7 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> {
|
||||
}
|
||||
|
||||
private void removeExpired() {
|
||||
- List<K> list = Lists.newArrayList();
|
||||
- Iterator iterator = this.map.values().iterator();
|
||||
-
|
||||
- while (iterator.hasNext()) {
|
||||
- V v0 = (V) iterator.next(); // CraftBukkit - decompile error
|
||||
-
|
||||
- if (v0.hasExpired()) {
|
||||
- list.add(v0.getUser());
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- iterator = list.iterator();
|
||||
-
|
||||
- while (iterator.hasNext()) {
|
||||
- K k0 = (K) iterator.next(); // CraftBukkit - decompile error
|
||||
-
|
||||
- this.map.remove(this.getKeyForUser(k0));
|
||||
- }
|
||||
-
|
||||
+ this.map.values().removeIf(StoredUserEntry::hasExpired); // Paper - Use ConcurrentHashMap in JsonList
|
||||
}
|
||||
|
||||
protected abstract StoredUserEntry<K> createEntry(JsonObject json);
|
||||
@@ -118,6 +103,7 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> {
|
||||
}
|
||||
|
||||
public void save() throws IOException {
|
||||
+ this.removeExpired(); // Paper - remove expired values before saving
|
||||
JsonArray jsonarray = new JsonArray();
|
||||
Stream<JsonObject> stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error
|
||||
JsonObject jsonobject = new JsonObject();
|
39
patches/server/0237-Use-a-Queue-for-Queueing-Commands.patch
Normal file
39
patches/server/0237-Use-a-Queue-for-Queueing-Commands.patch
Normal file
|
@ -0,0 +1,39 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 12 Aug 2018 02:33:39 -0400
|
||||
Subject: [PATCH] Use a Queue for Queueing Commands
|
||||
|
||||
Lists are bad as Queues mmmkay.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 1b47e228ad7365b31d6ddd8c572d3bc5de90a591..bce5fc7337d4e29c3353600a35c999caaed1428e 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -76,7 +76,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final int CONVERSION_RETRY_DELAY_MS = 5000;
|
||||
private static final int CONVERSION_RETRIES = 2;
|
||||
- private final List<ConsoleInput> consoleInput = Collections.synchronizedList(Lists.newArrayList());
|
||||
+ private final java.util.Queue<ConsoleInput> serverCommandQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - Perf: use a proper queue
|
||||
@Nullable
|
||||
private QueryThreadGs4 queryThreadGs4;
|
||||
// private final RemoteControlCommandListener rconConsoleSource; // CraftBukkit - remove field
|
||||
@@ -434,13 +434,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
}
|
||||
|
||||
public void handleConsoleInput(String command, CommandSourceStack commandSource) {
|
||||
- this.consoleInput.add(new ConsoleInput(command, commandSource));
|
||||
+ this.serverCommandQueue.add(new ConsoleInput(command, commandSource)); // Paper - Perf: use proper queue
|
||||
}
|
||||
|
||||
public void handleConsoleInputs() {
|
||||
MinecraftTimings.serverCommandTimer.startTiming(); // Spigot
|
||||
- while (!this.consoleInput.isEmpty()) {
|
||||
- ConsoleInput servercommand = (ConsoleInput) this.consoleInput.remove(0);
|
||||
+ // Paper start - Perf: use proper queue
|
||||
+ ConsoleInput servercommand;
|
||||
+ while ((servercommand = this.serverCommandQueue.poll()) != null) {
|
||||
+ // Paper end - Perf: use proper queue
|
||||
|
||||
// CraftBukkit start - ServerCommand for preprocessing
|
||||
ServerCommandEvent event = new ServerCommandEvent(this.console, servercommand.msg);
|
|
@ -0,0 +1,55 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 15 Aug 2018 01:16:34 -0400
|
||||
Subject: [PATCH] Ability to get block entities from a chunk without snapshots
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
index 1d4587a97e86251982a9df832949a7093b216862..fc335e4e80553e8c6c915e7813e9610ac10649c2 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
@@ -173,6 +173,13 @@ public class CraftChunk implements Chunk {
|
||||
|
||||
@Override
|
||||
public BlockState[] getTileEntities() {
|
||||
+ // Paper start
|
||||
+ return getTileEntities(true);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public BlockState[] getTileEntities(boolean useSnapshot) {
|
||||
+ // Paper end
|
||||
if (!this.isLoaded()) {
|
||||
this.getWorld().getChunkAt(this.x, this.z); // Transient load for this tick
|
||||
}
|
||||
@@ -182,7 +189,29 @@ public class CraftChunk implements Chunk {
|
||||
BlockState[] entities = new BlockState[chunk.blockEntities.size()];
|
||||
|
||||
for (BlockPos position : chunk.blockEntities.keySet()) {
|
||||
- entities[index++] = this.worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState();
|
||||
+ // Paper start
|
||||
+ entities[index++] = this.worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot);
|
||||
+ }
|
||||
+
|
||||
+ return entities;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Collection<BlockState> getTileEntities(Predicate<? super Block> blockPredicate, boolean useSnapshot) {
|
||||
+ Preconditions.checkNotNull(blockPredicate, "blockPredicate");
|
||||
+ if (!this.isLoaded()) {
|
||||
+ this.getWorld().getChunkAt(this.x, this.z); // Transient load for this tick
|
||||
+ }
|
||||
+ ChunkAccess chunk = this.getHandle(ChunkStatus.FULL);
|
||||
+
|
||||
+ java.util.List<BlockState> entities = new java.util.ArrayList<>();
|
||||
+
|
||||
+ for (BlockPos position : chunk.blockEntities.keySet()) {
|
||||
+ Block block = this.worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ());
|
||||
+ if (blockPredicate.test(block)) {
|
||||
+ entities.add(block.getState(useSnapshot));
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
return entities;
|
107
patches/server/0239-Optimize-BlockPosition-helper-methods.patch
Normal file
107
patches/server/0239-Optimize-BlockPosition-helper-methods.patch
Normal file
|
@ -0,0 +1,107 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Wed, 15 Aug 2018 12:05:12 -0700
|
||||
Subject: [PATCH] Optimize BlockPosition helper methods
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
index 2074d4327f0c356c220f3a6a9761439e76a15fc3..19fdd77d4830b7218b627fdf4ed755d8935c00aa 100644
|
||||
--- a/src/main/java/net/minecraft/core/BlockPos.java
|
||||
+++ b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
@@ -153,67 +153,84 @@ public class BlockPos extends Vec3i {
|
||||
|
||||
@Override
|
||||
public BlockPos above() {
|
||||
- return this.relative(Direction.UP);
|
||||
+ return new BlockPos(this.getX(), this.getY() + 1, this.getZ()); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos above(int distance) {
|
||||
- return this.relative(Direction.UP, distance);
|
||||
+ return distance == 0 ? this : new BlockPos(this.getX(), this.getY() + distance, this.getZ()); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos below() {
|
||||
- return this.relative(Direction.DOWN);
|
||||
+ return new BlockPos(this.getX(), this.getY() - 1, this.getZ()); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos below(int i) {
|
||||
- return this.relative(Direction.DOWN, i);
|
||||
+ return i == 0 ? this : new BlockPos(this.getX(), this.getY() - i, this.getZ()); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos north() {
|
||||
- return this.relative(Direction.NORTH);
|
||||
+ return new BlockPos(this.getX(), this.getY(), this.getZ() - 1); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos north(int distance) {
|
||||
- return this.relative(Direction.NORTH, distance);
|
||||
+ return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() - distance); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos south() {
|
||||
- return this.relative(Direction.SOUTH);
|
||||
+ return new BlockPos(this.getX(), this.getY(), this.getZ() + 1); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos south(int distance) {
|
||||
- return this.relative(Direction.SOUTH, distance);
|
||||
+ return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() + distance); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos west() {
|
||||
- return this.relative(Direction.WEST);
|
||||
+ return new BlockPos(this.getX() - 1, this.getY(), this.getZ()); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos west(int distance) {
|
||||
- return this.relative(Direction.WEST, distance);
|
||||
+ return distance == 0 ? this : new BlockPos(this.getX() - distance, this.getY(), this.getZ()); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos east() {
|
||||
- return this.relative(Direction.EAST);
|
||||
+ return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos east(int distance) {
|
||||
- return this.relative(Direction.EAST, distance);
|
||||
+ return distance == 0 ? this : new BlockPos(this.getX() + distance, this.getY(), this.getZ()); // Paper - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos relative(Direction direction) {
|
||||
+ // Paper start - Perf: Optimize BlockPosition
|
||||
+ switch(direction) {
|
||||
+ case UP:
|
||||
+ return new BlockPos(this.getX(), this.getY() + 1, this.getZ());
|
||||
+ case DOWN:
|
||||
+ return new BlockPos(this.getX(), this.getY() - 1, this.getZ());
|
||||
+ case NORTH:
|
||||
+ return new BlockPos(this.getX(), this.getY(), this.getZ() - 1);
|
||||
+ case SOUTH:
|
||||
+ return new BlockPos(this.getX(), this.getY(), this.getZ() + 1);
|
||||
+ case WEST:
|
||||
+ return new BlockPos(this.getX() - 1, this.getY(), this.getZ());
|
||||
+ case EAST:
|
||||
+ return new BlockPos(this.getX() + 1, this.getY(), this.getZ());
|
||||
+ default:
|
||||
return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ());
|
||||
+ }
|
||||
+ // Paper end - Perf: Optimize BlockPosition
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,20 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 18 Aug 2018 12:43:16 -0400
|
||||
Subject: [PATCH] Restore vanilla default mob-spawn-range and water animals
|
||||
limit
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
index 8491ff48051224204b58d273c4971d16ab8867c1..81c76360e8c7389bafd61f38e6782668e8c65d27 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
@@ -190,7 +190,7 @@ public class SpigotWorldConfig
|
||||
public byte mobSpawnRange;
|
||||
private void mobSpawnRange()
|
||||
{
|
||||
- this.mobSpawnRange = (byte) this.getInt( "mob-spawn-range", 6 );
|
||||
+ this.mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla
|
||||
this.log( "Mob Spawn Range: " + this.mobSpawnRange );
|
||||
}
|
||||
|
154
patches/server/0241-Slime-Pathfinder-Events.patch
Normal file
154
patches/server/0241-Slime-Pathfinder-Events.patch
Normal file
|
@ -0,0 +1,154 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 24 Aug 2018 08:18:42 -0500
|
||||
Subject: [PATCH] Slime Pathfinder Events
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
||||
index 136ec2413b6fe4680d7f2e903d04c9984b37f4c0..7062ef1cfd7d6279a4c6693cbdb80da49f23c542 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
||||
@@ -115,6 +115,7 @@ public class Slime extends Mob implements Enemy {
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag nbt) {
|
||||
super.addAdditionalSaveData(nbt);
|
||||
+ nbt.putBoolean("Paper.canWander", this.canWander); // Paper
|
||||
nbt.putInt("Size", this.getSize() - 1);
|
||||
nbt.putBoolean("wasOnGround", this.wasOnGround);
|
||||
}
|
||||
@@ -123,6 +124,11 @@ public class Slime extends Mob implements Enemy {
|
||||
public void readAdditionalSaveData(CompoundTag nbt) {
|
||||
this.setSize(nbt.getInt("Size") + 1, false);
|
||||
super.readAdditionalSaveData(nbt);
|
||||
+ // Paper start
|
||||
+ if (nbt.contains("Paper.canWander")) {
|
||||
+ this.canWander = nbt.getBoolean("Paper.canWander");
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.wasOnGround = nbt.getBoolean("wasOnGround");
|
||||
}
|
||||
|
||||
@@ -475,7 +481,7 @@ public class Slime extends Mob implements Enemy {
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
- return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl;
|
||||
+ return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeSwimEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper - Slime pathfinder events
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -512,7 +518,15 @@ public class Slime extends Mob implements Enemy {
|
||||
public boolean canUse() {
|
||||
LivingEntity entityliving = this.slime.getTarget();
|
||||
|
||||
- return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl);
|
||||
+ // Paper start - Slime pathfinder events
|
||||
+ if (entityliving == null || !entityliving.isAlive()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!this.slime.canAttack(entityliving)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity()).callEvent();
|
||||
+ // Paper end - Slime pathfinder events
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -525,7 +539,15 @@ public class Slime extends Mob implements Enemy {
|
||||
public boolean canContinueToUse() {
|
||||
LivingEntity entityliving = this.slime.getTarget();
|
||||
|
||||
- return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : --this.growTiredTimer > 0);
|
||||
+ // Paper start - Slime pathfinder events
|
||||
+ if (entityliving == null || !entityliving.isAlive()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!this.slime.canAttack(entityliving)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return --this.growTiredTimer > 0 && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity()).callEvent();
|
||||
+ // Paper end - Slime pathfinder events
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -548,6 +570,13 @@ public class Slime extends Mob implements Enemy {
|
||||
}
|
||||
|
||||
}
|
||||
+
|
||||
+ // Paper start - Slime pathfinder events; clear timer and target when goal resets
|
||||
+ public void stop() {
|
||||
+ this.growTiredTimer = 0;
|
||||
+ this.slime.setTarget(null);
|
||||
+ }
|
||||
+ // Paper end - Slime pathfinder events
|
||||
}
|
||||
|
||||
private static class SlimeRandomDirectionGoal extends Goal {
|
||||
@@ -563,7 +592,7 @@ public class Slime extends Mob implements Enemy {
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
- return this.slime.getTarget() == null && (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl;
|
||||
+ return this.slime.getTarget() == null && (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander; // Paper - Slime pathfinder events
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -571,6 +600,11 @@ public class Slime extends Mob implements Enemy {
|
||||
if (--this.nextRandomizeTime <= 0) {
|
||||
this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60));
|
||||
this.chosenDegrees = (float) this.slime.getRandom().nextInt(360);
|
||||
+ // Paper start - Slime pathfinder events
|
||||
+ com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent event = new com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), this.chosenDegrees);
|
||||
+ if (!this.slime.canWander || !event.callEvent()) return;
|
||||
+ this.chosenDegrees = event.getNewYaw();
|
||||
+ // Paper end - Slime pathfinder events
|
||||
}
|
||||
|
||||
MoveControl controllermove = this.slime.getMoveControl();
|
||||
@@ -593,7 +627,7 @@ public class Slime extends Mob implements Enemy {
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
- return !this.slime.isPassenger();
|
||||
+ return !this.slime.isPassenger() && this.slime.canWander && new com.destroystokyo.paper.event.entity.SlimeWanderEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper - Slime pathfinder events
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -606,4 +640,15 @@ public class Slime extends Mob implements Enemy {
|
||||
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start - Slime pathfinder events
|
||||
+ private boolean canWander = true;
|
||||
+ public boolean canWander() {
|
||||
+ return canWander;
|
||||
+ }
|
||||
+
|
||||
+ public void setWander(boolean canWander) {
|
||||
+ this.canWander = canWander;
|
||||
+ }
|
||||
+ // Paper end - Slime pathfinder events
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java
|
||||
index 3d991d9d9388108ec6d137950913209d61d132e7..3d9b7c0e128ea05bec5600c774e9685998b71cac 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java
|
||||
@@ -28,4 +28,16 @@ public class CraftSlime extends CraftMob implements Slime, CraftEnemy {
|
||||
public String toString() {
|
||||
return "CraftSlime";
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean canWander() {
|
||||
+ return getHandle().canWander();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setWander(boolean canWander) {
|
||||
+ getHandle().setWander(canWander);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Wed, 8 Aug 2018 16:33:21 -0600
|
||||
Subject: [PATCH] Configurable speed for water flowing over lava
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
|
||||
index 6d24989965e5215c1e256444a868633cf2772aa3..84623c632d8c2f0fa7ec939c711316d757117d23 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
|
||||
@@ -138,11 +138,31 @@ public class LiquidBlock extends Block implements BucketPickup {
|
||||
@Override
|
||||
protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
|
||||
if (this.shouldSpreadLiquid(world, pos, state)) {
|
||||
- world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
|
||||
+ world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper - Configurable speed for water flowing over lava
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start - Configurable speed for water flowing over lava
|
||||
+ public int getFlowSpeed(Level world, BlockPos blockposition) {
|
||||
+ if (net.minecraft.core.registries.BuiltInRegistries.FLUID.wrapAsHolder(this.fluid).is(FluidTags.WATER)) {
|
||||
+ if (
|
||||
+ isLava(world, blockposition.north(1)) ||
|
||||
+ isLava(world, blockposition.south(1)) ||
|
||||
+ isLava(world, blockposition.west(1)) ||
|
||||
+ isLava(world, blockposition.east(1))
|
||||
+ ) {
|
||||
+ return world.paperConfig().environment.waterOverLavaFlowSpeed;
|
||||
+ }
|
||||
+ }
|
||||
+ return this.fluid.getTickDelay(world);
|
||||
+ }
|
||||
+ private static boolean isLava(Level world, BlockPos blockPos) {
|
||||
+ final FluidState fluidState = world.getFluidIfLoaded(blockPos);
|
||||
+ return fluidState != null && fluidState.is(FluidTags.LAVA);
|
||||
+ }
|
||||
+ // Paper end - Configurable speed for water flowing over lava
|
||||
+
|
||||
@Override
|
||||
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
|
||||
if (state.getFluidState().isSource() || neighborState.getFluidState().isSource()) {
|
||||
@@ -155,7 +175,7 @@ public class LiquidBlock extends Block implements BucketPickup {
|
||||
@Override
|
||||
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
|
||||
if (this.shouldSpreadLiquid(world, pos, state)) {
|
||||
- world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
|
||||
+ world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper - Configurable speed for water flowing over lava
|
||||
}
|
||||
|
||||
}
|
49
patches/server/0243-Optimize-CraftBlockData-Creation.patch
Normal file
49
patches/server/0243-Optimize-CraftBlockData-Creation.patch
Normal file
|
@ -0,0 +1,49 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: miclebrick <miclebrick@outlook.com>
|
||||
Date: Thu, 23 Aug 2018 11:45:32 -0400
|
||||
Subject: [PATCH] Optimize CraftBlockData Creation
|
||||
|
||||
Avoids a hashmap lookup by cacheing a reference to the CraftBlockData
|
||||
and cloning it when one is needed.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
index 08eb369f8cb4c35be17cef816a0d33295a1ae3e0..da8b97c590fb38f65dee2e8a881a2f7ad658b5e7 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
@@ -807,6 +807,14 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
this.instrument = blockbase_info.instrument;
|
||||
this.replaceable = blockbase_info.replaceable;
|
||||
}
|
||||
+ // Paper start - Perf: impl cached craft block data, lazy load to fix issue with loading at the wrong time
|
||||
+ private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData;
|
||||
+
|
||||
+ public org.bukkit.craftbukkit.block.data.CraftBlockData createCraftBlockData() {
|
||||
+ if (cachedCraftBlockData == null) cachedCraftBlockData = org.bukkit.craftbukkit.block.data.CraftBlockData.createData(asState());
|
||||
+ return (org.bukkit.craftbukkit.block.data.CraftBlockData) cachedCraftBlockData.clone();
|
||||
+ }
|
||||
+ // Paper end - Perf: impl cached craft block data, lazy load to fix issue with loading at the wrong time
|
||||
|
||||
private boolean calculateSolid() {
|
||||
if (((Block) this.owner).properties.forceSolidOn) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||
index d2ec2d11736a74f8d568e25e9b560605518af987..19fab0d8d8a6211782df1fd99b5d60681aecd2f5 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||
@@ -571,7 +571,17 @@ public class CraftBlockData implements BlockData {
|
||||
return craft;
|
||||
}
|
||||
|
||||
+ // Paper start - optimize creating BlockData to not need a map lookup
|
||||
+ static {
|
||||
+ // Initialize cached data for all IBlockData instances after registration
|
||||
+ Block.BLOCK_STATE_REGISTRY.iterator().forEachRemaining(net.minecraft.world.level.block.state.BlockState::createCraftBlockData);
|
||||
+ }
|
||||
public static CraftBlockData fromData(net.minecraft.world.level.block.state.BlockState data) {
|
||||
+ return data.createCraftBlockData();
|
||||
+ }
|
||||
+
|
||||
+ public static CraftBlockData createData(net.minecraft.world.level.block.state.BlockState data) {
|
||||
+ // Paper end
|
||||
return CraftBlockData.MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data);
|
||||
}
|
||||
|
30
patches/server/0244-Optimize-MappedRegistry.patch
Normal file
30
patches/server/0244-Optimize-MappedRegistry.patch
Normal file
|
@ -0,0 +1,30 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 26 Aug 2018 20:49:50 -0400
|
||||
Subject: [PATCH] Optimize MappedRegistry
|
||||
|
||||
Use larger initial sizes to increase bucket capacity on the BiMap
|
||||
|
||||
BiMap.get was seen to be using a good bit of CPU time.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java
|
||||
index aac210f682303b85e207bb230decb1af62a1a25a..a35fe2b8ef35692fb7b5d520944d0c6ae53ac07e 100644
|
||||
--- a/src/main/java/net/minecraft/core/MappedRegistry.java
|
||||
+++ b/src/main/java/net/minecraft/core/MappedRegistry.java
|
||||
@@ -35,11 +35,11 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
final ResourceKey<? extends Registry<T>> key;
|
||||
private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
|
||||
- private final Reference2IntMap<T> toId = Util.make(new Reference2IntOpenHashMap<>(), map -> map.defaultReturnValue(-1));
|
||||
- private final Map<ResourceLocation, Holder.Reference<T>> byLocation = new HashMap<>();
|
||||
- private final Map<ResourceKey<T>, Holder.Reference<T>> byKey = new HashMap<>();
|
||||
- private final Map<T, Holder.Reference<T>> byValue = new IdentityHashMap<>();
|
||||
- private final Map<ResourceKey<T>, RegistrationInfo> registrationInfos = new IdentityHashMap<>();
|
||||
+ private final Reference2IntMap<T> toId = Util.make(new Reference2IntOpenHashMap<>(2048), map -> map.defaultReturnValue(-1)); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
+ private final Map<ResourceLocation, Holder.Reference<T>> byLocation = new HashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
+ private final Map<ResourceKey<T>, Holder.Reference<T>> byKey = new HashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
+ private final Map<T, Holder.Reference<T>> byValue = new IdentityHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
+ private final Map<ResourceKey<T>, RegistrationInfo> registrationInfos = new IdentityHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
private Lifecycle registryLifecycle;
|
||||
private volatile Map<TagKey<T>, HolderSet.Named<T>> tags = new IdentityHashMap<>();
|
||||
private boolean frozen;
|
92
patches/server/0245-Add-PhantomPreSpawnEvent.patch
Normal file
92
patches/server/0245-Add-PhantomPreSpawnEvent.patch
Normal file
|
@ -0,0 +1,92 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sat, 25 Aug 2018 19:56:51 -0500
|
||||
Subject: [PATCH] Add PhantomPreSpawnEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java
|
||||
index ef6bbcb6fc9d37748c74b68966e12637efd00aba..4292a0fbab588a8cd58db36bc279f2991231aeec 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java
|
||||
@@ -165,6 +165,11 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
}
|
||||
|
||||
this.setPhantomSize(nbt.getInt("Size"));
|
||||
+ // Paper start
|
||||
+ if (nbt.hasUUID("Paper.SpawningEntity")) {
|
||||
+ this.spawningEntity = nbt.getUUID("Paper.SpawningEntity");
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -174,6 +179,11 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
nbt.putInt("AY", this.anchorPoint.getY());
|
||||
nbt.putInt("AZ", this.anchorPoint.getZ());
|
||||
nbt.putInt("Size", this.getPhantomSize());
|
||||
+ // Paper start
|
||||
+ if (this.spawningEntity != null) {
|
||||
+ nbt.putUUID("Paper.SpawningEntity", this.spawningEntity);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -219,6 +229,17 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
return entitysize.scale(1.0F + 0.15F * (float) i);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Nullable
|
||||
+ java.util.UUID spawningEntity;
|
||||
+
|
||||
+ @Nullable
|
||||
+ public java.util.UUID getSpawningEntity() {
|
||||
+ return this.spawningEntity;
|
||||
+ }
|
||||
+ public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; }
|
||||
+ // Paper end
|
||||
+
|
||||
private static enum AttackPhase {
|
||||
|
||||
CIRCLE, SWOOP;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
index 9d28e3855a9b150534ef8b6c89e186f5c4c47694..bb7f2d3ff7fc6f5cadb4ab24efb5a3a2f5bdc33f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
@@ -69,9 +69,19 @@ public class PhantomSpawner implements CustomSpawner {
|
||||
int k = 1 + randomsource.nextInt(difficultydamagescaler.getDifficulty().getId() + 1);
|
||||
|
||||
for (int l = 0; l < k; ++l) {
|
||||
+ // Paper start - PhantomPreSpawnEvent
|
||||
+ com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(io.papermc.paper.util.MCUtil.toLocation(world, blockposition1), entityplayer.getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL);
|
||||
+ if (!event.callEvent()) {
|
||||
+ if (event.shouldAbortSpawn()) {
|
||||
+ break;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end - PhantomPreSpawnEvent
|
||||
Phantom entityphantom = (Phantom) EntityType.PHANTOM.create(world);
|
||||
|
||||
if (entityphantom != null) {
|
||||
+ entityphantom.setSpawningEntity(entityplayer.getUUID()); // Paper - PhantomPreSpawnEvent
|
||||
entityphantom.moveTo(blockposition1, 0.0F, 0.0F);
|
||||
groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity);
|
||||
world.addFreshEntityWithPassengers(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java
|
||||
index 0359c161448941f1b9fdac545a5c47a68f19b760..305a635b049741ac5e2670060c6818cb2c07e5ab 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java
|
||||
@@ -28,4 +28,11 @@ public class CraftPhantom extends CraftFlying implements Phantom, CraftEnemy {
|
||||
public String toString() {
|
||||
return "CraftPhantom";
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public java.util.UUID getSpawningEntity() {
|
||||
+ return getHandle().getSpawningEntity();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
60
patches/server/0246-Add-More-Creeper-API.patch
Normal file
60
patches/server/0246-Add-More-Creeper-API.patch
Normal file
|
@ -0,0 +1,60 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 24 Aug 2018 11:50:26 -0500
|
||||
Subject: [PATCH] Add More Creeper API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
||||
index dd57da9dc663484c4266d9973aee927899292749..4b94e21d05d6deae75f0c2fb711e43a4c7d06f90 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
||||
@@ -134,7 +134,7 @@ public class Creeper extends Monster implements PowerableMob {
|
||||
}
|
||||
|
||||
if (nbt.getBoolean("ignited")) {
|
||||
- this.ignite();
|
||||
+ this.entityData.set(Creeper.DATA_IS_IGNITED, true); // Paper - set directly to avoid firing event
|
||||
}
|
||||
|
||||
}
|
||||
@@ -314,7 +314,18 @@ public class Creeper extends Monster implements PowerableMob {
|
||||
}
|
||||
|
||||
public void ignite() {
|
||||
- this.entityData.set(Creeper.DATA_IS_IGNITED, true);
|
||||
+ // Paper start - CreeperIgniteEvent
|
||||
+ setIgnited(true);
|
||||
+ }
|
||||
+
|
||||
+ public void setIgnited(boolean ignited) {
|
||||
+ if (isIgnited() != ignited) {
|
||||
+ com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited);
|
||||
+ if (event.callEvent()) {
|
||||
+ this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - CreeperIgniteEvent
|
||||
}
|
||||
|
||||
public boolean canDropMobsSkull() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java
|
||||
index 127e65c5780c6727fde1ea3e597b116a475a666a..4191845bfe05d8691e50143c42090566522f7e74 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java
|
||||
@@ -88,4 +88,16 @@ public class CraftCreeper extends CraftMonster implements Creeper {
|
||||
public String toString() {
|
||||
return "CraftCreeper";
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void setIgnited(boolean ignited) {
|
||||
+ getHandle().setIgnited(ignited);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isIgnited() {
|
||||
+ return getHandle().isIgnited();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
58
patches/server/0247-Inventory-removeItemAnySlot.patch
Normal file
58
patches/server/0247-Inventory-removeItemAnySlot.patch
Normal file
|
@ -0,0 +1,58 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Tue, 28 Aug 2018 23:04:15 -0400
|
||||
Subject: [PATCH] Inventory#removeItemAnySlot
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
index 88d5590aa07de09e56ac0bd8d23caa588e36807b..6a47c6adb721f0c6737150d8b0ee18ab70f5f281 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
@@ -224,10 +224,16 @@ public class CraftInventory implements Inventory {
|
||||
}
|
||||
|
||||
private int first(ItemStack item, boolean withAmount) {
|
||||
+ // Paper start
|
||||
+ return first(item, withAmount, getStorageContents());
|
||||
+ }
|
||||
+
|
||||
+ private int first(ItemStack item, boolean withAmount, ItemStack[] inventory) {
|
||||
+ // Paper end
|
||||
if (item == null) {
|
||||
return -1;
|
||||
}
|
||||
- ItemStack[] inventory = this.getStorageContents();
|
||||
+ // ItemStack[] inventory = this.getStorageContents(); // Paper - let param deal
|
||||
for (int i = 0; i < inventory.length; i++) {
|
||||
if (inventory[i] == null) continue;
|
||||
|
||||
@@ -351,6 +357,17 @@ public class CraftInventory implements Inventory {
|
||||
|
||||
@Override
|
||||
public HashMap<Integer, ItemStack> removeItem(ItemStack... items) {
|
||||
+ // Paper start
|
||||
+ return removeItem(false, items);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public HashMap<Integer, ItemStack> removeItemAnySlot(ItemStack... items) {
|
||||
+ return removeItem(true, items);
|
||||
+ }
|
||||
+
|
||||
+ private HashMap<Integer, ItemStack> removeItem(boolean searchEntire, ItemStack... items) {
|
||||
+ // Paper end
|
||||
Preconditions.checkArgument(items != null, "items cannot be null");
|
||||
HashMap<Integer, ItemStack> leftover = new HashMap<Integer, ItemStack>();
|
||||
|
||||
@@ -362,7 +379,10 @@ public class CraftInventory implements Inventory {
|
||||
int toDelete = item.getAmount();
|
||||
|
||||
while (true) {
|
||||
- int first = this.first(item, false);
|
||||
+ // Paper start - Allow searching entire contents
|
||||
+ ItemStack[] toSearch = searchEntire ? getContents() : getStorageContents();
|
||||
+ int first = this.first(item, false, toSearch);
|
||||
+ // Paper end
|
||||
|
||||
// Drat! we don't have this type in the inventory
|
||||
if (first == -1) {
|
|
@ -0,0 +1,20 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 2 Sep 2018 19:34:33 -0700
|
||||
Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted
|
||||
chunks
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 59060c33f87db609510df111234b957b51badd87..4a7c418a497b98d5038794b6bbc38f5e0b7fedd7 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -407,7 +407,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);
|
||||
+ ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper
|
||||
|
||||
// If generate = false, but the chunk already exists, we will get this back.
|
||||
if (chunk instanceof ImposterProtoChunk) {
|
|
@ -0,0 +1,68 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Mon, 3 Sep 2018 18:20:03 -0500
|
||||
Subject: [PATCH] Add ray tracing methods to LivingEntity
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 7d44d4563e39f279cf335f307a4d84d0758858ee..67ba23c66e253d3a96f6b08a5580387859652aa2 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3932,6 +3932,19 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
|
||||
// Paper start - Make shield blocking delay configurable
|
||||
+ public HitResult getRayTrace(int maxDistance, ClipContext.Fluid fluidCollisionOption) {
|
||||
+ if (maxDistance < 1 || maxDistance > 120) {
|
||||
+ throw new IllegalArgumentException("maxDistance must be between 1-120");
|
||||
+ }
|
||||
+
|
||||
+ Vec3 start = new Vec3(getX(), getY() + getEyeHeight(), getZ());
|
||||
+ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance);
|
||||
+ Vec3 end = new Vec3(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ());
|
||||
+ ClipContext raytrace = new ClipContext(start, end, ClipContext.Block.OUTLINE, fluidCollisionOption, this);
|
||||
+
|
||||
+ return this.level().clip(raytrace);
|
||||
+ }
|
||||
+
|
||||
public int shieldBlockingDelay = this.level().paperConfig().misc.shieldBlockingDelay;
|
||||
|
||||
public int getShieldBlockingDelay() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
index bd5b535663935dc8f4a2a8f5c233c1c720400bd7..fa2cb4820698d4f0f317d7abd14216bdd54143a7 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
@@ -200,6 +200,33 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
return blocks.get(0);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public Block getTargetBlock(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
|
||||
+ return this.getTargetBlockExact(maxDistance, fluidMode.bukkit);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
|
||||
+ return this.getTargetBlockFace(maxDistance, fluidMode.bukkit);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, org.bukkit.FluidCollisionMode fluidMode) {
|
||||
+ RayTraceResult result = this.rayTraceBlocks(maxDistance, fluidMode);
|
||||
+ return result != null ? result.getHitBlockFace() : null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
|
||||
+ RayTraceResult result = this.rayTraceBlocks(maxDistance, fluidMode.bukkit);
|
||||
+ if (result != null && result.getHitBlock() != null && result.getHitBlockFace() != null) {
|
||||
+ return new com.destroystokyo.paper.block.TargetBlockInfo(result.getHitBlock(), result.getHitBlockFace());
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public List<Block> getLastTwoTargetBlocks(Set<Material> transparent, int maxDistance) {
|
||||
return this.getLineOfSight(transparent, maxDistance, 2);
|
|
@ -0,0 +1,32 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Tue, 4 Sep 2018 15:02:00 -0500
|
||||
Subject: [PATCH] Expose attack cooldown methods for Player
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 87e3eeb126284eab6d3391ae11d3bf2a8edfcb61..b3f6e1277c7afc77ff34ac14d3d16d1501abe14e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -2964,6 +2964,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
|
||||
return this.adventure$pointers;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public float getCooldownPeriod() {
|
||||
+ return getHandle().getCurrentItemAttackStrengthDelay();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public float getCooledAttackStrength(float adjustTicks) {
|
||||
+ return getHandle().getAttackStrengthScale(adjustTicks);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void resetCooldown() {
|
||||
+ getHandle().resetAttackStrengthTicker();
|
||||
+ }
|
||||
// Paper end
|
||||
// Spigot start
|
||||
private final Player.Spigot spigot = new Player.Spigot()
|
517
patches/server/0251-Improve-death-events.patch
Normal file
517
patches/server/0251-Improve-death-events.patch
Normal file
|
@ -0,0 +1,517 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Phoenix616 <mail@moep.tv>
|
||||
Date: Tue, 21 Aug 2018 01:39:35 +0100
|
||||
Subject: [PATCH] Improve death events
|
||||
|
||||
This adds the ability to cancel the death events and to modify the sound
|
||||
an entity makes when dying. (In cases were no sound should it will be
|
||||
called with shouldPlaySound set to false allowing unsilencing of silent
|
||||
entities)
|
||||
|
||||
It makes handling of entity deaths a lot nicer as you no longer need
|
||||
to listen on the damage event and calculate if the entity dies yourself
|
||||
to cancel the death which has the benefit of also receiving the dropped
|
||||
items and experience which is otherwise only properly possible by using
|
||||
internal code.
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.LivingEntity getDeathSound()Lnet/minecraft/sounds/SoundEvent;
|
||||
public net.minecraft.world.entity.LivingEntity getSoundVolume()F
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index e073b48ed6cbefc503216615f54d09b309217d80..c97410f580f31389987ef944fc410e44459a4693 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -263,6 +263,10 @@ public class ServerPlayer extends Player {
|
||||
private int containerCounter;
|
||||
public boolean wonGame;
|
||||
private int containerUpdateDelay; // Paper - Configurable container update tick rate
|
||||
+ // Paper start - cancellable death event
|
||||
+ public boolean queueHealthUpdatePacket;
|
||||
+ public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
|
||||
+ // Paper end - cancellable death event
|
||||
|
||||
// CraftBukkit start
|
||||
public CraftPlayer.TransferCookieConnection transferCookieConnection;
|
||||
@@ -877,7 +881,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
@Override
|
||||
public void die(DamageSource damageSource) {
|
||||
- this.gameEvent(GameEvent.ENTITY_DIE);
|
||||
+ // this.gameEvent(GameEvent.ENTITY_DIE); // Paper - move below event cancellation check
|
||||
boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES);
|
||||
// CraftBukkit start - fire PlayerDeathEvent
|
||||
if (this.isRemoved()) {
|
||||
@@ -905,6 +909,16 @@ public class ServerPlayer extends Player {
|
||||
String deathmessage = defaultMessage.getString();
|
||||
this.keepLevel = keepInventory; // SPIGOT-2222: pre-set keepLevel
|
||||
org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), keepInventory); // Paper - Adventure
|
||||
+ // Paper start - cancellable death event
|
||||
+ if (event.isCancelled()) {
|
||||
+ // make compatible with plugins that might have already set the health in an event listener
|
||||
+ if (this.getHealth() <= 0) {
|
||||
+ this.setHealth((float) event.getReviveHealth());
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ this.gameEvent(GameEvent.ENTITY_DIE); // moved from the top of this method
|
||||
+ // Paper end
|
||||
|
||||
// SPIGOT-943 - only call if they have an inventory open
|
||||
if (this.containerMenu != this.inventoryMenu) {
|
||||
@@ -1053,8 +1067,17 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
}
|
||||
-
|
||||
- return super.hurt(source, amount);
|
||||
+ // Paper start - cancellable death events
|
||||
+ //return super.hurt(source, amount);
|
||||
+ this.queueHealthUpdatePacket = true;
|
||||
+ boolean damaged = super.hurt(source, amount);
|
||||
+ this.queueHealthUpdatePacket = false;
|
||||
+ if (this.queuedHealthUpdatePacket != null) {
|
||||
+ this.connection.send(this.queuedHealthUpdatePacket);
|
||||
+ this.queuedHealthUpdatePacket = null;
|
||||
+ }
|
||||
+ return damaged;
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 67ba23c66e253d3a96f6b08a5580387859652aa2..a770d2bda45cee739a5371119018e6f6e4cbb2cb 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -271,6 +271,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
public Set<UUID> collidableExemptions = new HashSet<>();
|
||||
public boolean bukkitPickUpLoot;
|
||||
public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper
|
||||
+ public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event
|
||||
|
||||
@Override
|
||||
public float getBukkitYaw() {
|
||||
@@ -1543,11 +1544,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
|
||||
if (this.isDeadOrDying()) {
|
||||
if (!this.checkTotemDeathProtection(source)) {
|
||||
- if (flag1) {
|
||||
- this.makeSound(this.getDeathSound());
|
||||
- }
|
||||
+ // Paper start - moved into CraftEventFactory event caller for cancellable death event
|
||||
+ this.silentDeath = !flag1; // mark entity as dying silently
|
||||
+ // Paper end
|
||||
|
||||
this.die(source);
|
||||
+ this.silentDeath = false; // Paper - cancellable death event - reset to default
|
||||
}
|
||||
} else if (flag1) {
|
||||
this.playHurtSound(source);
|
||||
@@ -1706,6 +1708,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
Entity entity = damageSource.getEntity();
|
||||
LivingEntity entityliving = this.getKillCredit();
|
||||
|
||||
+ /* // Paper - move down to make death event cancellable - this is the awardKillScore below
|
||||
if (this.deathScore >= 0 && entityliving != null) {
|
||||
entityliving.awardKillScore(this, this.deathScore, damageSource);
|
||||
}
|
||||
@@ -1717,24 +1720,59 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (!this.level().isClientSide && this.hasCustomName()) {
|
||||
if (org.spigotmc.SpigotConfig.logNamedDeaths) LivingEntity.LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); // Spigot
|
||||
}
|
||||
+ */ // Paper - move down to make death event cancellable - this is the awardKillScore below
|
||||
|
||||
this.dead = true;
|
||||
- this.getCombatTracker().recheckStatus();
|
||||
+ // Paper - moved into if below
|
||||
Level world = this.level();
|
||||
|
||||
if (world instanceof ServerLevel) {
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
+ // Paper - move below into if for onKill
|
||||
+
|
||||
+ // Paper start
|
||||
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.dropAllDeathLoot(damageSource);
|
||||
+ if (deathEvent == null || !deathEvent.isCancelled()) {
|
||||
+ if (this.deathScore >= 0 && entityliving != null) {
|
||||
+ entityliving.awardKillScore(this, this.deathScore, damageSource);
|
||||
+ }
|
||||
+ // Paper start - clear equipment if event is not cancelled
|
||||
+ if (this instanceof Mob) {
|
||||
+ for (EquipmentSlot slot : this.clearedEquipmentSlots) {
|
||||
+ this.setItemSlot(slot, ItemStack.EMPTY);
|
||||
+ }
|
||||
+ this.clearedEquipmentSlots.clear();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ if (this.isSleeping()) {
|
||||
+ this.stopSleeping();
|
||||
+ }
|
||||
+
|
||||
+ if (!this.level().isClientSide && this.hasCustomName()) {
|
||||
+ if (org.spigotmc.SpigotConfig.logNamedDeaths) LivingEntity.LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); // Spigot
|
||||
+ }
|
||||
|
||||
- if (entity == null || entity.killedEntity(worldserver, this)) {
|
||||
+ this.getCombatTracker().recheckStatus();
|
||||
+ if (entity != null) {
|
||||
+ entity.killedEntity((ServerLevel) this.level(), this);
|
||||
+ }
|
||||
this.gameEvent(GameEvent.ENTITY_DIE);
|
||||
- this.dropAllDeathLoot(damageSource);
|
||||
- this.createWitherRose(entityliving);
|
||||
+ } else {
|
||||
+ this.dead = false;
|
||||
+ this.setHealth((float) deathEvent.getReviveHealth());
|
||||
}
|
||||
|
||||
- this.level().broadcastEntityEvent(this, (byte) 3);
|
||||
+ // Paper end
|
||||
+ this.createWitherRose(entityliving);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ if (this.dead) { // Paper
|
||||
+ this.level().broadcastEntityEvent(this, (byte) 3);
|
||||
this.setPose(Pose.DYING);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1742,7 +1780,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (!this.level().isClientSide) {
|
||||
boolean flag = false;
|
||||
|
||||
- if (adversary instanceof WitherBoss) {
|
||||
+ if (this.dead && adversary instanceof WitherBoss) { // Paper
|
||||
if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
BlockPos blockposition = this.blockPosition();
|
||||
BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState();
|
||||
@@ -1771,7 +1809,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
}
|
||||
|
||||
- protected void dropAllDeathLoot(DamageSource source) {
|
||||
+ // Paper start
|
||||
+ protected boolean clearEquipmentSlots = true;
|
||||
+ protected Set<EquipmentSlot> clearedEquipmentSlots = new java.util.HashSet<>();
|
||||
+ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) {
|
||||
+ // Paper end
|
||||
Entity entity = source.getEntity();
|
||||
int i;
|
||||
|
||||
@@ -1786,18 +1828,27 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
this.dropEquipment(); // CraftBukkit - from below
|
||||
if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
this.dropFromLootTable(source, flag);
|
||||
+ // Paper start
|
||||
+ final boolean prev = this.clearEquipmentSlots;
|
||||
+ this.clearEquipmentSlots = false;
|
||||
+ this.clearedEquipmentSlots.clear();
|
||||
+ // Paper end
|
||||
this.dropCustomDeathLoot(source, i, flag);
|
||||
+ this.clearEquipmentSlots = prev; // Paper
|
||||
}
|
||||
// CraftBukkit start - Call death event
|
||||
- CraftEventFactory.callEntityDeathEvent(this, this.drops);
|
||||
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper
|
||||
+ this.postDeathDropItems(deathEvent); // Paper
|
||||
this.drops = new ArrayList<>();
|
||||
// CraftBukkit end
|
||||
|
||||
// this.dropInventory();// CraftBukkit - moved up
|
||||
this.dropExperience();
|
||||
+ return deathEvent; // Paper
|
||||
}
|
||||
|
||||
protected void dropEquipment() {}
|
||||
+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled
|
||||
|
||||
// CraftBukkit start
|
||||
public int getExpReward() {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
index b740d931ad7ad81bf94afa62a9ae44a2fe9549d4..2b282ba23444110949508dac11a25fee4e472f5d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
@@ -1167,6 +1167,12 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ protected boolean shouldSkipLoot(EquipmentSlot slot) { // method to avoid to fallback into the global mob loot logic (i.e fox)
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
protected void dropCustomDeathLoot(DamageSource source, int lootingMultiplier, boolean allowDrops) {
|
||||
super.dropCustomDeathLoot(source, lootingMultiplier, allowDrops);
|
||||
@@ -1175,6 +1181,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
|
||||
|
||||
for (int k = 0; k < j; ++k) {
|
||||
EquipmentSlot enumitemslot = aenumitemslot[k];
|
||||
+ if (this.shouldSkipLoot(enumitemslot)) continue; // Paper
|
||||
ItemStack itemstack = this.getItemBySlot(enumitemslot);
|
||||
float f = this.getEquipmentDropChance(enumitemslot);
|
||||
boolean flag1 = f > 1.0F;
|
||||
@@ -1185,7 +1192,13 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
|
||||
}
|
||||
|
||||
this.spawnAtLocation(itemstack);
|
||||
+ if (this.clearEquipmentSlots) { // Paper
|
||||
this.setItemSlot(enumitemslot, ItemStack.EMPTY);
|
||||
+ // Paper start
|
||||
+ } else {
|
||||
+ this.clearedEquipmentSlots.add(enumitemslot);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
index d2dfccd1e31b2f050c9f480220cf17df71c687c3..82ced9f42dced65322a55579bb764fb4dc7c1b66 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
||||
@@ -704,16 +704,38 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
|
||||
return this.getTrustedUUIDs().contains(uuid);
|
||||
}
|
||||
|
||||
+ // Paper start - handle the bitten item separately like vanilla
|
||||
@Override
|
||||
- protected void dropAllDeathLoot(DamageSource source) {
|
||||
+ protected boolean shouldSkipLoot(EquipmentSlot slot) {
|
||||
+ return slot == EquipmentSlot.MAINHAND;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ @Override
|
||||
+ // Paper start - Cancellable death event
|
||||
+ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) {
|
||||
ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND);
|
||||
|
||||
- if (!itemstack.isEmpty()) {
|
||||
+ boolean releaseMouth = false;
|
||||
+ if (!itemstack.isEmpty() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Fix MC-153010
|
||||
this.spawnAtLocation(itemstack);
|
||||
+ releaseMouth = true;
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.dropAllDeathLoot(source);
|
||||
+
|
||||
+ // Below is code to drop
|
||||
+
|
||||
+ if (deathEvent == null || deathEvent.isCancelled()) {
|
||||
+ return deathEvent;
|
||||
+ }
|
||||
+
|
||||
+ if (releaseMouth) {
|
||||
+ // Paper end - Cancellable death event
|
||||
this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
- super.dropAllDeathLoot(source);
|
||||
+ return deathEvent; // Paper - Cancellable death event
|
||||
}
|
||||
|
||||
public static boolean isPathClear(Fox fox, LivingEntity chasedEntity) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
|
||||
index b93ea19186e9988b75fa55736df602fa7e5d1648..557d938b65af6b0e55571011bd1c50decbb64a3d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
|
||||
@@ -77,9 +77,17 @@ public abstract class AbstractChestedHorse extends AbstractHorse {
|
||||
this.spawnAtLocation(Blocks.CHEST);
|
||||
}
|
||||
|
||||
+ //this.setChest(false); // Paper - moved to post death logic
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Paper start
|
||||
+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {
|
||||
+ if (this.hasChest() && (event == null || !event.isCancelled())) {
|
||||
this.setChest(false);
|
||||
}
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag nbt) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
index 042968ff848da74be0c9fcf9bac3d0adfb135802..cb3729509e50fed64b17f16797825c1d21f7bf5b 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -499,8 +499,10 @@ public class ArmorStand extends LivingEntity {
|
||||
}
|
||||
// CraftBukkit end
|
||||
if (source.is(DamageTypeTags.IS_EXPLOSION)) {
|
||||
- this.brokenByAnything(source);
|
||||
- this.kill();
|
||||
+ // Paper start - avoid duplicate event call
|
||||
+ org.bukkit.event.entity.EntityDeathEvent event = this.brokenByAnything(source);
|
||||
+ if (!event.isCancelled()) this.kill(false);
|
||||
+ // Paper end
|
||||
return false;
|
||||
} else if (source.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) {
|
||||
if (this.isOnFire()) {
|
||||
@@ -543,9 +545,9 @@ public class ArmorStand extends LivingEntity {
|
||||
this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity());
|
||||
this.lastHit = i;
|
||||
} else {
|
||||
- this.brokenByPlayer(source);
|
||||
+ org.bukkit.event.entity.EntityDeathEvent event = this.brokenByPlayer(source); // Paper
|
||||
this.showBreakingParticles();
|
||||
- this.discard(EntityRemoveEvent.Cause.DEATH); // CraftBukkit - SPIGOT-4890: remain as this.discard() since above damagesource method will call death event
|
||||
+ if (!event.isCancelled()) this.kill(false); // Paper - we still need to kill to follow vanilla logic (emit the game event etc...)
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -597,8 +599,10 @@ public class ArmorStand extends LivingEntity {
|
||||
|
||||
f1 -= amount;
|
||||
if (f1 <= 0.5F) {
|
||||
- this.brokenByAnything(damageSource);
|
||||
- this.kill();
|
||||
+ // Paper start - avoid duplicate event call
|
||||
+ org.bukkit.event.entity.EntityDeathEvent event = this.brokenByAnything(damageSource);
|
||||
+ if (!event.isCancelled()) this.kill(false);
|
||||
+ // Paper end
|
||||
} else {
|
||||
this.setHealth(f1);
|
||||
this.gameEvent(GameEvent.ENTITY_DAMAGE, damageSource.getEntity());
|
||||
@@ -606,15 +610,15 @@ public class ArmorStand extends LivingEntity {
|
||||
|
||||
}
|
||||
|
||||
- private void brokenByPlayer(DamageSource damageSource) {
|
||||
+ private org.bukkit.event.entity.EntityDeathEvent brokenByPlayer(DamageSource damageSource) { // Paper
|
||||
ItemStack itemstack = new ItemStack(Items.ARMOR_STAND);
|
||||
|
||||
itemstack.set(DataComponents.CUSTOM_NAME, this.getCustomName());
|
||||
this.drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops
|
||||
- this.brokenByAnything(damageSource);
|
||||
+ return this.brokenByAnything(damageSource); // Paper
|
||||
}
|
||||
|
||||
- private void brokenByAnything(DamageSource damageSource) {
|
||||
+ private org.bukkit.event.entity.EntityDeathEvent brokenByAnything(DamageSource damageSource) { // Paper
|
||||
this.playBrokenSound();
|
||||
// this.dropAllDeathLoot(damagesource); // CraftBukkit - moved down
|
||||
|
||||
@@ -636,7 +640,7 @@ public class ArmorStand extends LivingEntity {
|
||||
this.armorItems.set(i, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
- this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above
|
||||
+ return this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above // Paper
|
||||
|
||||
}
|
||||
|
||||
@@ -758,7 +762,16 @@ public class ArmorStand extends LivingEntity {
|
||||
|
||||
@Override
|
||||
public void kill() {
|
||||
- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, this.drops); // CraftBukkit - call event
|
||||
+ // Paper start
|
||||
+ kill(true);
|
||||
+ }
|
||||
+
|
||||
+ public void kill(boolean callEvent) {
|
||||
+ if (callEvent) {
|
||||
+ // Paper end
|
||||
+ org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, this.drops); // CraftBukkit - call event // Paper - make cancellable
|
||||
+ if (event.isCancelled()) return; // Paper - make cancellable
|
||||
+ } // Paper
|
||||
this.remove(Entity.RemovalReason.KILLED, EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause
|
||||
this.gameEvent(GameEvent.ENTITY_DIE);
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index b3f6e1277c7afc77ff34ac14d3d16d1501abe14e..32bd55d8853cd1be12e910fc6626b96a6f3ea558 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -2502,7 +2502,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
@Override
|
||||
public void sendHealthUpdate() {
|
||||
FoodData foodData = this.getHandle().getFoodData();
|
||||
- this.sendHealthUpdate(this.getScaledHealth(), foodData.getFoodLevel(), foodData.getSaturationLevel());
|
||||
+ // Paper start - cancellable death event
|
||||
+ ClientboundSetHealthPacket packet = new ClientboundSetHealthPacket(this.getScaledHealth(), foodData.getFoodLevel(), foodData.getSaturationLevel());
|
||||
+ if (this.getHandle().queueHealthUpdatePacket) {
|
||||
+ this.getHandle().queuedHealthUpdatePacket = packet;
|
||||
+ } else {
|
||||
+ this.getHandle().connection.send(packet);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public void injectScaledMaxHealth(Collection<AttributeInstance> collection, boolean force) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index cecadd303f40a0e4a3e8315aa58226b6eb3ff7c3..e2d74bf7e888b5161b210393e72c484058a3657b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -891,9 +891,16 @@ public class CraftEventFactory {
|
||||
public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List<org.bukkit.inventory.ItemStack> drops) {
|
||||
CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity();
|
||||
EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward());
|
||||
+ populateFields(victim, event); // Paper - make cancellable
|
||||
CraftWorld world = (CraftWorld) entity.getWorld();
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
+ // Paper start - make cancellable
|
||||
+ if (event.isCancelled()) {
|
||||
+ return event;
|
||||
+ }
|
||||
+ playDeathSound(victim, event);
|
||||
+ // Paper end
|
||||
victim.expToDrop = event.getDroppedExp();
|
||||
|
||||
for (org.bukkit.inventory.ItemStack stack : event.getDrops()) {
|
||||
@@ -910,8 +917,15 @@ public class CraftEventFactory {
|
||||
PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage);
|
||||
event.setKeepInventory(keepInventory);
|
||||
event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel
|
||||
+ populateFields(victim, event); // Paper - make cancellable
|
||||
org.bukkit.World world = entity.getWorld();
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
+ // Paper start - make cancellable
|
||||
+ if (event.isCancelled()) {
|
||||
+ return event;
|
||||
+ }
|
||||
+ playDeathSound(victim, event);
|
||||
+ // Paper end
|
||||
|
||||
victim.keepLevel = event.getKeepLevel();
|
||||
victim.newLevel = event.getNewLevel();
|
||||
@@ -928,6 +942,31 @@ public class CraftEventFactory {
|
||||
return event;
|
||||
}
|
||||
|
||||
+ // Paper start - helper methods for making death event cancellable
|
||||
+ // Add information to death event
|
||||
+ private static void populateFields(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) {
|
||||
+ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue());
|
||||
+ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent());
|
||||
+ net.minecraft.sounds.SoundEvent soundEffect = victim.getDeathSound();
|
||||
+ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.minecraftToBukkit(soundEffect) : null);
|
||||
+ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundSource().name()));
|
||||
+ event.setDeathSoundVolume(victim.getSoundVolume());
|
||||
+ event.setDeathSoundPitch(victim.getVoicePitch());
|
||||
+ }
|
||||
+
|
||||
+ // Play death sound manually
|
||||
+ private static void playDeathSound(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) {
|
||||
+ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) {
|
||||
+ net.minecraft.world.entity.player.Player source = victim instanceof net.minecraft.world.entity.player.Player ? (net.minecraft.world.entity.player.Player) victim : null;
|
||||
+ double x = event.getEntity().getLocation().getX();
|
||||
+ double y = event.getEntity().getLocation().getY();
|
||||
+ double z = event.getEntity().getLocation().getZ();
|
||||
+ net.minecraft.sounds.SoundEvent soundEffect = org.bukkit.craftbukkit.CraftSound.bukkitToMinecraft(event.getDeathSound());
|
||||
+ net.minecraft.sounds.SoundSource soundCategory = net.minecraft.sounds.SoundSource.valueOf(event.getDeathSoundCategory().name());
|
||||
+ victim.level().playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
/**
|
||||
* Server methods
|
||||
*/
|
|
@ -0,0 +1,31 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sat, 8 Sep 2018 18:43:31 -0500
|
||||
Subject: [PATCH] Allow chests to be placed with NBT data
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
index 6f1ff953e6311ff859d3ddc5734d33146237992b..86aae218fb760d12e254dcf252c9f78c0ba856d5 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -461,6 +461,7 @@ public final class ItemStack implements DataComponentHolder {
|
||||
enuminteractionresult = InteractionResult.FAIL; // cancel placement
|
||||
// PAIL: Remove this when MC-99075 fixed
|
||||
placeEvent.getPlayer().updateInventory();
|
||||
+ world.capturedTileEntities.clear(); // Paper - Allow chests to be placed with NBT data; clear out block entities as chests and such will pop loot
|
||||
// revert back all captured blocks
|
||||
world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710
|
||||
for (BlockState blockstate : blocks) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
index 9d6262e286a00f840d88d6eb6bfdb304467466e3..b88aa184cd06a0485146f58a5b61a56a50911209 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
@@ -238,7 +238,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
// CraftBukkit start
|
||||
@Override
|
||||
public boolean onlyOpCanSetNbt() {
|
||||
- return true;
|
||||
+ return false; // Paper - Allow chests to be placed with NBT data
|
||||
}
|
||||
// CraftBukkit end
|
||||
}
|
204
patches/server/0253-Mob-Pathfinding-API.patch
Normal file
204
patches/server/0253-Mob-Pathfinding-API.patch
Normal file
|
@ -0,0 +1,204 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 9 Sep 2018 13:30:00 -0400
|
||||
Subject: [PATCH] Mob Pathfinding API
|
||||
|
||||
Implements Pathfinding API for mobs
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.entity.ai.navigation.PathNavigation pathFinder
|
||||
public net.minecraft.world.level.pathfinder.PathFinder nodeEvaluator
|
||||
public net.minecraft.world.level.pathfinder.Path nodes
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..064712e7b27a200b29c72076a82f4f5611fa507f
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java
|
||||
@@ -0,0 +1,143 @@
|
||||
+package com.destroystokyo.paper.entity;
|
||||
+
|
||||
+import org.apache.commons.lang.Validate;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
||||
+import org.bukkit.entity.LivingEntity;
|
||||
+import org.bukkit.entity.Mob;
|
||||
+import javax.annotation.Nonnull;
|
||||
+import javax.annotation.Nullable;
|
||||
+import net.minecraft.world.level.pathfinder.Node;
|
||||
+import net.minecraft.world.level.pathfinder.Path;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+
|
||||
+public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder {
|
||||
+
|
||||
+ private net.minecraft.world.entity.Mob entity;
|
||||
+
|
||||
+ public PaperPathfinder(net.minecraft.world.entity.Mob entity) {
|
||||
+ this.entity = entity;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Mob getEntity() {
|
||||
+ return entity.getBukkitMob();
|
||||
+ }
|
||||
+
|
||||
+ public void setHandle(net.minecraft.world.entity.Mob entity) {
|
||||
+ this.entity = entity;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void stopPathfinding() {
|
||||
+ entity.getNavigation().stop();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasPath() {
|
||||
+ return entity.getNavigation().getPath() != null && !entity.getNavigation().getPath().isDone();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public PathResult getCurrentPath() {
|
||||
+ Path path = entity.getNavigation().getPath();
|
||||
+ return path != null && !path.isDone() ? new PaperPathResult(path) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public PathResult findPath(Location loc) {
|
||||
+ Validate.notNull(loc, "Location can not be null");
|
||||
+ Path path = entity.getNavigation().createPath(loc.getX(), loc.getY(), loc.getZ(), 0);
|
||||
+ return path != null ? new PaperPathResult(path) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public PathResult findPath(LivingEntity target) {
|
||||
+ Validate.notNull(target, "Target can not be null");
|
||||
+ Path path = entity.getNavigation().createPath(((CraftLivingEntity) target).getHandle(), 0);
|
||||
+ return path != null ? new PaperPathResult(path) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean moveTo(@Nonnull PathResult path, double speed) {
|
||||
+ Validate.notNull(path, "PathResult can not be null");
|
||||
+ Path pathEntity = ((PaperPathResult) path).path;
|
||||
+ return entity.getNavigation().moveTo(pathEntity, speed);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canOpenDoors() {
|
||||
+ return entity.getNavigation().pathFinder.nodeEvaluator.canOpenDoors();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanOpenDoors(boolean canOpenDoors) {
|
||||
+ entity.getNavigation().pathFinder.nodeEvaluator.setCanOpenDoors(canOpenDoors);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canPassDoors() {
|
||||
+ return entity.getNavigation().pathFinder.nodeEvaluator.canPassDoors();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanPassDoors(boolean canPassDoors) {
|
||||
+ entity.getNavigation().pathFinder.nodeEvaluator.setCanPassDoors(canPassDoors);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canFloat() {
|
||||
+ return entity.getNavigation().pathFinder.nodeEvaluator.canFloat();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCanFloat(boolean canFloat) {
|
||||
+ entity.getNavigation().pathFinder.nodeEvaluator.setCanFloat(canFloat);
|
||||
+ }
|
||||
+
|
||||
+ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult {
|
||||
+
|
||||
+ private final Path path;
|
||||
+ PaperPathResult(Path path) {
|
||||
+ this.path = path;
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public Location getFinalPoint() {
|
||||
+ Node point = path.getEndNode();
|
||||
+ return point != null ? toLoc(point) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<Location> getPoints() {
|
||||
+ List<Location> points = new ArrayList<>();
|
||||
+ for (Node point : path.nodes) {
|
||||
+ points.add(toLoc(point));
|
||||
+ }
|
||||
+ return points;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getNextPointIndex() {
|
||||
+ return path.getNextNodeIndex();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ @Override
|
||||
+ public Location getNextPoint() {
|
||||
+ if (!path.hasNext()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ return toLoc(path.nodes.get(path.getNextNodeIndex()));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private Location toLoc(Node point) {
|
||||
+ return new Location(entity.level().getWorld(), point.x, point.y, point.z);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
||||
index f6419f3b345e9e21a05b315aa4669090d7da4194..d9d0fff9962131808d54cca20f209df50b8e4af1 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
||||
@@ -18,6 +18,7 @@ public class Path {
|
||||
private final BlockPos target;
|
||||
private final float distToTarget;
|
||||
private final boolean reached;
|
||||
+ public boolean hasNext() { return getNextNodeIndex() < this.nodes.size(); } // Paper - Mob Pathfinding API
|
||||
|
||||
public Path(List<Node> nodes, BlockPos target, boolean reachesTarget) {
|
||||
this.nodes = nodes;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
index 58e690a91aea9ea294f8e4ec9861aa92bc6060a0..d597eea5d5c2f223e87bff06f292619657596f1f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
||||
@@ -13,8 +13,11 @@ import org.bukkit.loot.LootTable;
|
||||
public abstract class CraftMob extends CraftLivingEntity implements Mob {
|
||||
public CraftMob(CraftServer server, net.minecraft.world.entity.Mob entity) {
|
||||
super(server, entity);
|
||||
+ paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper - Mob Pathfinding API
|
||||
}
|
||||
|
||||
+ private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper - Mob Pathfinding API
|
||||
+ @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper - Mob Pathfinding API
|
||||
@Override
|
||||
public void setTarget(LivingEntity target) {
|
||||
Preconditions.checkState(!this.getHandle().generation, "Cannot set target during world generation");
|
||||
@@ -55,6 +58,14 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob {
|
||||
return (net.minecraft.world.entity.Mob) this.entity;
|
||||
}
|
||||
|
||||
+ // Paper start - Mob Pathfinding API
|
||||
+ @Override
|
||||
+ public void setHandle(net.minecraft.world.entity.Entity entity) {
|
||||
+ super.setHandle(entity);
|
||||
+ paperPathfinder.setHandle(getHandle());
|
||||
+ }
|
||||
+ // Paper end - Mob Pathfinding API
|
||||
+
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CraftMob";
|
Loading…
Add table
Add a link
Reference in a new issue