Minimise EntityFertilizeEggEvent and add sniffer (#9280)

This commit is contained in:
Bjarne Koll 2023-06-09 09:01:08 +02:00
parent 0bd83b4c4d
commit 3553730d51
2 changed files with 98 additions and 23 deletions

View file

@ -23,8 +23,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Called when a mating occurs that results in a pregnancy.
+ * After a bit of time, the mother will lay an egg.
+ * Called when two entities mate and the mating process results in a fertilization.
+ * Fertilization differs from normal breeding, as represented by the {@link org.bukkit.event.entity.EntityBreedEvent}, as
+ * it does not result in the immediate creation of the child entity in the world.
+ * <p>
+ * An example of this would be:
+ * <ul>
+ * <li>A frog being marked as "is_pregnant" and laying {@link org.bukkit.Material#FROGSPAWN} later.</li>
+ * <li>Sniffers producing the {@link org.bukkit.Material#SNIFFER_EGG} item, which needs to be placed before it can begin to hatch.</li>
+ * <li>A turtle being marked with "HasEgg" and laying a {@link org.bukkit.Material#TURTLE_EGG} later.</li>
+ * </ul>
+ *
+ * The event hence only exposes the two parent entities in the fertilization process and cannot provide the child entity, as it will only exist at a later point in time.
+ */
+public class EntityFertilizeEggEvent extends EntityEvent implements Cancellable {
+
@ -58,9 +68,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ /**
+ * Gets the parent creating this entity.
+ * Provides the entity in the fertilization process that will eventually be responsible for "creating" offspring,
+ * may that be by setting a block that later hatches or dropping an egg that has to be placed.
+ *
+ * @return The "birth" parent
+ * @return The "mother" entity.
+ */
+ @NotNull
+ public LivingEntity getMother() {
@ -68,7 +79,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ /**
+ * Gets the other parent of the newly born entity.
+ * Provides the "father" entity in the fertilization process that is not responsible for initiating the offspring
+ * creation.
+ *
+ * @return the other parent
+ */

View file

@ -12,30 +12,93 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (entityplayer == null && this.partner.getLoveCause() != null) {
entityplayer = this.partner.getLoveCause();
}
+ // Paper start
+ RandomSource randomsource = this.animal.getRandom();
+ int experience = randomsource.nextInt(7) + 1;
+ io.papermc.paper.event.entity.EntityFertilizeEggEvent event = new io.papermc.paper.event.entity.EntityFertilizeEggEvent((org.bukkit.entity.LivingEntity) turtle.getBukkitEntity(), (org.bukkit.entity.LivingEntity) partner.getBukkitEntity(), entityplayer == null ? null : entityplayer.getBukkitEntity(), turtle.breedItem == null ? null : org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(turtle.breedItem).clone(), experience);
+ if (!event.callEvent()) {
+ animal.resetLove();
+ partner.resetLove(); // stop the pathfinding to avoid infinite loop
+ return;
+ }
+ experience = event.getExperience();
+ // Paper end
+ // Paper start - Add EntityFertilizeEggEvent event
+ io.papermc.paper.event.entity.EntityFertilizeEggEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this.animal, this.partner);
+ if (event.isCancelled()) return;
+ // Paper end - Add EntityFertilizeEggEvent event
if (entityplayer != null) {
entityplayer.awardStat(Stats.ANIMALS_BRED);
@@ -0,0 +0,0 @@ public class Turtle extends Animal {
this.partner.setAge(6000);
this.animal.resetLove();
this.partner.resetLove();
- RandomSource randomsource = this.animal.getRandom();
RandomSource randomsource = this.animal.getRandom();
- if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomsource.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper;
+ if (experience > 0 && this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper
+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper
+ if(event.getExperience() > 0) this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), event.getExperience(), org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper - Add EntityFertilizeEggEvent event
}
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
+++ b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
@@ -0,0 +0,0 @@ public class Frog extends Animal implements VariantHolder<FrogVariant> {
@Override
public void spawnChildFromBreeding(ServerLevel world, Animal other) {
- this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob)null);
+ // Paper start - Add EntityFertilizeEggEvent event
+ final io.papermc.paper.event.entity.EntityFertilizeEggEvent result = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this, other);
+ if (result.isCancelled()) return;
+
+ this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob)null, result.getExperience()); // Paper - use craftbukkit call that takes experience amount
+ // Paper end - Add EntityFertilizeEggEvent event
this.getBrain().setMemory(MemoryModuleType.IS_PREGNANT, Unit.INSTANCE);
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java b/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java
+++ b/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java
@@ -0,0 +0,0 @@ public class Sniffer extends Animal {
@Override
public void spawnChildFromBreeding(ServerLevel world, Animal other) {
+ // Paper start - Add EntityFertilizeEggEvent event
+ final io.papermc.paper.event.entity.EntityFertilizeEggEvent result = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this, other);
+ if (result.isCancelled()) return;
+ // Paper end - Add EntityFertilizeEggEvent event
+
ItemStack itemstack = new ItemStack(Items.SNIFFER_EGG);
ItemEntity entityitem = new ItemEntity(world, this.position().x(), this.position().y(), this.position().z(), itemstack);
entityitem.setDefaultPickUpDelay();
- this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob) null);
+ this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob) null, result.getExperience()); // Paper - Add EntityFertilizeEggEvent event
this.playSound(SoundEvents.SNIFFER_EGG_PLOP, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 0.5F);
world.addFreshEntity(entityitem);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -0,0 +0,0 @@ public class CraftEventFactory {
return event.callEvent();
}
// Paper end
+
+ // Paper start - add EntityFertilizeEggEvent
+ /**
+ * Calls the io.papermc.paper.event.entity.EntityFertilizeEggEvent.
+ * If the event is cancelled, this method also resets the love on both the {@code breeding} and {@code other} entity.
+ *
+ * @param breeding the entity on which #spawnChildFromBreeding was called.
+ * @param other the partner of the entity.
+ * @return the event after it was called. The instance may be used to retrieve the experience of the event.
+ */
+ public static io.papermc.paper.event.entity.EntityFertilizeEggEvent callEntityFertilizeEggEvent(net.minecraft.world.entity.animal.Animal breeding,
+ net.minecraft.world.entity.animal.Animal other) {
+ net.minecraft.server.level.ServerPlayer serverPlayer = breeding.getLoveCause();
+ if (serverPlayer == null) serverPlayer = other.getLoveCause();
+ final int experience = breeding.getRandom().nextInt(7) + 1; // From Animal#spawnChildFromBreeding(ServerLevel, Animal)
+
+ final io.papermc.paper.event.entity.EntityFertilizeEggEvent event = new io.papermc.paper.event.entity.EntityFertilizeEggEvent((org.bukkit.entity.LivingEntity) breeding.getBukkitEntity(), (org.bukkit.entity.LivingEntity) other.getBukkitEntity(), serverPlayer == null ? null : serverPlayer.getBukkitEntity(), breeding.breedItem == null ? null : org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(breeding.breedItem).clone(), experience);
+ if (!event.callEvent()) {
+ breeding.resetLove();
+ other.resetLove(); // stop the pathfinding to avoid infinite loop
+ }
+
+ return event;
+ }
+ // Paper end - add EntityFertilizeEggEvent
}