Files
Purpur/purpur-server/minecraft-patches/features/0017-API-for-any-mob-to-burn-daylight.patch
granny 0c913568e6 Updated Upstream (Paper)
Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@7b66699b 26.2-rc-2
PaperMC/Paper@bb676e22 actual 26.2-rc-2
PaperMC/Paper@a737972b Fix isAllowedInPeaceful call
PaperMC/Paper@c35810c3 Update deps to match Vanilla
PaperMC/Paper@e5643cd4 Update Vex#getSummoner return type
PaperMC/Paper@e00936a3 [ci/skip] update log4j for the api
PaperMC/Paper@eb5df78f fix wither spawning parity and remove openSign var
PaperMC/Paper@d1aca9a6 Apply most remaining feature patches
2026-06-12 17:36:00 -07:00

311 lines
18 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ben Kerllenevich <ben@omega24.dev>
Date: Tue, 25 May 2021 16:31:09 -0400
Subject: [PATCH] API for any mob to burn daylight
Co-authored by: Encode42 <me@encode42.dev>
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 8ca29762d465ba8ebeaa450bd6e1c4f77db5464c..0f5961a9fb49dbd77b682cf922cc14be48fe3397 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -558,6 +558,21 @@ public abstract class Entity
}
// Purpur end - Add canSaveToDisk to Entity
+ // Purpur start - copied from Mob - API for any mob to burn daylight
+ public boolean isSunBurnTick() {
+ if (!this.level().isClientSide() && this.level().environmentAttributes().getValue(EnvironmentAttributes.MONSTERS_BURN, this.position())) {
+ float br = this.getLightLevelDependentMagicValue();
+ BlockPos roundedPos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ());
+ boolean isInNonBurnableBlock = this.isInWaterOrRain() || this.isInPowderSnow || this.wasInPowderSnow;
+ if (br > 0.5F && this.random.nextFloat() * 30.0F < (br - 0.4F) * 2.0F && !isInNonBurnableBlock && this.level().canSeeSky(roundedPos)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ // Purpur end - copied from Mob - API for any mob to burn daylight
+
public Entity(final EntityType<?> type, final Level level) {
this.type = type;
this.level = level;
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 166c8d92937d534646d7a7521529d30afaa6f618..82705d97a520ffd6b4b4a1e5c7bf5439d93bf269 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -305,6 +305,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
public boolean silentDeath = true; // Paper - mark entity as dying silently for cancellable death event
public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
public int invulnerableDuration = LivingEntity.INVULNERABLE_DURATION; // Paper - configurable invulnerable duration
+ protected boolean shouldBurnInDay = false; public boolean shouldBurnInDay() { return this.shouldBurnInDay; } public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } // Purpur - API for any mob to burn daylight
// CraftBukkit end
protected LivingEntity(final EntityType<? extends LivingEntity> type, final Level level) {
@@ -810,6 +811,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
output.putBoolean("FallFlying", this.isFallFlying());
this.getSleepingPos().ifPresent(sleepingPos -> output.store("sleeping_pos", BlockPos.CODEC, sleepingPos));
output.store("Brain", Brain.Packed.CODEC, this.brain.pack());
+ output.putBoolean("Purpur.ShouldBurnInDay", this.shouldBurnInDay); // Purpur - API for any mob to burn daylight
if (this.lastHurtByPlayer != null) {
this.lastHurtByPlayer.store(output, "last_hurt_by_player");
output.putInt("last_hurt_by_player_memory_time", this.lastHurtByPlayerMemoryTime);
@@ -935,6 +937,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
} // Paper - The sleeping pos will always also set the actual pos, so a desync suggests something is wrong
}, this::clearSleepingPos);
input.read("Brain", Brain.Packed.CODEC).ifPresent(packedBrain -> this.brain = this.makeBrain(packedBrain));
+ this.shouldBurnInDay = input.getBooleanOr("Purpur.ShouldBurnInDay", this.shouldBurnInDay); // Purpur - API for any mob to burn daylight
this.lastHurtByPlayer = EntityReference.read(input, "last_hurt_by_player");
this.lastHurtByPlayerMemoryTime = input.getIntOr("last_hurt_by_player_memory_time", 0);
this.lastHurtByMob = EntityReference.read(input, "last_hurt_by_mob");
@@ -3938,6 +3941,37 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
if (this.level() instanceof ServerLevel serverLevel && this.isSensitiveToWater() && this.isInWaterOrRain()) {
this.hurtServer(serverLevel, this.damageSources().drown(), 1.0F);
}
+
+ // Purpur start - copied from Mob - API for any mob to burn daylight
+ if (this.isAlive()) {
+ boolean flag = this.shouldBurnInDay() && this.isSunBurnTick(); // Paper - shouldBurnInDay API // Purpur - use shouldBurnInDay() method to handle Phantoms properly - API for any mob to burn daylight
+ if (flag) {
+ EquipmentSlot equipmentSlot = this.sunProtectionSlot();
+ ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
+ if (!itemBySlot.isEmpty()) {
+ if (itemBySlot.isDamageableItem()) {
+ Item item = itemBySlot.getItem();
+ itemBySlot.setDamageValue(itemBySlot.getDamageValue() + this.random.nextInt(2));
+ if (itemBySlot.getDamageValue() >= itemBySlot.getMaxDamage()) {
+ this.onEquippedItemBroken(item, equipmentSlot);
+ this.setItemSlot(equipmentSlot, ItemStack.EMPTY);
+ }
+ }
+
+ flag = false;
+ }
+
+ if (flag) {
+ if (getRider() == null || !this.isControllable()) // Purpur - ignore mobs which are uncontrollable or without rider - API for any mob to burn daylight
+ this.igniteForSeconds(8.0F);
+ }
+ }
+ }
+ }
+
+ protected EquipmentSlot sunProtectionSlot() {
+ return net.minecraft.world.entity.EquipmentSlot.HEAD;
+ // Purpur end - copied from Mob - API for any mob to burn daylight
}
protected void applyInput() {
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
index 460ba9d3a192c5f17a1b5c4682bbbba3d2f8ebe2..00353f1668e4fb3d97c57175a5f141d6a39d70f7 100644
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -561,9 +561,9 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
@Override
public void aiStep() {
super.aiStep();
- if (this.is(EntityTypeTags.BURN_IN_DAYLIGHT)) {
+ /*if (this.is(EntityTypeTags.BURN_IN_DAYLIGHT)) { // Purpur start - implemented in LivingEntity - API for any mob to burn daylight
this.burnUndead();
- }
+ }*/ // Purpur end - implemented in LivingEntity - API for any mob to burn daylight
ProfilerFiller profiler = Profiler.get();
profiler.push("looting");
@@ -615,16 +615,8 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
}
public boolean isSunBurnTick() {
- if (!this.level().isClientSide() && this.level().environmentAttributes().getValue(EnvironmentAttributes.MONSTERS_BURN, this.position())) {
- float br = this.getLightLevelDependentMagicValue();
- BlockPos roundedPos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ());
- boolean isInNonBurnableBlock = this.isInWaterOrRain() || this.isInPowderSnow || this.wasInPowderSnow;
- if (br > 0.5F && this.random.nextFloat() * 30.0F < (br - 0.4F) * 2.0F && !isInNonBurnableBlock && this.level().canSeeSky(roundedPos)) {
- return true;
- }
- }
-
- return false;
+ // Purpur - implemented in Entity - API for any mob to burn daylight
+ return super.isSunBurnTick();
}
protected Vec3i getPickupReach() {
diff --git a/net/minecraft/world/entity/animal/equine/ZombieHorse.java b/net/minecraft/world/entity/animal/equine/ZombieHorse.java
index 9deb8e249830aea4bbc230f26eb192479eec0c4e..9c8ce7eee6bf462478a0755b074e229133eee1c3 100644
--- a/net/minecraft/world/entity/animal/equine/ZombieHorse.java
+++ b/net/minecraft/world/entity/animal/equine/ZombieHorse.java
@@ -48,6 +48,7 @@ public class ZombieHorse extends AbstractHorse {
public ZombieHorse(final EntityType<? extends ZombieHorse> type, final Level level) {
super(type, level);
+ this.setShouldBurnInDay(true); // Purpur - API for any mob to burn daylight
}
// Purpur start - Ridables
diff --git a/net/minecraft/world/entity/animal/nautilus/ZombieNautilus.java b/net/minecraft/world/entity/animal/nautilus/ZombieNautilus.java
index 55b4a41867799dcb2999f0c324bde8b2341b2e9d..da60906faaca79efbfd29ed05b01a0c07978bab2 100644
--- a/net/minecraft/world/entity/animal/nautilus/ZombieNautilus.java
+++ b/net/minecraft/world/entity/animal/nautilus/ZombieNautilus.java
@@ -46,6 +46,7 @@ public class ZombieNautilus extends AbstractNautilus {
public ZombieNautilus(final EntityType<? extends ZombieNautilus> type, final Level level) {
super(type, level);
+ this.setShouldBurnInDay(true); // Purpur - API for any mob to burn daylight
}
// Purpur start - Configurable entity base attributes
diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java
index 7c1aad8b5f9625d757039cb636783cb760aa87e0..9d646f3d924d3c2fdb2b396e4501111912fba043 100644
--- a/net/minecraft/world/entity/monster/Phantom.java
+++ b/net/minecraft/world/entity/monster/Phantom.java
@@ -52,7 +52,7 @@ public class Phantom extends Mob implements Enemy {
Vec3 crystalPosition; // Purpur - Phantoms attracted to crystals and crystals shoot phantoms
// Paper start
public java.util.@Nullable UUID spawningEntity;
- public boolean shouldBurnInDay = true;
+ //public boolean shouldBurnInDay = true; // Purpur - API for any mob to burn daylight
// Paper end
private static final net.minecraft.world.item.crafting.Ingredient TORCH = net.minecraft.world.item.crafting.Ingredient.of(net.minecraft.world.item.Items.TORCH, net.minecraft.world.item.Items.SOUL_TORCH); // Purpur - Phantoms burn in light
@@ -61,6 +61,7 @@ public class Phantom extends Mob implements Enemy {
this.xpReward = 5;
this.moveControl = new Phantom.PhantomMoveControl<>(this);
this.lookControl = new Phantom.PhantomLookControl(this);
+ this.setShouldBurnInDay(true); // Purpur - API for any mob to burn daylight
}
// Purpur start - Ridables
@@ -297,7 +298,7 @@ public class Phantom extends Mob implements Enemy {
this.setPhantomSize(input.getIntOr("size", 0));
// Paper start
this.spawningEntity = input.read("Paper.SpawningEntity", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
- this.shouldBurnInDay = input.getBooleanOr("Paper.ShouldBurnInDay", true);
+ //this.shouldBurnInDay = input.getBooleanOr("Paper.ShouldBurnInDay", true); // Purpur - implemented in LivingEntity - API for any mob to burn daylight
// Paper end
}
@@ -308,7 +309,7 @@ public class Phantom extends Mob implements Enemy {
output.putInt("size", this.getPhantomSize());
// Paper start
output.storeNullable("Paper.SpawningEntity", net.minecraft.core.UUIDUtil.CODEC, this.spawningEntity);
- output.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay);
+ //output.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Purpur - implemented in LivingEntity - API for any mob to burn daylight
// Paper end
}
diff --git a/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java b/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
index 3294aca7cb32d5cf9bbc7c2c99a538eb00fc3dcc..8f30f9f0f12e5fd6ddcb1809195f0823ea3ebd51 100644
--- a/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
+++ b/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
@@ -66,11 +66,12 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
AbstractSkeleton.this.setAggressive(true);
}
};
- private boolean shouldBurnInDay = true; // Paper - shouldBurnInDay API
+ //private boolean shouldBurnInDay = true; // Paper - shouldBurnInDay API // Purpur - moved to LivingEntity; keep methods for ABI compatibility - API for any mob to burn daylight
protected AbstractSkeleton(final EntityType<? extends AbstractSkeleton> type, final Level level) {
super(type, level);
this.reassessWeaponGoal();
+ this.setShouldBurnInDay(true); // Purpur - API for any mob to burn daylight
}
@Override
@@ -223,7 +224,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
protected void readAdditionalSaveData(final ValueInput input) {
super.readAdditionalSaveData(input);
this.reassessWeaponGoal();
- this.shouldBurnInDay = input.getBooleanOr("Paper.ShouldBurnInDay", true); // Paper - shouldBurnInDay API
+ //this.shouldBurnInDay = input.getBooleanOr("Paper.ShouldBurnInDay", true); // Paper - shouldBurnInDay API // Purpur - implemented in LivingEntity - API for any mob to burn daylight
}
// Paper start - silent equipping
@@ -249,7 +250,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
@Override
protected void addAdditionalSaveData(final net.minecraft.world.level.storage.ValueOutput output) {
super.addAdditionalSaveData(output);
- output.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay);
+ //output.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Purpur - implemented in LivingEntity - API for any mob to burn daylight
}
// Paper end - shouldBurnInDay API
}
diff --git a/net/minecraft/world/entity/monster/skeleton/Parched.java b/net/minecraft/world/entity/monster/skeleton/Parched.java
index 986caff5325830c6d3eb0f6927c3294ae8b9ebe0..ed121e0b32a791ade0126edc627a96f713bc30d4 100644
--- a/net/minecraft/world/entity/monster/skeleton/Parched.java
+++ b/net/minecraft/world/entity/monster/skeleton/Parched.java
@@ -17,6 +17,7 @@ import org.jspecify.annotations.Nullable;
public class Parched extends AbstractSkeleton {
public Parched(final EntityType<? extends AbstractSkeleton> type, final Level level) {
super(type, level);
+ this.setShouldBurnInDay(false); // Purpur - API for any mob to burn daylight
}
@Override
diff --git a/net/minecraft/world/entity/monster/zombie/Husk.java b/net/minecraft/world/entity/monster/zombie/Husk.java
index 83c2d21587fc490eb7eb60c43a21da73f144140c..afca08cfa58a25a7fa257eebf66dd888ccc1c734 100644
--- a/net/minecraft/world/entity/monster/zombie/Husk.java
+++ b/net/minecraft/world/entity/monster/zombie/Husk.java
@@ -36,6 +36,7 @@ public class Husk extends Zombie {
public Husk(final EntityType<? extends Husk> type, final Level level) {
super(type, level);
+ this.setShouldBurnInDay(false); // Purpur - API for any mob to burn daylight
}
// Purpur start - Ridables
@@ -93,7 +94,7 @@ public class Husk extends Zombie {
@Override
public boolean isSunSensitive() {
- return false;
+ return this.shouldBurnInDay; // Purpur - moved to LivingEntity; keep methods for ABI compatibility - API for any mob to burn daylight
}
@Override
diff --git a/net/minecraft/world/entity/monster/zombie/Zombie.java b/net/minecraft/world/entity/monster/zombie/Zombie.java
index 26f0ac03eaa3d33fa593ce65bc944872864a66a9..f104394d49989fe80462602cb06b2f58c4282fbb 100644
--- a/net/minecraft/world/entity/monster/zombie/Zombie.java
+++ b/net/minecraft/world/entity/monster/zombie/Zombie.java
@@ -102,11 +102,12 @@ public class Zombie extends Monster {
private boolean canBreakDoors = false;
private int inWaterTime = 0;
public int conversionTime;
- private boolean shouldBurnInDay = true; // Paper - Add more Zombie API
+ //private boolean shouldBurnInDay = true; // Paper - Add more Zombie API // Purpur - implemented in LivingEntity - API for any mob to burn daylight
public Zombie(final EntityType<? extends Zombie> type, final Level level) {
super(type, level);
this.breakDoorGoal = new BreakDoorGoal(this, com.google.common.base.Predicates.in(level.paperConfig().entities.behavior.doorBreakingDifficulty.getOrDefault(type, level.paperConfig().entities.behavior.doorBreakingDifficulty.get(EntityTypes.ZOMBIE)))); // Paper - Configurable door breaking difficulty
+ this.setShouldBurnInDay(true); // Purpur - API for any mob to burn daylight
}
public Zombie(final Level level) {
@@ -365,6 +366,7 @@ public class Zombie extends Monster {
// CraftBukkit end
}
+ public boolean shouldBurnInDay() { return this.isSunSensitive(); } // Purpur - for ABI compatibility - API for any mob to burn daylight
public boolean isSunSensitive() {
return this.shouldBurnInDay; // Paper - Add more Zombie API
}
@@ -504,7 +506,7 @@ public class Zombie extends Monster {
output.putBoolean("CanBreakDoors", this.canBreakDoors());
output.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1);
output.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1);
- output.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Paper - Add more Zombie API
+ //output.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Paper - Add more Zombie API // Purpur - implemented in LivingEntity - API for any mob to burn daylight
}
@Override
@@ -519,7 +521,7 @@ public class Zombie extends Monster {
} else {
this.getEntityData().set(DATA_DROWNED_CONVERSION_ID, false);
}
- this.shouldBurnInDay = input.getBooleanOr("Paper.ShouldBurnInDay", true); // Paper - Add more Zombie API
+ //this.shouldBurnInDay = input.getBooleanOr("Paper.ShouldBurnInDay", true); // Paper - Add more Zombie API // Purpur - implemented in LivingEntity - API for any mob to burn daylight
}
@Override