From c7648eb04e95783a7ae279aaf69e5b24ca3c56f9 Mon Sep 17 00:00:00 2001 From: CraftBukkit/Spigot Date: Mon, 20 Mar 2023 19:03:53 +1100 Subject: [PATCH] #1150: Add Sniffer API and handle EntityItemDropEvent By: Doc --- .../world/entity/animal/sniffer/Sniffer.patch | 55 ++++++++++++- .../craftbukkit/entity/CraftSniffer.java | 77 +++++++++++++++++++ 2 files changed, 130 insertions(+), 2 deletions(-) diff --git a/paper-server/nms-patches/net/minecraft/world/entity/animal/sniffer/Sniffer.patch b/paper-server/nms-patches/net/minecraft/world/entity/animal/sniffer/Sniffer.patch index 8c881f8e6a..975f797b33 100644 --- a/paper-server/nms-patches/net/minecraft/world/entity/animal/sniffer/Sniffer.patch +++ b/paper-server/nms-patches/net/minecraft/world/entity/animal/sniffer/Sniffer.patch @@ -24,7 +24,53 @@ @Override protected float getStandingEyeHeight(EntityPose entitypose, EntitySize entitysize) { return this.getDimensions(entitypose).height * 0.6F; -@@ -278,7 +287,7 @@ +@@ -114,7 +123,7 @@ + return BlockPosition.containing(vec3d.x(), this.getY(), vec3d.z()); + } + +- private Sniffer.a getState() { ++ public Sniffer.a getState() { // PAIL private -> public + return (Sniffer.a) this.entityData.get(Sniffer.DATA_STATE); + } + +@@ -207,7 +216,7 @@ + return this; + } + +- Optional calculateDigPosition() { ++ public Optional calculateDigPosition() { // PAIL public + return IntStream.range(0, 5).mapToObj((i) -> { + return LandRandomPos.getPos(this, 10 + 2 * i, 3); + }).filter(Objects::nonNull).map(BlockPosition::containing).map(BlockPosition::below).filter(this::canDig).findFirst(); +@@ -218,7 +227,7 @@ + return false; + } + +- boolean canDig() { ++ public boolean canDig() { // PAIL public + return !this.isPanicking() && !this.isBaby() && !this.isInWater() && this.canDig(this.getHeadPosition().below()); + } + +@@ -245,6 +254,13 @@ + BlockPosition blockposition = this.getHeadPosition(); + EntityItem entityitem = new EntityItem(this.level, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack); + ++ // CraftBukkit start - handle EntityDropItemEvent ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + entityitem.setDefaultPickUpDelay(); + this.level.addFreshEntity(entityitem); + this.playSound(SoundEffects.SNIFFER_DROP_SEED, 1.0F, 1.0F); +@@ -274,15 +290,15 @@ + return this; + } + +- private Sniffer storeExploredPosition(BlockPosition blockposition) { ++ public Sniffer storeExploredPosition(BlockPosition blockposition) { // PAIL private -> public List list = (List) this.getExploredPositions().limit(20L).collect(Collectors.toList()); list.add(0, blockposition); @@ -33,7 +79,12 @@ return this; } -@@ -416,7 +425,7 @@ +- private Stream getExploredPositions() { ++ public Stream getExploredPositions() { // PAIL private -> public + return this.getBrain().getMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS).stream().flatMap(Collection::stream); + } + +@@ -416,7 +432,7 @@ @Override public BehaviorController getBrain() { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java index 92d1c7943c..9b94b43432 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java @@ -1,5 +1,11 @@ package org.bukkit.craftbukkit.entity; +import com.google.common.base.Preconditions; +import java.util.Collection; +import java.util.stream.Collectors; +import net.minecraft.core.BlockPosition; +import net.minecraft.world.entity.ai.memory.MemoryModuleType; +import org.bukkit.Location; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.EntityType; import org.bukkit.entity.Sniffer; @@ -24,4 +30,75 @@ public class CraftSniffer extends CraftAnimals implements Sniffer { public EntityType getType() { return EntityType.SNIFFER; } + + @Override + public Collection getExploredLocations() { + return this.getHandle().getExploredPositions().map(blockPosition -> new Location(this.getLocation().getWorld(), blockPosition.getX(), blockPosition.getY(), blockPosition.getZ())).collect(Collectors.toList()); + } + + @Override + public void removeExploredLocation(Location location) { + Preconditions.checkArgument(location != null, "location cannot be null"); + if (location.getWorld() != getWorld()) { + return; + } + + BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + this.getHandle().getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, this.getHandle().getExploredPositions().filter(blockPositionExplored -> !blockPositionExplored.equals(blockPosition)).collect(Collectors.toList())); + } + + @Override + public void addExploredLocation(Location location) { + Preconditions.checkArgument(location != null, "location cannot be null"); + if (location.getWorld() != getWorld()) { + return; + } + + this.getHandle().storeExploredPosition(new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ())); + } + + @Override + public Sniffer.State getState() { + return this.stateToBukkit(this.getHandle().getState()); + } + + @Override + public void setState(Sniffer.State state) { + Preconditions.checkArgument(state != null, "state cannot be null"); + this.getHandle().transitionTo(this.stateToNMS(state)); + } + + @Override + public Location findPossibleDigLocation() { + return this.getHandle().calculateDigPosition().map(blockPosition -> new Location(this.getLocation().getWorld(), blockPosition.getX(), blockPosition.getY(), blockPosition.getZ())).orElse(null); + } + + @Override + public boolean canDig() { + return this.getHandle().canDig(); + } + + private net.minecraft.world.entity.animal.sniffer.Sniffer.a stateToNMS(Sniffer.State state) { + return switch (state) { + case IDLING -> net.minecraft.world.entity.animal.sniffer.Sniffer.a.IDLING; + case FEELING_HAPPY -> net.minecraft.world.entity.animal.sniffer.Sniffer.a.FEELING_HAPPY; + case SCENTING -> net.minecraft.world.entity.animal.sniffer.Sniffer.a.SCENTING; + case SNIFFING -> net.minecraft.world.entity.animal.sniffer.Sniffer.a.SNIFFING; + case SEARCHING -> net.minecraft.world.entity.animal.sniffer.Sniffer.a.SEARCHING; + case DIGGING -> net.minecraft.world.entity.animal.sniffer.Sniffer.a.DIGGING; + case RISING -> net.minecraft.world.entity.animal.sniffer.Sniffer.a.RISING; + }; + } + + private Sniffer.State stateToBukkit(net.minecraft.world.entity.animal.sniffer.Sniffer.a state) { + return switch (state) { + case IDLING -> Sniffer.State.IDLING; + case FEELING_HAPPY -> Sniffer.State.FEELING_HAPPY; + case SCENTING -> Sniffer.State.SCENTING; + case SNIFFING -> Sniffer.State.SNIFFING; + case SEARCHING -> Sniffer.State.SEARCHING; + case DIGGING -> Sniffer.State.DIGGING; + case RISING -> Sniffer.State.RISING; + }; + } }