From c0a3a0d12cb2b0a65dbb81cb9275e27c7732f0ad Mon Sep 17 00:00:00 2001 From: Riley Park Date: Wed, 15 Aug 2018 01:26:09 -0700 Subject: [PATCH] Allow disabling armor stand ticking --- .../entity/decoration/ArmorStand.java.patch | 153 +++++++++++++++--- .../craftbukkit/entity/CraftArmorStand.java | 11 ++ 2 files changed, 138 insertions(+), 26 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/entity/decoration/ArmorStand.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/decoration/ArmorStand.java.patch index 5dbdef256f..84c2f2641d 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/decoration/ArmorStand.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/decoration/ArmorStand.java.patch @@ -31,15 +31,25 @@ public class ArmorStand extends LivingEntity { -@@ -101,6 +107,7 @@ +@@ -101,9 +107,17 @@ public Rotations rightArmPose; 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 type, Level world) { super(type, world); -@@ -123,7 +130,14 @@ ++ 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; +@@ -123,7 +137,14 @@ return createLivingAttributes().add(Attributes.STEP_HEIGHT, 0.0D); } @@ -54,7 +64,7 @@ public void refreshDimensions() { double d0 = this.getX(); double d1 = this.getY(); -@@ -165,7 +179,7 @@ +@@ -165,7 +186,7 @@ } @Override @@ -63,7 +73,7 @@ switch (slot.getType()) { case HAND: return (ItemStack) this.handItems.get(slot.getIndex()); -@@ -177,19 +191,26 @@ +@@ -177,21 +198,29 @@ } @Override @@ -96,8 +106,32 @@ + 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 } -@@ -327,6 +348,7 @@ + + @Override +@@ -227,6 +256,7 @@ + } + + nbt.put("Pose", this.writePose()); ++ if (this.canTickSetByAPI) nbt.putBoolean("Paper.CanTickOverride", this.canTick); // Paper - Allow ArmorStands not to tick + } + + @Override +@@ -261,6 +291,12 @@ + 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); +@@ -327,6 +363,7 @@ @Override protected void pushEntities() { @@ -105,7 +139,7 @@ List list = this.level().getEntities((Entity) this, this.getBoundingBox(), ArmorStand.RIDABLE_MINECARTS); Iterator iterator = list.iterator(); -@@ -341,7 +363,7 @@ +@@ -341,7 +378,7 @@ } @Override @@ -114,7 +148,7 @@ ItemStack itemstack = player.getItemInHand(hand); if (!this.isMarker() && !itemstack.is(Items.NAME_TAG)) { -@@ -350,11 +372,11 @@ +@@ -350,11 +387,11 @@ } else if (player.level().isClientSide) { return InteractionResult.SUCCESS_SERVER; } else { @@ -129,7 +163,7 @@ if (this.hasItemInSlot(enumitemslot2) && this.swapItem(player, enumitemslot2, itemstack, hand)) { return InteractionResult.SUCCESS_SERVER; -@@ -364,7 +386,7 @@ +@@ -364,7 +401,7 @@ return InteractionResult.FAIL; } @@ -138,7 +172,7 @@ return InteractionResult.FAIL; } -@@ -380,39 +402,57 @@ +@@ -380,39 +417,57 @@ } } @@ -212,7 +246,7 @@ this.setItemSlot(slot, stack.copyWithCount(1)); return true; } else if (!stack.isEmpty() && stack.getCount() > 1) { -@@ -427,6 +467,7 @@ +@@ -427,6 +482,7 @@ player.setItemInHand(hand, itemstack1); return true; } @@ -220,7 +254,7 @@ } @Override -@@ -436,12 +477,22 @@ +@@ -436,12 +492,22 @@ } else if (!world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && source.getEntity() instanceof Mob) { return false; } else if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { @@ -246,7 +280,7 @@ return false; } else if (source.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) { if (this.isOnFire()) { -@@ -463,8 +514,8 @@ +@@ -463,8 +529,8 @@ } else { Entity entity = source.getEntity(); @@ -257,7 +291,7 @@ if (!entityhuman.getAbilities().mayBuild) { return false; -@@ -474,7 +525,7 @@ +@@ -474,7 +540,7 @@ if (source.isCreativePlayer()) { this.playBrokenSound(); this.showBreakingParticles(); @@ -266,7 +300,7 @@ return true; } else { long i = world.getGameTime(); -@@ -486,7 +537,7 @@ +@@ -486,7 +552,7 @@ } else { this.brokenByPlayer(world, source); this.showBreakingParticles(); @@ -275,7 +309,7 @@ } return true; -@@ -536,7 +587,7 @@ +@@ -536,7 +602,7 @@ f1 -= amount; if (f1 <= 0.5F) { this.brokenByAnything(world, damageSource); @@ -284,7 +318,7 @@ } else { this.setHealth(f1); this.gameEvent(GameEvent.ENTITY_DAMAGE, damageSource.getEntity()); -@@ -548,13 +599,13 @@ +@@ -548,13 +614,13 @@ ItemStack itemstack = new ItemStack(Items.ARMOR_STAND); itemstack.set(DataComponents.CUSTOM_NAME, this.getCustomName()); @@ -300,7 +334,7 @@ ItemStack itemstack; int i; -@@ -562,7 +613,7 @@ +@@ -562,7 +628,7 @@ for (i = 0; i < this.handItems.size(); ++i) { itemstack = (ItemStack) this.handItems.get(i); if (!itemstack.isEmpty()) { @@ -309,7 +343,7 @@ this.handItems.set(i, ItemStack.EMPTY); } } -@@ -570,15 +621,16 @@ +@@ -570,15 +636,16 @@ for (i = 0; i < this.armorItems.size(); ++i) { itemstack = (ItemStack) this.armorItems.get(i); if (!itemstack.isEmpty()) { @@ -328,19 +362,48 @@ } @Override -@@ -663,10 +715,24 @@ - public boolean isBaby() { +@@ -609,7 +676,29 @@ + + @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)) { +@@ -664,9 +753,23 @@ return this.isSmall(); } -+ + + // CraftBukkit start -+ @Override + @Override + public boolean shouldDropExperience() { + return true; // MC-157395, SPIGOT-5193 even baby (small) armor stands should drop + } + // CraftBukkit end - - @Override ++ ++ @Override public void kill(ServerLevel world) { - this.remove(Entity.RemovalReason.KILLED); + // CraftBukkit start - pass DamageSource for kill @@ -354,7 +417,45 @@ this.gameEvent(GameEvent.ENTITY_DIE); } -@@ -788,7 +854,7 @@ +@@ -730,31 +833,37 @@ + 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() { +@@ -788,7 +897,7 @@ @Override public boolean skipAttackInteraction(Entity attacker) { @@ -363,7 +464,7 @@ } @Override -@@ -882,4 +948,13 @@ +@@ -882,4 +991,13 @@ public boolean canBeSeenByAnyone() { return !this.isInvisible() && !this.isMarker(); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java index 56fcd9dd40..1bb080a8af 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +++ b/paper-server/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 }