diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch index a7dd223c0a..557d5bf7e6 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch @@ -78,7 +78,7 @@ + // CraftBukkit start + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; - ++ + public LevelChunk getChunkIfLoaded(int x, int z) { + return this.chunkSource.getChunk(x, z, false); + } @@ -128,7 +128,7 @@ + } + int minBlockX = Mth.floor(axisalignedbb.minX - 1.0E-7D) - 3; + int minBlockZ = Mth.floor(axisalignedbb.minZ - 1.0E-7D) - 3; -+ + + int maxBlockX = Mth.floor(axisalignedbb.maxX + 1.0E-7D) + 3; + int maxBlockZ = Mth.floor(axisalignedbb.maxZ + 1.0E-7D) + 3; + @@ -404,7 +404,7 @@ + ((ServerPlayer) this.players.get(idx)).tickWeather(); + } + } -+ + + if (flag != this.isRaining()) { + // Only send weather packets to those affected + for (int idx = 0; idx < this.players.size(); ++idx) { @@ -419,7 +419,7 @@ + } + } + // CraftBukkit end - ++ } @VisibleForTesting @@ -855,12 +855,21 @@ ServerLevel.this.getChunkSource().addEntity(entity); if (entity instanceof ServerPlayer entityplayer) { ServerLevel.this.players.add(entityplayer); -@@ -1864,9 +2195,42 @@ +@@ -1864,9 +2195,51 @@ } entity.updateDynamicGameEventListener(DynamicGameEventListener::add); + entity.inWorld = true; // CraftBukkit - Mark entity as in world + entity.valid = true; // CraftBukkit ++ // Paper start - Entity origin API ++ if (entity.getOriginVector() == null) { ++ entity.setOrigin(entity.getBukkitEntity().getLocation()); ++ } ++ // Default to current world if unknown, gross assumption but entities rarely change world ++ if (entity.getOriginWorld() == null) { ++ entity.setOrigin(entity.getOriginVector().toLocation(getWorld())); ++ } ++ // Paper end - Entity origin API } public void onTrackingEnd(Entity entity) { @@ -898,7 +907,7 @@ ServerLevel.this.getChunkSource().removeEntity(entity); if (entity instanceof ServerPlayer entityplayer) { ServerLevel.this.players.remove(entityplayer); -@@ -1895,6 +2259,14 @@ +@@ -1895,6 +2268,14 @@ } entity.updateDynamicGameEventListener(DynamicGameEventListener::remove); diff --git a/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch index 58e250b6fd..d55dca6e51 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch @@ -61,7 +61,7 @@ +// CraftBukkit end public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder { -+ + + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; + static boolean isLevelAtLeast(CompoundTag tag, int level) { @@ -69,7 +69,7 @@ + } + + private CraftEntity bukkitEntity; - ++ + public CraftEntity getBukkitEntity() { + if (this.bukkitEntity == null) { + this.bukkitEntity = CraftEntity.getEntity(this.level.getCraftServer(), this); @@ -95,7 +95,7 @@ private static final EntityDataAccessor<Integer> DATA_TICKS_FROZEN = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.INT); private EntityInLevelCallback levelCallback; private final VecDeltaCodec packetPositionCodec; -@@ -253,6 +311,41 @@ +@@ -253,7 +311,62 @@ private final List<Entity.Movement> movementThisTick; private final Set<BlockState> blocksInside; private final LongSet visitedBlocks; @@ -120,7 +120,27 @@ + public long activatedTick = Integer.MIN_VALUE; + public void inactiveTick() { } + // Spigot end ++ // Paper start - Entity origin API ++ @javax.annotation.Nullable ++ private org.bukkit.util.Vector origin; ++ @javax.annotation.Nullable ++ private UUID originWorld; + ++ public void setOrigin(@javax.annotation.Nonnull Location location) { ++ this.origin = location.toVector(); ++ this.originWorld = location.getWorld().getUID(); ++ } + ++ @javax.annotation.Nullable ++ public org.bukkit.util.Vector getOriginVector() { ++ return this.origin != null ? this.origin.clone() : null; ++ } ++ ++ @javax.annotation.Nullable ++ public UUID getOriginWorld() { ++ return this.originWorld; ++ } ++ // Paper end - Entity origin API + public float getBukkitYaw() { + return this.yRot; + } @@ -134,10 +154,11 @@ + return this.dimensions.makeBoundingBox(x, y, z); + } + // Paper end - ++ public Entity(EntityType<?> type, Level world) { this.id = Entity.ENTITY_COUNTER.incrementAndGet(); -@@ -284,6 +377,13 @@ + this.passengers = ImmutableList.of(); +@@ -284,6 +397,13 @@ this.position = Vec3.ZERO; this.blockPosition = BlockPos.ZERO; this.chunkPosition = ChunkPos.ZERO; @@ -151,7 +172,7 @@ SynchedEntityData.Builder datawatcher_a = new SynchedEntityData.Builder(this); datawatcher_a.define(Entity.DATA_SHARED_FLAGS_ID, (byte) 0); -@@ -292,7 +392,7 @@ +@@ -292,7 +412,7 @@ datawatcher_a.define(Entity.DATA_CUSTOM_NAME, Optional.empty()); datawatcher_a.define(Entity.DATA_SILENT, false); datawatcher_a.define(Entity.DATA_NO_GRAVITY, false); @@ -160,7 +181,7 @@ datawatcher_a.define(Entity.DATA_TICKS_FROZEN, 0); this.defineSynchedData(datawatcher_a); this.entityData = datawatcher_a.build(); -@@ -362,20 +462,36 @@ +@@ -362,20 +482,36 @@ } public void kill(ServerLevel world) { @@ -199,7 +220,7 @@ public boolean equals(Object object) { return object instanceof Entity ? ((Entity) object).id == this.id : false; } -@@ -385,22 +501,34 @@ +@@ -385,22 +521,34 @@ } public void remove(Entity.RemovalReason reason) { @@ -239,7 +260,7 @@ return this.getPose() == pose; } -@@ -417,6 +545,33 @@ +@@ -417,6 +565,33 @@ } public void setRot(float yaw, float pitch) { @@ -273,23 +294,24 @@ this.setYRot(yaw % 360.0F); this.setXRot(pitch % 360.0F); } -@@ -462,6 +617,15 @@ - this.baseTick(); - } +@@ -460,7 +635,16 @@ + public void tick() { + this.baseTick(); ++ } ++ + // CraftBukkit start + public void postTick() { + // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle + if (!(this instanceof ServerPlayer)) { + this.handlePortal(); + } -+ } + } + // CraftBukkit end -+ + public void baseTick() { ProfilerFiller gameprofilerfiller = Profiler.get(); - -@@ -475,7 +639,7 @@ +@@ -475,7 +659,7 @@ --this.boardingCooldown; } @@ -298,7 +320,7 @@ if (this.canSpawnSprintParticle()) { this.spawnSprintParticle(); } -@@ -514,6 +678,10 @@ +@@ -514,6 +698,10 @@ if (this.isInLava()) { this.lavaHurt(); this.fallDistance *= 0.5F; @@ -309,7 +331,7 @@ } this.checkBelowWorld(); -@@ -525,7 +693,7 @@ +@@ -525,7 +713,7 @@ world = this.level(); if (world instanceof ServerLevel worldserver) { if (this instanceof Leashable) { @@ -318,7 +340,7 @@ } } -@@ -568,15 +736,32 @@ +@@ -568,15 +756,32 @@ public void lavaHurt() { if (!this.fireImmune()) { @@ -353,7 +375,7 @@ } } -@@ -587,9 +772,25 @@ +@@ -587,9 +792,25 @@ } public final void igniteForSeconds(float seconds) { @@ -380,7 +402,7 @@ public void igniteForTicks(int ticks) { if (this.remainingFireTicks < ticks) { this.setRemainingFireTicks(ticks); -@@ -610,7 +811,7 @@ +@@ -610,7 +831,7 @@ } protected void onBelowWorld() { @@ -389,7 +411,7 @@ } public boolean isFree(double offsetX, double offsetY, double offsetZ) { -@@ -750,6 +951,28 @@ +@@ -750,6 +971,28 @@ } } @@ -418,10 +440,12 @@ if (!this.level().isClientSide() || this.isControlledByLocalInstance()) { Entity.MovementEmission entity_movementemission = this.getMovementEmission(); -@@ -1133,6 +1356,20 @@ - return SoundEvents.GENERIC_SPLASH; - } +@@ -1131,7 +1374,21 @@ + protected SoundEvent getSwimHighSpeedSplashSound() { + return SoundEvents.GENERIC_SPLASH; ++ } ++ + // CraftBukkit start - Add delegate methods + public SoundEvent getSwimSound0() { + return this.getSwimSound(); @@ -433,13 +457,12 @@ + + public SoundEvent getSwimHighSpeedSplashSound0() { + return this.getSwimHighSpeedSplashSound(); -+ } + } + // CraftBukkit end -+ + public void recordMovementThroughBlocks(Vec3 oldPos, Vec3 newPos) { this.movementThisTick.add(new Entity.Movement(oldPos, newPos)); - } -@@ -1609,6 +1846,7 @@ +@@ -1609,6 +1866,7 @@ this.yo = y; this.zo = d4; this.setPos(d3, y, d4); @@ -447,20 +470,21 @@ } public void moveTo(Vec3 pos) { -@@ -1861,6 +2099,12 @@ - return false; - } +@@ -1859,7 +2117,13 @@ + public boolean isPushable() { + return false; ++ } ++ + // CraftBukkit start - collidable API + public boolean canCollideWithBukkit(Entity entity) { + return this.isPushable(); -+ } + } + // CraftBukkit end -+ + public void awardKillScore(Entity entityKilled, DamageSource damageSource) { if (entityKilled instanceof ServerPlayer) { - CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) entityKilled, this, damageSource); -@@ -1889,16 +2133,22 @@ +@@ -1889,16 +2153,22 @@ } public boolean saveAsPassenger(CompoundTag nbt) { @@ -486,7 +510,7 @@ return true; } } -@@ -1909,54 +2159,98 @@ +@@ -1909,54 +2179,98 @@ } public CompoundTag saveWithoutId(CompoundTag nbt) { @@ -605,7 +629,7 @@ } ListTag nbttaglist; -@@ -1972,10 +2266,10 @@ +@@ -1972,10 +2286,10 @@ nbttaglist.add(StringTag.valueOf(s)); } @@ -618,7 +642,7 @@ if (this.isVehicle()) { nbttaglist = new ListTag(); iterator = this.getPassengers().iterator(); -@@ -1984,17 +2278,22 @@ +@@ -1984,17 +2298,31 @@ Entity entity = (Entity) iterator.next(); CompoundTag nbttagcompound1 = new CompoundTag(); @@ -640,15 +664,23 @@ + this.bukkitEntity.storeBukkitValues(nbttagcompound); + } + // CraftBukkit end ++ // Paper start ++ if (this.origin != null) { ++ UUID originWorld = this.originWorld != null ? this.originWorld : this.level != null ? this.level.getWorld().getUID() : null; ++ if (originWorld != null) { ++ nbttagcompound.putUUID("Paper.OriginWorld", originWorld); ++ } ++ nbttagcompound.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ())); ++ } ++ // Paper end + return nbttagcompound; } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being saved"); -@@ -2079,7 +2378,51 @@ - } +@@ -2080,6 +2408,64 @@ } else { throw new IllegalStateException("Entity has invalid position"); -+ } + } + + // CraftBukkit start + // Spigot start @@ -684,7 +716,7 @@ + } + + ((ServerPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); - } ++ } + this.getBukkitEntity().readBukkitValues(nbt); + if (nbt.contains("Bukkit.invisible")) { + boolean bukkitInvisible = nbt.getBoolean("Bukkit.invisible"); @@ -692,11 +724,25 @@ + this.persistentInvisibility = bukkitInvisible; + } + // CraftBukkit end ++ ++ // Paper start ++ ListTag originTag = nbt.getList("Paper.Origin", net.minecraft.nbt.Tag.TAG_DOUBLE); ++ if (!originTag.isEmpty()) { ++ UUID originWorld = null; ++ if (nbt.contains("Paper.OriginWorld")) { ++ originWorld = nbt.getUUID("Paper.OriginWorld"); ++ } else if (this.level != null) { ++ originWorld = this.level.getWorld().getUID(); ++ } ++ this.originWorld = originWorld; ++ origin = new org.bukkit.util.Vector(originTag.getDouble(0), originTag.getDouble(1), originTag.getDouble(2)); ++ } ++ // Paper end + } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded"); -@@ -2101,6 +2444,12 @@ +@@ -2101,6 +2487,12 @@ return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null; } @@ -709,7 +755,7 @@ protected abstract void readAdditionalSaveData(CompoundTag nbt); protected abstract void addAdditionalSaveData(CompoundTag nbt); -@@ -2153,9 +2502,22 @@ +@@ -2153,9 +2545,22 @@ if (stack.isEmpty()) { return null; } else { @@ -732,7 +778,7 @@ world.addFreshEntity(entityitem); return entityitem; } -@@ -2184,6 +2546,12 @@ +@@ -2184,6 +2589,12 @@ if (this.isAlive() && this instanceof Leashable leashable) { if (leashable.getLeashHolder() == player) { if (!this.level().isClientSide()) { @@ -745,7 +791,7 @@ if (player.hasInfiniteMaterials()) { leashable.removeLeash(); } else { -@@ -2200,6 +2568,13 @@ +@@ -2200,6 +2611,13 @@ if (itemstack.is(Items.LEAD) && leashable.canHaveALeashAttachedToIt()) { if (!this.level().isClientSide()) { @@ -759,7 +805,7 @@ leashable.setLeashedTo(player, true); } -@@ -2265,7 +2640,7 @@ +@@ -2265,7 +2683,7 @@ } public boolean showVehicleHealth() { @@ -768,7 +814,7 @@ } public boolean startRiding(Entity entity, boolean force) { -@@ -2273,7 +2648,7 @@ +@@ -2273,7 +2691,7 @@ return false; } else if (!entity.couldAcceptPassenger()) { return false; @@ -777,7 +823,7 @@ return false; } else { for (Entity entity1 = entity; entity1.vehicle != null; entity1 = entity1.vehicle) { -@@ -2285,11 +2660,32 @@ +@@ -2285,11 +2703,32 @@ if (!force && (!this.canRide(entity) || !entity.canAddPassenger(this))) { return false; } else { @@ -811,7 +857,7 @@ this.vehicle = entity; this.vehicle.addPassenger(this); entity.getIndirectPassengersStream().filter((entity2) -> { -@@ -2318,7 +2714,7 @@ +@@ -2318,7 +2757,7 @@ Entity entity = this.vehicle; this.vehicle = null; @@ -820,7 +866,7 @@ } } -@@ -2349,21 +2745,50 @@ +@@ -2349,21 +2788,50 @@ } } @@ -877,7 +923,7 @@ } protected boolean canAddPassenger(Entity passenger) { -@@ -2464,7 +2889,7 @@ +@@ -2464,7 +2932,7 @@ if (teleporttransition != null) { ServerLevel worldserver1 = teleporttransition.newLevel(); @@ -886,7 +932,7 @@ this.teleport(teleporttransition); } } -@@ -2547,7 +2972,7 @@ +@@ -2547,7 +3015,7 @@ } public boolean isCrouching() { @@ -895,7 +941,7 @@ } public boolean isSprinting() { -@@ -2563,7 +2988,7 @@ +@@ -2563,7 +3031,7 @@ } public boolean isVisuallySwimming() { @@ -904,7 +950,7 @@ } public boolean isVisuallyCrawling() { -@@ -2571,6 +2996,13 @@ +@@ -2571,6 +3039,13 @@ } public void setSwimming(boolean swimming) { @@ -918,7 +964,7 @@ this.setSharedFlag(4, swimming); } -@@ -2624,8 +3056,12 @@ +@@ -2624,8 +3099,12 @@ return this.getTeam() != null ? this.getTeam().isAlliedTo(team) : false; } @@ -932,7 +978,7 @@ } public boolean getSharedFlag(int index) { -@@ -2644,7 +3080,7 @@ +@@ -2644,7 +3123,7 @@ } public int getMaxAirSupply() { @@ -941,7 +987,7 @@ } public int getAirSupply() { -@@ -2652,7 +3088,18 @@ +@@ -2652,7 +3131,18 @@ } public void setAirSupply(int air) { @@ -961,7 +1007,7 @@ } public int getTicksFrozen() { -@@ -2679,11 +3126,40 @@ +@@ -2679,11 +3169,40 @@ public void thunderHit(ServerLevel world, LightningBolt lightning) { this.setRemainingFireTicks(this.remainingFireTicks + 1); @@ -1004,7 +1050,7 @@ } public void onAboveBubbleCol(boolean drag) { -@@ -2713,7 +3189,7 @@ +@@ -2713,7 +3232,7 @@ this.resetFallDistance(); } @@ -1013,7 +1059,7 @@ return true; } -@@ -2852,6 +3328,18 @@ +@@ -2852,6 +3371,18 @@ if (world instanceof ServerLevel worldserver) { if (!this.isRemoved()) { @@ -1032,7 +1078,7 @@ ServerLevel worldserver1 = teleportTarget.newLevel(); boolean flag = worldserver1.dimension() != worldserver.dimension(); -@@ -2920,8 +3408,12 @@ +@@ -2920,8 +3451,12 @@ } else { entity.restoreFrom(this); this.removeAfterChangingDimensions(); @@ -1046,7 +1092,7 @@ Iterator iterator1 = list1.iterator(); while (iterator1.hasNext()) { -@@ -2947,7 +3439,7 @@ +@@ -2947,7 +3482,7 @@ } private void sendTeleportTransitionToRidingPlayers(TeleportTransition teleportTarget) { @@ -1055,7 +1101,7 @@ Iterator iterator = this.getIndirectPassengers().iterator(); while (iterator.hasNext()) { -@@ -2995,8 +3487,9 @@ +@@ -2995,8 +3530,9 @@ } protected void removeAfterChangingDimensions() { @@ -1066,7 +1112,7 @@ leashable.removeLeash(); } -@@ -3006,6 +3499,20 @@ +@@ -3006,6 +3542,20 @@ return PortalShape.getRelativePosition(portalRect, portalAxis, this.position(), this.getDimensions(this.getPose())); } @@ -1087,7 +1133,7 @@ public boolean canUsePortal(boolean allowVehicles) { return (allowVehicles || !this.isPassenger()) && this.isAlive(); } -@@ -3134,10 +3641,16 @@ +@@ -3134,10 +3684,16 @@ return (Boolean) this.entityData.get(Entity.DATA_CUSTOM_NAME_VISIBLE); } @@ -1107,7 +1153,7 @@ return entity != null; } -@@ -3187,7 +3700,7 @@ +@@ -3187,7 +3743,7 @@ /** @deprecated */ @Deprecated protected void fixupDimensions() { @@ -1116,7 +1162,7 @@ EntityDimensions entitysize = this.getDimensions(entitypose); this.dimensions = entitysize; -@@ -3196,7 +3709,7 @@ +@@ -3196,7 +3752,7 @@ public void refreshDimensions() { EntityDimensions entitysize = this.dimensions; @@ -1125,7 +1171,7 @@ EntityDimensions entitysize1 = this.getDimensions(entitypose); this.dimensions = entitysize1; -@@ -3258,10 +3771,29 @@ +@@ -3258,10 +3814,29 @@ } public final void setBoundingBox(AABB boundingBox) { @@ -1157,7 +1203,7 @@ return this.getDimensions(pose).eyeHeight(); } -@@ -3335,7 +3867,7 @@ +@@ -3335,7 +3910,7 @@ } @Nullable @@ -1166,7 +1212,7 @@ return null; } -@@ -3435,7 +3967,7 @@ +@@ -3435,7 +4010,7 @@ } public boolean isControlledByLocalInstance() { @@ -1175,7 +1221,7 @@ if (entityliving instanceof Player entityhuman) { return entityhuman.isLocalPlayer(); -@@ -3445,7 +3977,7 @@ +@@ -3445,7 +4020,7 @@ } public boolean isControlledByClient() { @@ -1184,7 +1230,7 @@ return entityliving != null && entityliving.isControlledByClient(); } -@@ -3463,7 +3995,7 @@ +@@ -3463,7 +4038,7 @@ return new Vec3((double) f1 * d2 / (double) f3, 0.0D, (double) f2 * d2 / (double) f3); } @@ -1193,10 +1239,11 @@ return new Vec3(this.getX(), this.getBoundingBox().maxY, this.getZ()); } -@@ -3489,8 +4021,37 @@ +@@ -3488,9 +4063,38 @@ + public int getFireImmuneTicks() { return 1; } - ++ + // CraftBukkit start + private final CommandSource commandSource = new CommandSource() { + @@ -1208,7 +1255,7 @@ + public CommandSender getBukkitSender(CommandSourceStack wrapper) { + return Entity.this.getBukkitEntity(); + } -+ + + @Override + public boolean acceptsSuccess() { + return ((ServerLevel) Entity.this.level()).getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK); @@ -1232,20 +1279,19 @@ } public void lookAt(EntityAnchorArgument.Anchor anchorPoint, Vec3 target) { -@@ -3550,7 +4111,12 @@ - +@@ -3551,6 +4155,11 @@ vec3d = vec3d.add(vec3d1); ++k1; -+ } + } + // CraftBukkit start - store last lava contact location + if (tag == FluidTags.LAVA) { + this.lastLavaContact = blockposition_mutableblockposition.immutable(); - } ++ } + // CraftBukkit end } } } -@@ -3613,7 +4179,7 @@ +@@ -3613,7 +4222,7 @@ return new ClientboundAddEntityPacket(this, entityTrackerEntry); } @@ -1254,7 +1300,7 @@ return this.type.getDimensions(); } -@@ -3818,8 +4384,16 @@ +@@ -3818,8 +4427,16 @@ @Override public final void setRemoved(Entity.RemovalReason reason) { @@ -1272,7 +1318,7 @@ } if (this.removalReason.shouldDestroy()) { -@@ -3827,8 +4401,8 @@ +@@ -3827,8 +4444,8 @@ } this.getPassengers().forEach(Entity::stopRiding); @@ -1283,7 +1329,7 @@ } public void unsetRemoved() { -@@ -3887,7 +4461,7 @@ +@@ -3887,7 +4504,7 @@ } public Vec3 getKnownMovement() { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java index 978397e517..ea27931d01 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -964,4 +964,21 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return this.spigot; } // Spigot end + + // Paper start - entity origin API + @Override + public Location getOrigin() { + Vector originVector = this.getHandle().getOriginVector(); + if (originVector == null) { + return null; + } + World world = this.getWorld(); + if (this.getHandle().getOriginWorld() != null) { + world = org.bukkit.Bukkit.getWorld(this.getHandle().getOriginWorld()); + } + + //noinspection ConstantConditions + return originVector.toLocation(world); + } + // Paper end - entity origin API }