Commits

md_5 authored e8010dc93fb
#1136: Add API to allow entities to be invisible by default

Designed to make creating per-player entities easier
No tags

nms-patches/net/minecraft/world/entity/Entity.patch

Modified
59 59 +
60 60 + // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
61 61 + public int getDefaultMaxAirSupply() {
62 62 + return TOTAL_AIR_SUPPLY;
63 63 + }
64 64 + // CraftBukkit end
65 65 +
66 66 private static final Logger LOGGER = LogUtils.getLogger();
67 67 public static final String ID_TAG = "id";
68 68 public static final String PASSENGERS_TAG = "Passengers";
69 -@@ -234,6 +291,24 @@
69 +@@ -234,6 +291,25 @@
70 70 public boolean hasVisualFire;
71 71 @Nullable
72 72 private IBlockData feetBlockState;
73 73 + // CraftBukkit start
74 74 + public boolean persist = true;
75 ++ public boolean visibleByDefault = true;
75 76 + public boolean valid;
76 77 + public boolean generation;
77 78 + public int maxAirTicks = getDefaultMaxAirSupply(); // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
78 79 + public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only
79 80 + public boolean lastDamageCancelled; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled
80 81 + public boolean persistentInvisibility = false;
81 82 + public BlockPosition lastLavaContact;
82 83 +
83 84 + public float getBukkitYaw() {
84 85 + return this.yRot;
85 86 + }
86 87 +
87 88 + public boolean isChunkLoaded() {
88 89 + return level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4);
89 90 + }
90 91 + // CraftBukkit end
91 92
92 93 public Entity(EntityTypes<?> entitytypes, World world) {
93 94 this.id = Entity.ENTITY_COUNTER.incrementAndGet();
94 -@@ -365,6 +440,12 @@
95 +@@ -365,6 +441,12 @@
95 96 public void onClientRemoval() {}
96 97
97 98 public void setPose(EntityPose entitypose) {
98 99 + // CraftBukkit start
99 100 + if (entitypose == this.getPose()) {
100 101 + return;
101 102 + }
102 103 + this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[entitypose.ordinal()]));
103 104 + // CraftBukkit end
104 105 this.entityData.set(Entity.DATA_POSE, entitypose);
105 106 }
106 107
107 -@@ -389,6 +470,33 @@
108 +@@ -389,6 +471,33 @@
108 109 }
109 110
110 111 protected void setRot(float f, float f1) {
111 112 + // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0
112 113 + if (Float.isNaN(f)) {
113 114 + f = 0;
114 115 + }
115 116 +
116 117 + if (f == Float.POSITIVE_INFINITY || f == Float.NEGATIVE_INFINITY) {
117 118 + if (this instanceof EntityPlayer) {
131 132 + this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid pitch");
132 133 + ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite pitch (Hacking?)");
133 134 + }
134 135 + f1 = 0;
135 136 + }
136 137 + // CraftBukkit end
137 138 +
138 139 this.setYRot(f % 360.0F);
139 140 this.setXRot(f1 % 360.0F);
140 141 }
141 -@@ -430,6 +538,15 @@
142 +@@ -430,6 +539,15 @@
142 143 this.baseTick();
143 144 }
144 145
145 146 + // CraftBukkit start
146 147 + public void postTick() {
147 148 + // 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
148 149 + if (!(this instanceof EntityPlayer)) {
149 150 + this.handleNetherPortal();
150 151 + }
151 152 + }
152 153 + // CraftBukkit end
153 154 +
154 155 public void baseTick() {
155 156 this.level.getProfiler().push("entityBaseTick");
156 157 this.feetBlockState = null;
157 -@@ -444,7 +561,7 @@
158 +@@ -444,7 +562,7 @@
158 159 this.walkDistO = this.walkDist;
159 160 this.xRotO = this.getXRot();
160 161 this.yRotO = this.getYRot();
161 162 - this.handleNetherPortal();
162 163 + if (this instanceof EntityPlayer) this.handleNetherPortal(); // CraftBukkit - // Moved up to postTick
163 164 if (this.canSpawnSprintParticle()) {
164 165 this.spawnSprintParticle();
165 166 }
166 -@@ -479,6 +596,10 @@
167 +@@ -479,6 +597,10 @@
167 168 if (this.isInLava()) {
168 169 this.lavaHurt();
169 170 this.fallDistance *= 0.5F;
170 171 + // CraftBukkit start
171 172 + } else {
172 173 + this.lastLavaContact = null;
173 174 + // CraftBukkit end
174 175 }
175 176
176 177 this.checkOutOfWorld();
177 -@@ -522,15 +643,48 @@
178 +@@ -522,15 +644,48 @@
178 179
179 180 public void lavaHurt() {
180 181 if (!this.fireImmune()) {
181 182 - this.setSecondsOnFire(15);
182 183 + // CraftBukkit start - Fallen in lava TODO: this event spams!
183 184 + if (this instanceof EntityLiving && remainingFireTicks <= 0) {
184 185 + // not on fire yet
185 186 + org.bukkit.block.Block damager = (lastLavaContact == null) ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact);
186 187 + org.bukkit.entity.Entity damagee = this.getBukkitEntity();
187 188 + EntityCombustEvent combustEvent = new org.bukkit.event.entity.EntityCombustByBlockEvent(damager, damagee, 15);
217 218 + if (event.isCancelled()) {
218 219 + return;
219 220 + }
220 221 +
221 222 + i = event.getDuration();
222 223 + }
223 224 + // CraftBukkit end
224 225 int j = i * 20;
225 226
226 227 if (this instanceof EntityLiving) {
227 -@@ -644,6 +798,28 @@
228 +@@ -644,6 +799,28 @@
228 229 block.updateEntityAfterFallOn(this.level, this);
229 230 }
230 231
231 232 + // CraftBukkit start
232 233 + if (horizontalCollision && getBukkitEntity() instanceof Vehicle) {
233 234 + Vehicle vehicle = (Vehicle) this.getBukkitEntity();
234 235 + org.bukkit.block.Block bl = this.level.getWorld().getBlockAt(MathHelper.floor(this.getX()), MathHelper.floor(this.getY()), MathHelper.floor(this.getZ()));
235 236 +
236 237 + if (vec3d.x > vec3d1.x) {
237 238 + bl = bl.getRelative(BlockFace.EAST);
246 247 + if (!bl.getType().isAir()) {
247 248 + VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, bl);
248 249 + level.getCraftServer().getPluginManager().callEvent(event);
249 250 + }
250 251 + }
251 252 + // CraftBukkit end
252 253 +
253 254 if (this.onGround) {
254 255 block.stepOn(this.level, blockposition, iblockdata, this);
255 256 }
256 -@@ -946,6 +1122,20 @@
257 +@@ -946,6 +1123,20 @@
257 258 return SoundEffects.GENERIC_SPLASH;
258 259 }
259 260
260 261 + // CraftBukkit start - Add delegate methods
261 262 + public SoundEffect getSwimSound0() {
262 263 + return getSwimSound();
263 264 + }
264 265 +
265 266 + public SoundEffect getSwimSplashSound0() {
266 267 + return getSwimSplashSound();
267 268 + }
268 269 +
269 270 + public SoundEffect getSwimHighSpeedSplashSound0() {
270 271 + return getSwimHighSpeedSplashSound();
271 272 + }
272 273 + // CraftBukkit end
273 274 +
274 275 protected void checkInsideBlocks() {
275 276 AxisAlignedBB axisalignedbb = this.getBoundingBox();
276 277 BlockPosition blockposition = new BlockPosition(axisalignedbb.minX + 1.0E-7D, axisalignedbb.minY + 1.0E-7D, axisalignedbb.minZ + 1.0E-7D);
277 -@@ -1305,6 +1495,7 @@
278 +@@ -1305,6 +1496,7 @@
278 279 this.yo = d1;
279 280 this.zo = d4;
280 281 this.setPos(d3, d1, d4);
281 282 + if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit
282 283 }
283 284
284 285 public void moveTo(Vec3D vec3d) {
285 -@@ -1495,6 +1686,12 @@
286 +@@ -1495,6 +1687,12 @@
286 287 return false;
287 288 }
288 289
289 290 + // CraftBukkit start - collidable API
290 291 + public boolean canCollideWithBukkit(Entity entity) {
291 292 + return isPushable();
292 293 + }
293 294 + // CraftBukkit end
294 295 +
295 296 public void awardKillScore(Entity entity, int i, DamageSource damagesource) {
296 297 if (entity instanceof EntityPlayer) {
297 298 CriterionTriggers.ENTITY_KILLED_PLAYER.trigger((EntityPlayer) entity, this, damagesource);
298 -@@ -1528,7 +1725,7 @@
299 +@@ -1528,7 +1726,7 @@
299 300 } else {
300 301 String s = this.getEncodeId();
301 302
302 303 - if (s == null) {
303 304 + if (!this.persist || s == null) { // CraftBukkit - persist flag
304 305 return false;
305 306 } else {
306 307 nbttagcompound.putString("id", s);
307 -@@ -1553,6 +1750,18 @@
308 +@@ -1553,6 +1751,18 @@
308 309 Vec3D vec3d = this.getDeltaMovement();
309 310
310 311 nbttagcompound.put("Motion", this.newDoubleList(vec3d.x, vec3d.y, vec3d.z));
311 312 +
312 313 + // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero
313 314 + // TODO: make sure this is the best way to address this.
314 315 + if (Float.isNaN(this.yRot)) {
315 316 + this.yRot = 0;
316 317 + }
317 318 +
318 319 + if (Float.isNaN(this.xRot)) {
319 320 + this.xRot = 0;
320 321 + }
321 322 + // CraftBukkit end
322 323 +
323 324 nbttagcompound.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot()));
324 325 nbttagcompound.putFloat("FallDistance", this.fallDistance);
325 326 nbttagcompound.putShort("Fire", (short) this.remainingFireTicks);
326 -@@ -1561,6 +1770,22 @@
327 +@@ -1561,6 +1771,25 @@
327 328 nbttagcompound.putBoolean("Invulnerable", this.invulnerable);
328 329 nbttagcompound.putInt("PortalCooldown", this.portalCooldown);
329 330 nbttagcompound.putUUID("UUID", this.getUUID());
330 331 + // CraftBukkit start
331 332 + // PAIL: Check above UUID reads 1.8 properly, ie: UUIDMost / UUIDLeast
332 333 + nbttagcompound.putLong("WorldUUIDLeast", ((WorldServer) this.level).getWorld().getUID().getLeastSignificantBits());
333 334 + nbttagcompound.putLong("WorldUUIDMost", ((WorldServer) this.level).getWorld().getUID().getMostSignificantBits());
334 335 + nbttagcompound.putInt("Bukkit.updateLevel", CURRENT_LEVEL);
335 336 + if (!this.persist) {
336 337 + nbttagcompound.putBoolean("Bukkit.persist", this.persist);
337 338 + }
339 ++ if (!this.visibleByDefault) {
340 ++ nbttagcompound.putBoolean("Bukkit.visibleByDefault", this.visibleByDefault);
341 ++ }
338 342 + if (this.persistentInvisibility) {
339 343 + nbttagcompound.putBoolean("Bukkit.invisible", this.persistentInvisibility);
340 344 + }
341 345 + // SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
342 346 + if (maxAirTicks != getDefaultMaxAirSupply()) {
343 347 + nbttagcompound.putInt("Bukkit.MaxAirSupply", getMaxAirSupply());
344 348 + }
345 349 + // CraftBukkit end
346 350 IChatBaseComponent ichatbasecomponent = this.getCustomName();
347 351
348 352 if (ichatbasecomponent != null) {
349 -@@ -1628,6 +1853,11 @@
353 +@@ -1628,6 +1857,11 @@
350 354 }
351 355 }
352 356
353 357 + // CraftBukkit start - stores eventually existing bukkit values
354 358 + if (this.bukkitEntity != null) {
355 359 + this.bukkitEntity.storeBukkitValues(nbttagcompound);
356 360 + }
357 361 + // CraftBukkit end
358 362 return nbttagcompound;
359 363 } catch (Throwable throwable) {
360 364 CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT");
361 -@@ -1711,6 +1941,44 @@
365 +@@ -1711,6 +1945,45 @@
362 366 } else {
363 367 throw new IllegalStateException("Entity has invalid position");
364 368 }
365 369 +
366 370 + // CraftBukkit start
367 371 + this.persist = !nbttagcompound.contains("Bukkit.persist") || nbttagcompound.getBoolean("Bukkit.persist");
372 ++ this.visibleByDefault = !nbttagcompound.contains("Bukkit.visibleByDefault") || nbttagcompound.getBoolean("Bukkit.visibleByDefault");
368 373 + // SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
369 374 + if (nbttagcompound.contains("Bukkit.MaxAirSupply")) {
370 375 + maxAirTicks = nbttagcompound.getInt("Bukkit.MaxAirSupply");
371 376 + }
372 377 + // CraftBukkit end
373 378 +
374 379 + // CraftBukkit start - Reset world
375 380 + if (this instanceof EntityPlayer) {
376 381 + Server server = Bukkit.getServer();
377 382 + org.bukkit.World bworld = null;
396 401 + if (nbttagcompound.contains("Bukkit.invisible")) {
397 402 + boolean bukkitInvisible = nbttagcompound.getBoolean("Bukkit.invisible");
398 403 + this.setInvisible(bukkitInvisible);
399 404 + this.persistentInvisibility = bukkitInvisible;
400 405 + }
401 406 + // CraftBukkit end
402 407 +
403 408 } catch (Throwable throwable) {
404 409 CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT");
405 410 CrashReportSystemDetails crashreportsystemdetails = crashreport.addCategory("Entity being loaded");
406 -@@ -1786,9 +2054,22 @@
411 +@@ -1786,9 +2059,22 @@
407 412 } else if (this.level.isClientSide) {
408 413 return null;
409 414 } else {
410 415 + // CraftBukkit start - Capture drops for death event
411 416 + if (this instanceof EntityLiving && !((EntityLiving) this).forceDrops) {
412 417 + ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack));
413 418 + return null;
414 419 + }
415 420 + // CraftBukkit end
416 421 EntityItem entityitem = new EntityItem(this.level, this.getX(), this.getY() + (double) f, this.getZ(), itemstack);
419 424 + // CraftBukkit start
420 425 + EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity());
421 426 + Bukkit.getPluginManager().callEvent(event);
422 427 + if (event.isCancelled()) {
423 428 + return null;
424 429 + }
425 430 + // CraftBukkit end
426 431 this.level.addFreshEntity(entityitem);
427 432 return entityitem;
428 433 }
429 -@@ -1882,7 +2163,7 @@
434 +@@ -1882,7 +2168,7 @@
430 435
431 436 this.setPose(EntityPose.STANDING);
432 437 this.vehicle = entity;
433 438 - this.vehicle.addPassenger(this);
434 439 + if (!this.vehicle.addPassenger(this)) this.vehicle = null; // CraftBukkit
435 440 entity.getIndirectPassengersStream().filter((entity2) -> {
436 441 return entity2 instanceof EntityPlayer;
437 442 }).forEach((entity2) -> {
438 -@@ -1913,7 +2194,7 @@
443 +@@ -1913,7 +2199,7 @@
439 444 Entity entity = this.vehicle;
440 445
441 446 this.vehicle = null;
442 447 - entity.removePassenger(this);
443 448 + if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit
444 449 }
445 450
446 451 }
447 -@@ -1926,10 +2207,31 @@
452 +@@ -1926,10 +2212,31 @@
448 453 this.removeVehicle();
449 454 }
450 455
451 456 - protected void addPassenger(Entity entity) {
452 457 + protected boolean addPassenger(Entity entity) { // CraftBukkit
453 458 if (entity.getVehicle() != this) {
454 459 throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)");
455 460 } else {
456 461 + // CraftBukkit start
457 462 + com.google.common.base.Preconditions.checkState(!entity.passengers.contains(this), "Circular entity riding! %s %s", this, entity);
470 475 + CraftEntity craftn = (CraftEntity) entity.getBukkitEntity().getVehicle();
471 476 + Entity n = craftn == null ? null : craftn.getHandle();
472 477 + if (event.isCancelled() || n != orig) {
473 478 + return false;
474 479 + }
475 480 + }
476 481 + // CraftBukkit end
477 482 if (this.passengers.isEmpty()) {
478 483 this.passengers = ImmutableList.of(entity);
479 484 } else {
480 -@@ -1945,12 +2247,32 @@
485 +@@ -1945,12 +2252,32 @@
481 486 }
482 487
483 488 }
484 489 + return true; // CraftBukkit
485 490 }
486 491
487 492 - protected void removePassenger(Entity entity) {
488 493 + protected boolean removePassenger(Entity entity) { // CraftBukkit
489 494 if (entity.getVehicle() == this) {
490 495 throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)");
504 509 + CraftEntity craftn = (CraftEntity) entity.getBukkitEntity().getVehicle();
505 510 + Entity n = craftn == null ? null : craftn.getHandle();
506 511 + if (event.isCancelled() || n != orig) {
507 512 + return false;
508 513 + }
509 514 + }
510 515 + // CraftBukkit end
511 516 if (this.passengers.size() == 1 && this.passengers.get(0) == entity) {
512 517 this.passengers = ImmutableList.of();
513 518 } else {
514 -@@ -1961,6 +2283,7 @@
519 +@@ -1961,6 +2288,7 @@
515 520
516 521 entity.boardingCooldown = 60;
517 522 }
518 523 + return true; // CraftBukkit
519 524 }
520 525
521 526 protected boolean canAddPassenger(Entity entity) {
522 -@@ -2023,14 +2346,20 @@
527 +@@ -2023,14 +2351,20 @@
523 528
524 529 if (this.isInsidePortal) {
525 530 MinecraftServer minecraftserver = worldserver.getServer();
526 531 - ResourceKey<World> resourcekey = this.level.dimension() == World.NETHER ? World.OVERWORLD : World.NETHER;
527 532 + ResourceKey<World> resourcekey = this.level.getTypeKey() == WorldDimension.NETHER ? World.OVERWORLD : World.NETHER; // CraftBukkit
528 533 WorldServer worldserver1 = minecraftserver.getLevel(resourcekey);
529 534
530 535 - if (worldserver1 != null && minecraftserver.isNetherEnabled() && !this.isPassenger() && this.portalTime++ >= i) {
531 536 + if (true && !this.isPassenger() && this.portalTime++ >= i) { // CraftBukkit
532 537 this.level.getProfiler().push("portal");
536 541 + // CraftBukkit start
537 542 + if (this instanceof EntityPlayer) {
538 543 + ((EntityPlayer) this).changeDimension(worldserver1, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL);
539 544 + } else {
540 545 + this.changeDimension(worldserver1);
541 546 + }
542 547 + // CraftBukkit end
543 548 this.level.getProfiler().pop();
544 549 }
545 550
546 -@@ -2148,6 +2477,13 @@
551 +@@ -2148,6 +2482,13 @@
547 552 }
548 553
549 554 public void setSwimming(boolean flag) {
550 555 + // CraftBukkit start
551 556 + if (valid && this.isSwimming() != flag && this instanceof EntityLiving) {
552 557 + if (CraftEventFactory.callToggleSwimEvent((EntityLiving) this, flag).isCancelled()) {
553 558 + return;
554 559 + }
555 560 + }
556 561 + // CraftBukkit end
557 562 this.setSharedFlag(4, flag);
558 563 }
559 564
560 -@@ -2193,8 +2529,12 @@
565 +@@ -2193,8 +2534,12 @@
561 566 return this.getTeam() != null ? this.getTeam().isAlliedTo(scoreboardteambase) : false;
562 567 }
563 568
564 569 + // CraftBukkit - start
565 570 public void setInvisible(boolean flag) {
566 571 - this.setSharedFlag(5, flag);
567 572 + if (!this.persistentInvisibility) { // Prevent Minecraft from removing our invisibility flag
568 573 + this.setSharedFlag(5, flag);
569 574 + }
570 575 + // CraftBukkit - end
571 576 }
572 577
573 578 public boolean getSharedFlag(int i) {
574 -@@ -2213,7 +2553,7 @@
579 +@@ -2213,7 +2558,7 @@
575 580 }
576 581
577 582 public int getMaxAirSupply() {
578 583 - return 300;
579 584 + return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
580 585 }
581 586
582 587 public int getAirSupply() {
583 -@@ -2221,7 +2561,18 @@
588 +@@ -2221,7 +2566,18 @@
584 589 }
585 590
586 591 public void setAirSupply(int i) {
587 592 - this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, i);
588 593 + // CraftBukkit start
589 594 + EntityAirChangeEvent event = new EntityAirChangeEvent(this.getBukkitEntity(), i);
590 595 + // Suppress during worldgen
591 596 + if (this.valid) {
592 597 + event.getEntity().getServer().getPluginManager().callEvent(event);
593 598 + }
594 599 + if (event.isCancelled() && this.getAirSupply() != i) {
595 600 + this.entityData.markDirty(Entity.DATA_AIR_SUPPLY_ID);
596 601 + return;
597 602 + }
598 603 + this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, event.getAmount());
599 604 + // CraftBukkit end
600 605 }
601 606
602 607 public int getTicksFrozen() {
603 -@@ -2248,11 +2599,41 @@
608 +@@ -2248,11 +2604,41 @@
604 609
605 610 public void thunderHit(WorldServer worldserver, EntityLightning entitylightning) {
606 611 this.setRemainingFireTicks(this.remainingFireTicks + 1);
607 612 + // CraftBukkit start
608 613 + final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity();
609 614 + final org.bukkit.entity.Entity stormBukkitEntity = entitylightning.getBukkitEntity();
610 615 + final PluginManager pluginManager = Bukkit.getPluginManager();
611 616 + // CraftBukkit end
612 617 +
613 618 if (this.remainingFireTicks == 0) {
637 642 + }
638 643 + CraftEventFactory.entityDamage = entitylightning;
639 644 + if (!this.hurt(DamageSource.LIGHTNING_BOLT, 5.0F)) {
640 645 + CraftEventFactory.entityDamage = null;
641 646 + return;
642 647 + }
643 648 + // CraftBukkit end
644 649 }
645 650
646 651 public void onAboveBubbleCol(boolean flag) {
647 -@@ -2417,15 +2798,38 @@
652 +@@ -2417,15 +2803,38 @@
648 653
649 654 @Nullable
650 655 public Entity changeDimension(WorldServer worldserver) {
651 656 + // CraftBukkit start
652 657 + return teleportTo(worldserver, null);
653 658 + }
654 659 +
655 660 + @Nullable
656 661 + public Entity teleportTo(WorldServer worldserver, Position location) {
657 662 + // CraftBukkit end
678 683 + moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot);
679 684 + setDeltaMovement(shapedetectorshape.speed);
680 685 + return this;
681 686 + }
682 687 + this.unRide();
683 688 + // CraftBukkit end
684 689 +
685 690 this.level.getProfiler().popPush("reloading");
686 691 Entity entity = this.getType().create(worldserver);
687 692
688 -@@ -2434,9 +2838,17 @@
693 +@@ -2434,9 +2843,17 @@
689 694 entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot());
690 695 entity.setDeltaMovement(shapedetectorshape.speed);
691 696 worldserver.addDuringTeleport(entity);
692 697 - if (worldserver.dimension() == World.END) {
693 698 - WorldServer.makeObsidianPlatform(worldserver);
694 699 + if (worldserver.getTypeKey() == WorldDimension.END) { // CraftBukkit
695 700 + WorldServer.makeObsidianPlatform(worldserver, this); // CraftBukkit
696 701 }
697 702 + // CraftBukkit start - Forward the CraftEntity to the new entity
698 703 + this.getBukkitEntity().setHandle(entity);
699 704 + entity.bukkitEntity = this.getBukkitEntity();
700 705 +
701 706 + if (this instanceof EntityInsentient) {
702 707 + ((EntityInsentient) this).dropLeash(true, false); // Unleash to prevent duping of leads.
703 708 + }
704 709 + // CraftBukkit end
705 710 }
706 711
707 712 this.removeAfterChangingDimensions();
708 -@@ -2457,20 +2869,34 @@
713 +@@ -2457,20 +2874,34 @@
709 714
710 715 @Nullable
711 716 protected ShapeDetectorShape findDimensionEntryPoint(WorldServer worldserver) {
712 717 - boolean flag = this.level.dimension() == World.END && worldserver.dimension() == World.OVERWORLD;
713 718 - boolean flag1 = worldserver.dimension() == World.END;
714 719 + // CraftBukkit start
715 720 + if (worldserver == null) {
716 721 + return null;
717 722 + }
718 723 + boolean flag = this.level.getTypeKey() == WorldDimension.END && worldserver.getTypeKey() == WorldDimension.OVERWORLD; // fromEndToOverworld
738 743 + final WorldServer worldserverFinal = worldserver = ((CraftWorld) event.getTo().getWorld()).getHandle();
739 744 + worldborder = worldserverFinal.getWorldBorder();
740 745 + blockposition = worldborder.clampToBounds(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ());
741 746
742 747 - return (ShapeDetectorShape) this.getExitPortal(worldserver, blockposition, flag2, worldborder).map((blockutil_rectangle) -> {
743 748 + return (ShapeDetectorShape) this.getExitPortal(worldserver, blockposition, flag2, worldborder, event.getSearchRadius(), event.getCanCreatePortal(), event.getCreationRadius()).map((blockutil_rectangle) -> {
744 749 + // CraftBukkit end
745 750 IBlockData iblockdata = this.level.getBlockState(this.portalEntrancePos);
746 751 EnumDirection.EnumAxis enumdirection_enumaxis;
747 752 Vec3D vec3d;
748 -@@ -2487,8 +2913,8 @@
753 +@@ -2487,8 +2918,8 @@
749 754 vec3d = new Vec3D(0.5D, 0.0D, 0.0D);
750 755 }
751 756
752 757 - return BlockPortalShape.createPortalInfo(worldserver, blockutil_rectangle, enumdirection_enumaxis, vec3d, this, this.getDeltaMovement(), this.getYRot(), this.getXRot());
753 758 - }).orElse((Object) null);
754 759 + return BlockPortalShape.createPortalInfo(worldserverFinal, blockutil_rectangle, enumdirection_enumaxis, vec3d, this, this.getDeltaMovement(), this.getYRot(), this.getXRot(), event); // CraftBukkit
755 760 + }).orElse(null); // CraftBukkit - decompile error
756 761 }
757 762 } else {
758 763 BlockPosition blockposition1;
759 -@@ -2498,8 +2924,14 @@
764 +@@ -2498,8 +2929,14 @@
760 765 } else {
761 766 blockposition1 = worldserver.getHeightmapPos(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSharedSpawnPos());
762 767 }
763 768 + // CraftBukkit start
764 769 + CraftPortalEvent event = callPortalEvent(this, worldserver, new Position(blockposition1.getX() + 0.5D, blockposition1.getY(), blockposition1.getZ() + 0.5D), PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0);
765 770 + if (event == null) {
766 771 + return null;
767 772 + }
768 773
769 774 - return new ShapeDetectorShape(new Vec3D((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D), this.getDeltaMovement(), this.getYRot(), this.getXRot());
770 775 + return new ShapeDetectorShape(new Vec3D(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()), this.getDeltaMovement(), this.getYRot(), this.getXRot(), ((CraftWorld) event.getTo().getWorld()).getHandle(), event);
771 776 + // CraftBukkit end
772 777 }
773 778 }
774 779
775 -@@ -2507,8 +2939,23 @@
780 +@@ -2507,8 +2944,23 @@
776 781 return BlockPortalShape.getRelativePosition(blockutil_rectangle, enumdirection_enumaxis, this.position(), this.getDimensions(this.getPose()));
777 782 }
778 783
779 784 - protected Optional<BlockUtil.Rectangle> getExitPortal(WorldServer worldserver, BlockPosition blockposition, boolean flag, WorldBorder worldborder) {
780 785 - return worldserver.getPortalForcer().findPortalAround(blockposition, flag, worldborder);
781 786 + // CraftBukkit start
782 787 + protected CraftPortalEvent callPortalEvent(Entity entity, WorldServer exitWorldServer, Position exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) {
783 788 + org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity();
784 789 + Location enter = bukkitEntity.getLocation();
785 790 + Location exit = new Location(exitWorldServer.getWorld(), exitPosition.x(), exitPosition.y(), exitPosition.z());
791 796 + }
792 797 + return new CraftPortalEvent(event);
793 798 + }
794 799 +
795 800 + protected Optional<BlockUtil.Rectangle> getExitPortal(WorldServer worldserver, BlockPosition blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) {
796 801 + return worldserver.getPortalForcer().findPortalAround(blockposition, worldborder, searchRadius);
797 802 + // CraftBukkit end
798 803 }
799 804
800 805 public boolean canChangeDimensions() {
801 -@@ -2731,7 +3178,26 @@
806 +@@ -2731,7 +3183,26 @@
802 807 }
803 808
804 809 public final void setBoundingBox(AxisAlignedBB axisalignedbb) {
805 810 - this.bb = axisalignedbb;
806 811 + // CraftBukkit start - block invalid bounding boxes
807 812 + double minX = axisalignedbb.minX,
808 813 + minY = axisalignedbb.minY,
809 814 + minZ = axisalignedbb.minZ,
810 815 + maxX = axisalignedbb.maxX,
811 816 + maxY = axisalignedbb.maxY,
819 824 + if (len > 64) maxY = minY + 64.0;
820 825 +
821 826 + len = axisalignedbb.maxZ - axisalignedbb.minZ;
822 827 + if (len < 0) maxZ = minZ;
823 828 + if (len > 64) maxZ = minZ + 64.0;
824 829 + this.bb = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
825 830 + // CraftBukkit end
826 831 }
827 832
828 833 protected float getEyeHeight(EntityPose entitypose, EntitySize entitysize) {
829 -@@ -3023,6 +3489,11 @@
834 +@@ -3023,6 +3494,11 @@
830 835 vec3d = vec3d.add(vec3d1);
831 836 ++k1;
832 837 }
833 838 + // CraftBukkit start - store last lava contact location
834 839 + if (tagkey == TagsFluid.LAVA) {
835 840 + this.lastLavaContact = blockposition_mutableblockposition.immutable();
836 841 + }
837 842 + // CraftBukkit end
838 843 }
839 844 }
840 845 }

Everything looks good. We'll let you know here if there's anything you should know about.

Add shortcut