Fix MC-136995 - Chunk loading and unloading issue with entities placed in exact positions. (#5160)

This includes three commits from 1.12.x:
c20a5e8805
93b704b459
ee0d43bbde

Scatter gun patches to improve entity tracking and position tracking.
Provided by Aikar through the Paper project, this commit of patches combines the following patches:

fd1bd5223a/Spigot-Server-Patches/0306-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch
fd1bd5223a/Spigot-Server-Patches/0315-Always-process-chunk-registration-after-moving.patch
fd1bd5223a/Spigot-Server-Patches/0335-Ensure-chunks-are-always-loaded-on-hard-position-set.patch
fd1bd5223a/Spigot-Server-Patches/0378-Sync-Player-Position-to-Vehicles.patch

Co-authored-by: Gabriel Harris-Rouquette <github@gabizou.com>
This commit is contained in:
tterrag 2019-01-11 17:16:14 -05:00
parent e98951ee65
commit 958bbf6c9a
7 changed files with 148 additions and 20 deletions

View file

@ -27,7 +27,23 @@
}
public EntityType<?> func_200600_R() {
@@ -845,7 +847,7 @@
@@ -324,6 +326,7 @@
this.field_70165_t = p_70107_1_;
this.field_70163_u = p_70107_3_;
this.field_70161_v = p_70107_5_;
+ if (this.isAddedToWorld() && !this.field_70170_p.field_72995_K) this.field_70170_p.func_72866_a(this, false); // Forge - Process chunk registration after moving.
float f = this.field_70130_N / 2.0F;
float f1 = this.field_70131_O;
this.func_174826_a(new AxisAlignedBB(p_70107_1_ - (double)f, p_70107_3_, p_70107_5_ - (double)f, p_70107_1_ + (double)f, p_70107_3_ + (double)f1, p_70107_5_ + (double)f));
@@ -794,6 +797,7 @@
this.field_70165_t = (axisalignedbb.field_72340_a + axisalignedbb.field_72336_d) / 2.0D;
this.field_70163_u = axisalignedbb.field_72338_b;
this.field_70161_v = (axisalignedbb.field_72339_c + axisalignedbb.field_72334_f) / 2.0D;
+ if (this.isAddedToWorld() && !this.field_70170_p.field_72995_K) this.field_70170_p.func_72866_a(this, false); // Forge - Process chunk registration after moving.
}
protected SoundEvent func_184184_Z() {
@@ -845,7 +849,7 @@
protected void func_180429_a(BlockPos p_180429_1_, IBlockState p_180429_2_) {
if (!p_180429_2_.func_185904_a().func_76224_d()) {
@ -36,7 +52,7 @@
this.func_184185_a(soundtype.func_185844_d(), soundtype.func_185843_a() * 0.15F, soundtype.func_185847_b());
}
}
@@ -1040,6 +1042,7 @@
@@ -1040,6 +1044,7 @@
int k = MathHelper.func_76128_c(this.field_70161_v);
BlockPos blockpos = new BlockPos(i, j, k);
IBlockState iblockstate = this.field_70170_p.func_180495_p(blockpos);
@ -44,7 +60,7 @@
if (iblockstate.func_185901_i() != EnumBlockRenderType.INVISIBLE) {
this.field_70170_p.func_195594_a(new BlockParticleData(Particles.field_197611_d, iblockstate), this.field_70165_t + ((double)this.field_70146_Z.nextFloat() - 0.5D) * (double)this.field_70130_N, this.func_174813_aQ().field_72338_b + 0.1D, this.field_70161_v + ((double)this.field_70146_Z.nextFloat() - 0.5D) * (double)this.field_70130_N, -this.field_70159_w * 4.0D, 1.5D, -this.field_70179_y * 4.0D);
}
@@ -1053,7 +1056,7 @@
@@ -1053,7 +1058,7 @@
double d0 = this.field_70163_u + (double)this.func_70047_e();
BlockPos blockpos = new BlockPos(this.field_70165_t, d0, this.field_70161_v);
IFluidState ifluidstate = this.field_70170_p.func_204610_c(blockpos);
@ -53,7 +69,15 @@
}
}
@@ -1370,6 +1373,7 @@
@@ -1122,6 +1127,7 @@
this.field_70126_B -= 360.0F;
}
+ if (!this.field_70170_p.field_72995_K) this.field_70170_p.func_72964_e((int) Math.floor(this.field_70165_t) >> 4, (int) Math.floor(this.field_70161_v) >> 4); // Forge - ensure target chunk is loaded.
this.func_70107_b(this.field_70165_t, this.field_70163_u, this.field_70161_v);
this.func_70101_b(p_70080_7_, p_70080_8_);
}
@@ -1370,6 +1376,7 @@
if (this.field_184238_ar) {
p_189511_1_.func_74757_a("Glowing", this.field_184238_ar);
}
@ -61,7 +85,7 @@
if (!this.field_184236_aF.isEmpty()) {
NBTTagList nbttaglist = new NBTTagList();
@@ -1381,6 +1385,9 @@
@@ -1381,6 +1388,9 @@
p_189511_1_.func_74782_a("Tags", nbttaglist);
}
@ -71,7 +95,7 @@
this.func_70014_b(p_189511_1_);
if (this.func_184207_aI()) {
NBTTagList nbttaglist1 = new NBTTagList();
@@ -1466,6 +1473,8 @@
@@ -1466,6 +1476,8 @@
this.func_174810_b(p_70020_1_.func_74767_n("Silent"));
this.func_189654_d(p_70020_1_.func_74767_n("NoGravity"));
this.func_184195_f(p_70020_1_.func_74767_n("Glowing"));
@ -80,7 +104,7 @@
if (p_70020_1_.func_150297_b("Tags", 9)) {
this.field_184236_aF.clear();
NBTTagList nbttaglist1 = p_70020_1_.func_150295_c("Tags", 8);
@@ -1546,6 +1555,8 @@
@@ -1546,6 +1558,8 @@
} else {
EntityItem entityitem = new EntityItem(this.field_70170_p, this.field_70165_t, this.field_70163_u + (double)p_70099_2_, this.field_70161_v, p_70099_1_);
entityitem.func_174869_p();
@ -89,7 +113,7 @@
this.field_70170_p.func_72838_d(entityitem);
return entityitem;
}
@@ -1595,6 +1606,7 @@
@@ -1595,6 +1609,7 @@
this.field_70159_w = 0.0D;
this.field_70181_x = 0.0D;
this.field_70179_y = 0.0D;
@ -97,7 +121,7 @@
this.func_70071_h_();
if (this.func_184218_aH()) {
entity.func_184232_k(this);
@@ -1636,6 +1648,7 @@
@@ -1636,6 +1651,7 @@
}
}
@ -105,7 +129,7 @@
if (p_184205_2_ || this.func_184228_n(p_184205_1_) && p_184205_1_.func_184219_q(this)) {
if (this.func_184218_aH()) {
this.func_184210_p();
@@ -1663,6 +1676,7 @@
@@ -1663,6 +1679,7 @@
public void func_184210_p() {
if (this.field_184239_as != null) {
Entity entity = this.field_184239_as;
@ -113,7 +137,7 @@
this.field_184239_as = null;
entity.func_184225_p(this);
}
@@ -1789,10 +1803,15 @@
@@ -1789,10 +1806,15 @@
return !this.func_184188_bt().isEmpty();
}
@ -129,7 +153,7 @@
public boolean func_70093_af() {
return this.func_70083_f(1);
}
@@ -2053,6 +2072,14 @@
@@ -2053,6 +2075,14 @@
@Nullable
public Entity func_184204_a(int p_184204_1_) {
@ -144,7 +168,7 @@
if (!this.field_70170_p.field_72995_K && !this.field_70128_L) {
this.field_70170_p.field_72984_F.func_76320_a("changeDimension");
MinecraftServer minecraftserver = this.func_184102_h();
@@ -2060,7 +2087,7 @@
@@ -2060,7 +2090,7 @@
WorldServer worldserver = minecraftserver.func_71218_a(i);
WorldServer worldserver1 = minecraftserver.func_71218_a(p_184204_1_);
this.field_71093_bK = p_184204_1_;
@ -153,7 +177,7 @@
worldserver1 = minecraftserver.func_200667_a(DimensionType.OVERWORLD);
this.field_71093_bK = 0;
}
@@ -2069,16 +2096,17 @@
@@ -2069,16 +2099,17 @@
this.field_70128_L = false;
this.field_70170_p.field_72984_F.func_76320_a("reposition");
BlockPos blockpos;
@ -176,7 +200,7 @@
d0 = MathHelper.func_151237_a(d0 * 8.0D, worldserver1.func_175723_af().func_177726_b() + 16.0D, worldserver1.func_175723_af().func_177728_d() - 16.0D);
d1 = MathHelper.func_151237_a(d1 * 8.0D, worldserver1.func_175723_af().func_177736_c() + 16.0D, worldserver1.func_175723_af().func_177733_e() - 16.0D);
}
@@ -2087,8 +2115,7 @@
@@ -2087,8 +2118,7 @@
d1 = (double)MathHelper.func_76125_a((int)d1, -29999872, 29999872);
float f = this.field_70177_z;
this.func_70012_b(d0, this.field_70163_u, d1, 90.0F, 0.0F);
@ -186,7 +210,7 @@
blockpos = new BlockPos(this);
}
@@ -2097,7 +2124,7 @@
@@ -2097,7 +2127,7 @@
Entity entity = this.func_200600_R().func_200721_a(worldserver1);
if (entity != null) {
entity.func_180432_n(this);
@ -195,7 +219,7 @@
BlockPos blockpos1 = worldserver1.func_205770_a(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver1.func_175694_M());
entity.func_174828_a(blockpos1, entity.field_70177_z, entity.field_70125_A);
} else {
@@ -2591,4 +2618,32 @@
@@ -2591,4 +2621,49 @@
public double func_212107_bY() {
return this.field_211517_W;
}
@ -227,4 +251,21 @@
+ && (this instanceof EntityPlayer || net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(field_70170_p, this))
+ && this.field_70130_N * this.field_70130_N * this.field_70131_O > 0.512F;
+ }
+
+ /* ================================== Forge Start =====================================*/
+ /**
+ * Internal use for keeping track of entities that are tracked by a world, to
+ * allow guarantees that entity position changes will force a chunk load, avoiding
+ * potential issues with entity desyncing and bad chunk data.
+ */
+ private boolean isAddedToWorld;
+
+ @Override
+ public final boolean isAddedToWorld() { return this.isAddedToWorld; }
+
+ @Override
+ public void onAddedToWorld() { this.isAddedToWorld = true; }
+
+ @Override
+ public void onRemovedFromWorld() { this.isAddedToWorld = false; }
}

View file

@ -0,0 +1,10 @@
--- a/net/minecraft/entity/EntityLeashKnot.java
+++ b/net/minecraft/entity/EntityLeashKnot.java
@@ -38,6 +38,7 @@
this.field_70165_t = (double)this.field_174861_a.func_177958_n() + 0.5D;
this.field_70163_u = (double)this.field_174861_a.func_177956_o() + 0.5D;
this.field_70161_v = (double)this.field_174861_a.func_177952_p() + 0.5D;
+ if (this.isAddedToWorld() && !this.field_70170_p.field_72995_K) this.field_70170_p.func_72866_a(this, false); // Forge - Process chunk registration after moving.
}
public void func_174859_a(EnumFacing p_174859_1_) {

View file

@ -1,6 +1,14 @@
--- a/net/minecraft/entity/monster/EntityShulker.java
+++ b/net/minecraft/entity/monster/EntityShulker.java
@@ -338,6 +338,13 @@
@@ -245,6 +245,7 @@
this.field_70165_t = (double)blockpos.func_177958_n() + 0.5D;
this.field_70163_u = (double)blockpos.func_177956_o();
this.field_70161_v = (double)blockpos.func_177952_p() + 0.5D;
+ if (this.isAddedToWorld() && !this.field_70170_p.field_72995_K) this.field_70170_p.func_72866_a(this, false); // Forge - Process chunk registration after moving.
this.field_70169_q = this.field_70165_t;
this.field_70167_r = this.field_70163_u;
this.field_70166_s = this.field_70161_v;
@@ -338,6 +339,13 @@
}
}

View file

@ -1,6 +1,18 @@
--- a/net/minecraft/network/NetHandlerPlayServer.java
+++ b/net/minecraft/network/NetHandlerPlayServer.java
@@ -1265,5 +1265,7 @@
@@ -327,9 +327,11 @@
}
entity.func_70080_a(d3, d4, d5, f, f1);
+ this.field_147369_b.func_70080_a(d3, d4, d5, this.field_147369_b.field_70177_z, this.field_147369_b.field_70125_A); // Forge - Resync player position on vehicle moving
boolean flag2 = worldserver.func_195586_b(entity, entity.func_174813_aQ().func_186664_h(0.0625D));
if (flag && (flag1 || !flag2)) {
entity.func_70080_a(d0, d1, d2, f, f1);
+ this.field_147369_b.func_70080_a(d0, d1, d2, this.field_147369_b.field_70177_z, this.field_147369_b.field_70125_A); // Forge - Resync player position on vehicle moving
this.field_147371_a.func_179290_a(new SPacketMoveVehicle(entity));
return;
}
@@ -1265,5 +1267,7 @@
}
public void func_147349_a(CPacketCustomPayload p_147349_1_) {

View file

@ -235,6 +235,23 @@
this.func_72964_e(i, j).func_76612_a(p_72838_1_);
this.field_72996_f.add(p_72838_1_);
this.func_72923_a(p_72838_1_);
@@ -766,14 +818,14 @@
for(int i = 0; i < this.field_73021_x.size(); ++i) {
((IWorldEventListener)this.field_73021_x.get(i)).func_72703_a(p_72923_1_);
}
-
+ p_72923_1_.onAddedToWorld();
}
public void func_72847_b(Entity p_72847_1_) {
for(int i = 0; i < this.field_73021_x.size(); ++i) {
((IWorldEventListener)this.field_73021_x.get(i)).func_72709_b(p_72847_1_);
}
-
+ p_72847_1_.onRemovedFromWorld();
}
public void func_72900_e(Entity p_72900_1_) {
@@ -816,52 +868,62 @@
this.field_73021_x.add(p_72954_1_);
}

View file

@ -17,7 +17,23 @@
}
public Chunk(World p_i48703_1_, ChunkPrimer p_i48703_2_, int p_i48703_3_, int p_i48703_4_) {
@@ -1164,4 +1165,30 @@
@@ -593,6 +594,7 @@
p_76612_1_.field_70162_ai = k;
p_76612_1_.field_70164_aj = this.field_76647_h;
this.field_76645_j[k].add(p_76612_1_);
+ this.func_76630_e(); // Forge - ensure chunks are marked to save after an entity add
}
public void func_201607_a(Heightmap.Type p_201607_1_, long[] p_201607_2_) {
@@ -613,6 +615,7 @@
}
this.field_76645_j[p_76608_2_].remove(p_76608_1_);
+ this.func_76630_e(); // Forge - ensure chunks are marked to save after entity removals
}
public boolean func_177444_d(BlockPos p_177444_1_) {
@@ -1164,4 +1167,30 @@
QUEUED,
CHECK;
}

View file

@ -181,4 +181,28 @@ public interface IForgeEntity extends ICapabilitySerializable<NBTTagCompound>
if (forSpawnCount && (this instanceof EntityLiving) && ((EntityLiving)this).isNoDespawnRequired()) return false;
return type.getBaseClass().isAssignableFrom(this.getClass());
}
/**
* Gets whether this entity has been added to a world (for tracking). Specifically
* between the times when an entity is added to a world and the entity being removed
* from the world's tracked lists. See {@link World#onEntityAdded(Entity)} and
* {@link World#onEntityRemoved(Entity)}.
*
* @return True if this entity is being tracked by a world
*/
boolean isAddedToWorld();
/**
* Called after the entity has been added to the world's
* ticking list. Can be overriden, but needs to call super
* to prevent MC-136995.
*/
void onAddedToWorld();
/**
* Called after the entity has been removed to the world's
* ticking list. Can be overriden, but needs to call super
* to prevent MC-136995.
*/
void onRemovedFromWorld();
}