More entity classes
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
--- a/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/net/minecraft/world/entity/EntityType.java
|
||||
@@ -176,6 +_,7 @@
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
+import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class EntityType<T extends Entity> implements FeatureElement, EntityTypeTest<Entity, T> {
|
||||
@@ -215,7 +_,7 @@
|
||||
.fireImmune()
|
||||
.sized(6.0F, 0.5F)
|
||||
.clientTrackingRange(10)
|
||||
- .updateInterval(Integer.MAX_VALUE)
|
||||
+ .updateInterval(10) // CraftBukkit - SPIGOT-3729: track area effect clouds
|
||||
);
|
||||
public static final EntityType<Armadillo> ARMADILLO = register(
|
||||
"armadillo", EntityType.Builder.of(Armadillo::new, MobCategory.CREATURE).sized(0.7F, 0.65F).eyeHeight(0.26F).clientTrackingRange(10)
|
||||
@@ -1132,6 +_,22 @@
|
||||
boolean shouldOffsetY,
|
||||
boolean shouldOffsetYMore
|
||||
) {
|
||||
+ // CraftBukkit start
|
||||
+ return this.spawn(level, spawnedFrom, player, pos, reason, shouldOffsetY, shouldOffsetYMore, reason == EntitySpawnReason.DISPENSER ? org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DISPENSE_EGG : org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // Paper - use correct spawn reason for dispenser spawn eggs
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public T spawn(
|
||||
+ ServerLevel level,
|
||||
+ @Nullable ItemStack spawnedFrom,
|
||||
+ @Nullable Player player,
|
||||
+ BlockPos pos,
|
||||
+ EntitySpawnReason reason,
|
||||
+ boolean shouldOffsetY,
|
||||
+ boolean shouldOffsetYMore,
|
||||
+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason createSpawnReason
|
||||
+ ) {
|
||||
+ // CraftBukkit end
|
||||
Consumer<T> consumer;
|
||||
if (spawnedFrom != null) {
|
||||
consumer = createDefaultStackConfig(level, spawnedFrom, player);
|
||||
@@ -1139,7 +_,7 @@
|
||||
consumer = entity -> {};
|
||||
}
|
||||
|
||||
- return this.spawn(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore);
|
||||
+ return this.spawn(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore, createSpawnReason); // CraftBukkit
|
||||
}
|
||||
|
||||
public static <T extends Entity> Consumer<T> createDefaultStackConfig(Level level, ItemStack spawnedFrom, @Nullable Player player) {
|
||||
@@ -1159,19 +_,54 @@
|
||||
Consumer<T> consumer, Level level, ItemStack spawnedFrom, @Nullable Player player
|
||||
) {
|
||||
CustomData customData = spawnedFrom.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY);
|
||||
- return !customData.isEmpty() ? consumer.andThen(entity -> updateCustomEntityTag(level, player, entity, customData)) : consumer;
|
||||
+ // CraftBukkit start - SPIGOT-5665
|
||||
+ return !customData.isEmpty() ? consumer.andThen(entity -> {
|
||||
+ try {
|
||||
+ updateCustomEntityTag(level, player, entity, customData);
|
||||
+ } catch (Throwable t) {
|
||||
+ EntityType.LOGGER.warn("Error loading spawn egg NBT", t);
|
||||
+ }
|
||||
+ }) : consumer;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T spawn(ServerLevel level, BlockPos pos, EntitySpawnReason reason) {
|
||||
- return this.spawn(level, null, pos, reason, false, false);
|
||||
+ // CraftBukkit start
|
||||
+ return this.spawn(level, pos, reason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ }
|
||||
+ @Nullable
|
||||
+ public T spawn(ServerLevel level, BlockPos pos, EntitySpawnReason reason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason creatureSpawnReason) {
|
||||
+ return this.spawn(level, null, pos, reason, false, false, creatureSpawnReason);
|
||||
+ // CraftBukkit End
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T spawn(ServerLevel level, @Nullable Consumer<T> consumer, BlockPos pos, EntitySpawnReason reason, boolean shouldOffsetY, boolean shouldOffsetYMore) {
|
||||
+ // CraftBukkit start
|
||||
+ return this.spawn(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ }
|
||||
+ @Nullable
|
||||
+ public T spawn(ServerLevel level, @Nullable Consumer<T> consumer, BlockPos pos, EntitySpawnReason reason, boolean shouldOffsetY, boolean shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason creatureSpawnReason) {
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start - PreCreatureSpawnEvent
|
||||
+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ io.papermc.paper.util.MCUtil.toLocation(level, pos),
|
||||
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(this),
|
||||
+ creatureSpawnReason
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end - PreCreatureSpawnEvent
|
||||
T entity = this.create(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore);
|
||||
if (entity != null) {
|
||||
- level.addFreshEntityWithPassengers(entity);
|
||||
+ // CraftBukkit start
|
||||
+ level.addFreshEntityWithPassengers(entity, creatureSpawnReason);
|
||||
+ if (entity.isRemoved()) {
|
||||
+ return null; // Don't return an entity when CreatureSpawnEvent is canceled
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (entity instanceof Mob mob) {
|
||||
mob.playAmbientSound();
|
||||
}
|
||||
@@ -1225,6 +_,15 @@
|
||||
EntityType<?> entityType = customData.parseEntityType(server.registryAccess(), Registries.ENTITY_TYPE);
|
||||
if (entity.getType() == entityType) {
|
||||
if (level.isClientSide || !entity.getType().onlyOpCanSetNbt() || player != null && server.getPlayerList().isOp(player.getGameProfile())) {
|
||||
+ // Paper start - filter out protected tags
|
||||
+ if (player == null || !player.getBukkitEntity().hasPermission("minecraft.nbt.place")) {
|
||||
+ customData = customData.update((compound) -> {
|
||||
+ for (net.minecraft.commands.arguments.NbtPathArgument.NbtPath tag : level.paperConfig().entities.spawning.filteredEntityTagNbtPaths) {
|
||||
+ tag.remove(compound);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ // Paper end - filter out protected tags
|
||||
customData.loadInto(entity);
|
||||
}
|
||||
}
|
||||
@@ -1296,9 +_,19 @@
|
||||
}
|
||||
|
||||
public static Optional<Entity> create(CompoundTag tag, Level level, EntitySpawnReason spawnReason) {
|
||||
+ // Paper start - Don't fire sync event during generation
|
||||
+ return create(tag, level, spawnReason, false);
|
||||
+ }
|
||||
+ public static Optional<Entity> create(CompoundTag tag, Level level, EntitySpawnReason spawnReason, boolean generation) {
|
||||
+ // Paper end - Don't fire sync event during generation
|
||||
return Util.ifElse(
|
||||
by(tag).map(entityType -> entityType.create(level, spawnReason)),
|
||||
- entity -> entity.load(tag),
|
||||
+ // Paper start - Don't fire sync event during generation
|
||||
+ entity -> {
|
||||
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
|
||||
+ entity.load(tag);
|
||||
+ },
|
||||
+ // Paper end - Don't fire sync event during generation
|
||||
() -> LOGGER.warn("Skipping Entity with id {}", tag.getString("id"))
|
||||
);
|
||||
}
|
||||
@@ -1325,7 +_,7 @@
|
||||
}
|
||||
|
||||
public static Optional<EntityType<?>> by(CompoundTag tag) {
|
||||
- return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.parse(tag.getString("id")));
|
||||
+ return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(tag.getString("id"))); // Paper - Validate ResourceLocation
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -0,0 +1,98 @@
|
||||
--- a/net/minecraft/world/entity/Leashable.java
|
||||
+++ b/net/minecraft/world/entity/Leashable.java
|
||||
@@ -56,7 +_,13 @@
|
||||
@Nullable
|
||||
private static Leashable.LeashData readLeashDataInternal(CompoundTag tag) {
|
||||
if (tag.contains("leash", 10)) {
|
||||
- return new Leashable.LeashData(Either.left(tag.getCompound("leash").getUUID("UUID")));
|
||||
+ // Paper start
|
||||
+ final CompoundTag leashTag = tag.getCompound("leash");
|
||||
+ if (!leashTag.hasUUID("UUID")) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ return new Leashable.LeashData(Either.left(leashTag.getUUID("UUID")));
|
||||
+ // Paper end
|
||||
} else {
|
||||
if (tag.contains("leash", 11)) {
|
||||
Either<UUID, BlockPos> either = NbtUtils.readBlockPos(tag, "leash").<Either<UUID, BlockPos>>map(Either::right).orElse(null);
|
||||
@@ -72,6 +_,11 @@
|
||||
default void writeLeashData(CompoundTag tag, @Nullable Leashable.LeashData leashData) {
|
||||
if (leashData != null) {
|
||||
Either<UUID, BlockPos> either = leashData.delayedLeashInfo;
|
||||
+ // CraftBukkit start - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin
|
||||
+ if (leashData.leashHolder != null && leashData.leashHolder.pluginRemoved) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (leashData.leashHolder instanceof LeashFenceKnotEntity leashFenceKnotEntity) {
|
||||
either = Either.right(leashFenceKnotEntity.getPos());
|
||||
} else if (leashData.leashHolder != null) {
|
||||
@@ -104,7 +_,9 @@
|
||||
}
|
||||
|
||||
if (entity.tickCount > 100) {
|
||||
+ entity.forceDrops = true; // CraftBukkit
|
||||
entity.spawnAtLocation(serverLevel, Items.LEAD);
|
||||
+ entity.forceDrops = false; // CraftBukkit
|
||||
entity.setLeashData(null);
|
||||
}
|
||||
}
|
||||
@@ -128,7 +_,9 @@
|
||||
entity.onLeashRemoved();
|
||||
if (entity.level() instanceof ServerLevel serverLevel) {
|
||||
if (dropItem) {
|
||||
+ entity.forceDrops = true; // CraftBukkit
|
||||
entity.spawnAtLocation(serverLevel, Items.LEAD);
|
||||
+ entity.forceDrops = false; // CraftBukkit
|
||||
}
|
||||
|
||||
if (broadcastPacket) {
|
||||
@@ -146,7 +_,15 @@
|
||||
|
||||
if (leashData != null && leashData.leashHolder != null) {
|
||||
if (!entity.isAlive() || !leashData.leashHolder.isAlive()) {
|
||||
- if (level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
|
||||
+ // Paper start - Expand EntityUnleashEvent
|
||||
+ final org.bukkit.event.entity.EntityUnleashEvent event = new org.bukkit.event.entity.EntityUnleashEvent(
|
||||
+ entity.getBukkitEntity(),
|
||||
+ !entity.isAlive() ? org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.PLAYER_UNLEASH : org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.HOLDER_GONE,
|
||||
+ level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS) && !entity.pluginRemoved
|
||||
+ );
|
||||
+ event.callEvent();
|
||||
+ if (event.isDropLeash()) { // CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin
|
||||
+ // Paper end - Expand EntityUnleashEvent
|
||||
entity.dropLeash();
|
||||
} else {
|
||||
entity.removeLeash();
|
||||
@@ -160,7 +_,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
- if (f > 10.0) {
|
||||
+ if (f > entity.level().paperConfig().misc.maxLeashDistance.or(LEASH_TOO_FAR_DIST)) { // Paper - Configurable max leash distance
|
||||
entity.leashTooFarBehaviour();
|
||||
} else if (f > 6.0) {
|
||||
entity.elasticRangeLeashBehaviour(leashHolder, f);
|
||||
@@ -177,7 +_,21 @@
|
||||
}
|
||||
|
||||
default void leashTooFarBehaviour() {
|
||||
- this.dropLeash();
|
||||
+ // CraftBukkit start
|
||||
+ boolean dropLeash = true; // Paper
|
||||
+ if (this instanceof Entity entity) {
|
||||
+ // Paper start - Expand EntityUnleashEvent
|
||||
+ final org.bukkit.event.entity.EntityUnleashEvent event = new org.bukkit.event.entity.EntityUnleashEvent(entity.getBukkitEntity(), org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.DISTANCE, true);
|
||||
+ if (!event.callEvent()) return;
|
||||
+ dropLeash = event.isDropLeash();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ if (dropLeash) {
|
||||
+ this.dropLeash();
|
||||
+ } else {
|
||||
+ this.removeLeash();
|
||||
+ }
|
||||
+ // Paper end - Expand EntityUnleashEvent
|
||||
}
|
||||
|
||||
default void closeRangeLeashBehaviour(Entity entity) {
|
||||
Reference in New Issue
Block a user