From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Ben Kerllenevich Date: Tue, 25 May 2021 16:31:09 -0400 Subject: [PATCH] API for any mob to burn daylight Co-authored by: Encode42 diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java index a812442edc8ef3f53b8e9a071a7e3e864314ae6d..e9fae59a2fffdd4b72e086d846beccf0a5265127 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 bf817c8cf1308a2621f387305b8d29af96a99f7f..b8c805694fae68ed2bcc5470d6ee53c2de6443ab 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -291,6 +291,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin public boolean silentDeath = false; // 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 type, final Level level) { @@ -788,6 +789,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); @@ -912,6 +914,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"); @@ -3915,6 +3918,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 7fe31c03780625ead30d4e629da4cca3bcf5b18c..6651a03adb5cb18db71d814b57d2d754497cc782 100644 --- a/net/minecraft/world/entity/Mob.java +++ b/net/minecraft/world/entity/Mob.java @@ -555,9 +555,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"); @@ -609,16 +609,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 586151b916a5e21c36578aa04cab9d71994dcf43..426b468ee821a7441d15dae3634032535cb60725 100644 --- a/net/minecraft/world/entity/animal/equine/ZombieHorse.java +++ b/net/minecraft/world/entity/animal/equine/ZombieHorse.java @@ -47,6 +47,7 @@ public class ZombieHorse extends AbstractHorse { public ZombieHorse(final EntityType 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 18bfb321e3728d3fa0596da0b86e4b76ced2178a..ab97449bfa5e8b5615e0f2b6b16be2fe7e4233fd 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 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 20096d8305bbfc29195834b87245c94096986ec8..6b6eed1c636f2ca65d0cbcd71e96bdd1b2063267 100644 --- a/net/minecraft/world/entity/monster/Phantom.java +++ b/net/minecraft/world/entity/monster/Phantom.java @@ -53,7 +53,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 @@ -62,6 +62,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 @@ -298,7 +299,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 } @@ -309,7 +310,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 32da5212c85c829eeedc9d0f7904bbcaa3ce5ed3..062c7f20e73b882ef0550d90e3da47ac39a1b3a7 100644 --- a/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java +++ b/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java @@ -71,11 +71,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 type, final Level level) { super(type, level); this.reassessWeaponGoal(); + this.setShouldBurnInDay(true); // Purpur - API for any mob to burn daylight } @Override @@ -228,7 +229,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 @@ -254,7 +255,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 36348e59c278e8842330e685340820c2ac9205eb..b14ea9e0f3de832fb73ae51728607486e399120b 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 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 8d6262e99fb3ad98d3142ee069f07d2370ca0778..02e935edd7a6cabbf2e6fcc6c96a9601bee71acc 100644 --- a/net/minecraft/world/entity/monster/zombie/Husk.java +++ b/net/minecraft/world/entity/monster/zombie/Husk.java @@ -35,6 +35,7 @@ public class Husk extends Zombie { public Husk(final EntityType type, final Level level) { super(type, level); + this.setShouldBurnInDay(false); // Purpur - API for any mob to burn daylight } // Purpur start - Ridables @@ -92,7 +93,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 6693ae88aa5780189faba8649346579f5b95b77e..f8eccfab70e7d99dd74965a506837e620515b6d1 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 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(EntityType.ZOMBIE)))); // Paper - Configurable door breaking difficulty + this.setShouldBurnInDay(true); // Purpur - API for any mob to burn daylight } public Zombie(final Level level) { @@ -364,6 +365,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 } @@ -505,7 +507,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 @@ -520,7 +522,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